Using @Autowired with AspectJ and Springboot

前端 未结 2 1654
眼角桃花
眼角桃花 2021-01-17 16:05

I want to use @Autowired annotation into an "Aspect". I want to inject a repository in my aspect but when I try to call a method of my autowired class a NullPointE

相关标签:
2条回答
  • 2021-01-17 16:56

    Here is my configuration:

    @Component
    @Aspect
    public class WebControllerAop {
        @Autowired
        private PersonService personService;
        //匹配com.zkn.learnspringboot.web.controller包及其子包下的所有类的所有方法
        @Pointcut("execution(* com.zkn.learnspringboot.web.controller..*.*(..))")
        public void executeService(){
    
        }
    }
    
    @RestController
    @EnableAutoConfiguration
    @ComponentScan
    public class FirstExample {
        public static void main(String[] args) {
            SpringApplication.run(FirstExample.class, args);
        }
    }
    
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>1.4.0.RELEASE</version>
    </parent>
    
    <dependency>
          <groupId>org.springframework.boot</groupId>
          <artifactId>spring-boot-starter-aop</artifactId>
      </dependency>
    

    It can work well.

    0 讨论(0)
  • 2021-01-17 16:59

    It's quite tricky to set up AspectJ weaving so a few things could be wrong here. I would suggest that you do not use @Component on your @Aspect (or at least make sure it is excluded from a @ComponentScan). The reason for that is you have to create a @Bean of that type and explicitly use the same creation mechanism that AspectJ does, so that Spring and AspectJ agree on the value of the singleton instance. I believe the correct way to do that is to use the static convenience methods in Aspects in your @Bean definition. E.g.

    @Bean
    public AspectSecurity interceptor() {
        AspectSecurity aspect = Aspects.aspectOf(AspectSecurity.class);
        // ... inject dependencies here if not using @Autowired
        return aspect;
    }
    

    In addition you will need an aop.xml to ensure that the compiled aspect is on the AspectJ weaver path. It could be that is what you are doing with the Maven AspectJ plugin, but if it was me doing this I would probably just create an aop.xml manually, use @EnableLoadTimeWeaving, and ditch the plugin. You can probably decide yourself based on what works.

    There can also be lifecycle issues if the aspect needs to intercept something that is used during the construction of the application context. You can maybe avoid that by not relying on any interception in @Bean methods, or else you end up playing games with @DependsOn to try and force a particular order of bean creation. Whether your app suffers from that yet I can't say.

    PREVIOUSLY (obsolete with Spring Boot 1.3):

    Another stumbling block is that you are using Spring Boot and @EnableAutoConfiguration which explicitly switches on @EnableAspectJAutoProxy, and that switches off the AspectJ weaving for the Spring bean aspects. I actually have no idea if that is an intended side effect of @EnableAspectJAutoProxy, but you can disable it by excluding it from the autoconfig, e.g.

    @ComponentScan
    @EnableAutoConfiguration(exclude=AopAutoConfiguration.class)
    public class Application {    
        ...
    }
    

    N.B. you might not notice that weaving is switched off if you forget to exclude this config because Spring will create proxies for you and many of your aspects will just work anyway.

    0 讨论(0)
提交回复
热议问题