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
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.
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.