使用@Autowired与AspectJ和Springboot [英] Using @Autowired with AspectJ and Springboot

查看:113
本文介绍了使用@Autowired与AspectJ和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 尝试强制创建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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆