我想在@Aspect中使用@Autowired注释。我想在我的方面注入存储库,但是当我尝试调用自动装配类的方法时,会发生NullPointException。
@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在我的方面类之上添加内容,但是我有同样的错误。
@Component
如果我不使用方面类,而是使用方面类,则@Controller可以毫无问题地调用我的存储库。
@Controller
一些文档谈到了带有xml文件的spring配置,但是对于spring boot,我没有这些文件。
这是我的pom.xml的一部分,它称为AspectJ插件:
<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>
这是我的Application类:
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类:
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在我的应用程序类之上添加
@EnableAspectJAutoProxy
谢谢你的帮助
设置AspectJ编织是非常棘手的,所以这里有些事情可能是错误的。我建议你 不 使用@Component你的@Aspect(或至少确保它是从排除@ComponentScan)。这样做的原因是您必须创建@Bean该类型的,并显式地使用与AspectJ相同的创建机制,以便Spring和AspectJ在单例实例的值上达成一致。我相信正确的方法是Aspects在@Bean定义中使用静态便利方法。例如
@Aspect
@ComponentScan
@Bean
Aspects
@Bean public AspectSecurity interceptor() { AspectSecurity aspect = Aspects.aspectOf(AspectSecurity.class); // ... inject dependencies here if not using @Autowired return aspect; }
另外,您将需要aop.xml确保编译的方面位于AspectJ韦弗路径上。可能就是您使用Maven AspectJ插件所做的事情,但是如果是我这样做,则可能只需要aop.xml手动创建,使用@EnableLoadTimeWeaving并抛弃该插件即可。您可能可以根据有效的方法来决定自己。
aop.xml
@EnableLoadTimeWeaving
如果方面需要拦截在构建应用程序上下文期间使用的内容,则还可能存在生命周期问题。您可以通过不依赖任何@Bean方法上的拦截来避免这种情况,否则您最终@DependsOn会尝试强制执行特定的Bean创建顺序而玩游戏。您的应用是否受此困扰,我无法确定。
@DependsOn
以前(在Spring Boot 1.3中已作废):
另一个绊脚石是您正在使用Spring Boot并且@EnableAutoConfiguration显式打开@EnableAspectJAutoProxy,并且关闭了Spring bean方面的AspectJ编织。我实际上不知道这是否是的预期副作用@EnableAspectJAutoProxy,但是您可以通过将其从自动配置中排除来禁用它,例如
@EnableAutoConfiguration
@ComponentScan @EnableAutoConfiguration(exclude=AopAutoConfiguration.class) public class Application { ... }
注意,如果您忘记排除此配置,您可能不会注意到编织已关闭,因为Spring会为您创建代理,并且您的许多方面仍然可以正常工作。