使用@Autowired与AspectJ和Springboot [英] Using @Autowired with AspectJ and Springboot
问题描述
我想将@Autowired注释用于Aspect。我想在我的方面注入一个存储库,但是当我尝试调用我的自动装配类的方法时,会发生NullPointException。
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 NullPointException occurs.
@Aspect
public class AspectSecurity {
@Autowired
private UserRepository userRepository;
@After("execution(public * dash.*.*Controller.*(..))")
public void authentication(JoinPoint jp) throws UnauthorizedException {
System.out.println("SECURITY !");
System.out.println(userRepository.findAll().toString());
}
}
我已经尝试添加 @Component
高于我的方面类但我有同样的错误。
I have already tried to add @Component
above my aspect Class but I have the same error.
如果我不使用方面类但是一个 @Controller
我可以毫无问题地调用我的存储库。
If I don't use an aspect class but a @Controller
I can call my repository without problems.
有些文档讲的是带有xml文件的spring配置但是spring boot我没有这些文件。
Some documentation speak about spring configuration with xml files but with spring boot I don't have these files.
这是我的pom.xml的一部分,它调用了aspectJ插件:
Here a part of my pom.xml wich call the aspectJ plugin:
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>aspectj-maven-plugin</artifactId>
<version>1.4</version>
<configuration>
<showWeaveInfo>true</showWeaveInfo>
<source>1.6</source>
<target>1.6</target>
<Xlint>ignore</Xlint>
<complianceLevel>${compiler.version}</complianceLevel>
<encoding>UTF-8</encoding>
<verbose>false</verbose>
<aspectLibraries>
<aspectLibrary>
<groupId>org.springframework</groupId>
<artifactId>spring-aspects</artifactId>
</aspectLibrary>
</aspectLibraries>
</configuration>
<executions>
<execution>
<goals>
<goal>compile</goal>
<goal>test-compile</goal>
</goals>
</execution>
</executions>
<dependencies>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjrt</artifactId>
<version>${aspectj.version}</version>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjtools</artifactId>
<version>${aspectj.version}</version>
</dependency>
</dependencies>
</plugin>
这是我的申请类:
package dash;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.SpringApplication;
import org.springframework.context.annotation.ComponentScan;
@ComponentScan
@EnableAutoConfiguration
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
这里调用方面的Controller类: / p>
Here the Controller class which the aspect is called:
package dash.user;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import dash.GenericController;
@Controller
@RequestMapping("/user")
public class UserController extends GenericController {
@Autowired
private UserRepository repository;
@RequestMapping("/findAll")
public @ResponseBody User create(
@RequestParam(value="login", required=true) String login,
@RequestParam(value="password", required=true) String password) {
System.out.println(login);
System.out.println(password);
System.out.println("Users found with findAll():");
System.out.println("-------------------------------");
for (User user : repository.findAll()) {
System.out.println(user);
}
return repository.findOne("root");
}
}
注意:我已经尝试添加 @EnableAspectJAutoProxy
在我的应用程序类之上
Note: I have already tried to add @EnableAspectJAutoProxy
above my application class
感谢您的帮助
推荐答案
设置AspectJ编织非常棘手,所以这里可能有些错误。我建议您在 @Aspect
上使用不使用 @Component
(或者至少要确保它从 @ComponentScan
中排除。原因是您必须创建该类型的 @Bean
并显式使用AspectJ所做的相同创建机制,以便Spring和AspectJ同意该值的值。单身实例。我相信正确的方法是在 @Bean
定义中使用 Aspects
中的静态便捷方法。例如
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;
}
此外你需要一个 aop.xml
确保已编译的方面位于AspectJ weaver路径上。这可能就是你在使用Maven AspectJ插件做的事情,但如果我这样做,我可能只是手动创建一个 aop.xml
,使用 @EnableLoadTimeWeaving
,并放弃插件。您可以根据什么有效来决定自己。
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.
如果方面需要拦截在构建应用程序上下文期间使用的内容,也可能存在生命周期问题。您可以通过不依赖 @Bean
方法中的任何拦截来避免这种情况,否则您最终会使用 @DependsOn $ c $玩游戏c>尝试强制创建bean的特定顺序。你的应用程序是否会受到影响,但我不能说。
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.
上一篇(Spring Boot 1.3已废弃):
PREVIOUSLY (obsolete with Spring Boot 1.3):
另一个绊脚石是你正在使用Spring Boot和 @EnableAutoConfiguration
,它明确地打开了 @EnableAspectJAutoProxy
,那个关闭SpringJ方面的AspectJ编织。我实际上不知道这是否是 @EnableAspectJAutoProxy
的预期副作用,但您可以通过从autoconfig中排除它来禁用它,例如
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 {
...
}
NB如果您忘记排除此配置,您可能不会注意到编织已关闭,因为Spring会为您创建代理,并且您的许多方面都会正常工作。
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.
这篇关于使用@Autowired与AspectJ和Springboot的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!