使用@Autowired与AspectJ和Springboot

max*_*lay 10 java spring aspectj autowired spring-boot

我想将@Autowired注释用于"Aspect".我想在我的方面注入一个存储库但是当我尝试调用我的自动连接类的方法时,会发生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());

   }
}
Run Code Online (Sandbox Code Playgroud)

我已经尝试@Component在我的方面类上面添加,但我有同样的错误.

如果我不使用方面类,但@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>
Run Code Online (Sandbox Code Playgroud)

这是我的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);
    }
}
Run Code Online (Sandbox Code Playgroud)

这里调用方面的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");
    }
}
Run Code Online (Sandbox Code Playgroud)

注意:我已经尝试@EnableAspectJAutoProxy在我的应用程序类上面添加

谢谢你的帮助

Dav*_*yer 16

设置AspectJ编织非常棘手,所以这里可能有些错误.我建议你使用@Component你的@Aspect(或至少要确保它是从一个除外@ComponentScan).原因是您必须创建@Bean该类型并显式使用AspectJ所执行的相同创建机制,以便Spring和AspectJ同意单例实例的值.我相信正确的方法是Aspects@Bean定义中使用静态便捷方法.例如

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

此外,您还需要aop.xml确保已编译的方面位于AspectJ weaver路径上.这可能是你正在使用Maven AspectJ插件做的事情,但如果是我这样做,我可能只是创建一个aop.xml手动,使用@EnableLoadTimeWeaving和放弃插件.您可以根据有效的方法来决定自己.

如果方面需要拦截在构建应用程序上下文期间使用的某些内容,则还可能存在生命周期问题.您可以通过不依赖于@Bean方法中的任何拦截来避免这种情况,否则您最终会玩游戏@DependsOn以尝试强制创建特定的bean顺序.你的应用程序是否受到影响但我不能说.

以前(使用Spring Boot 1.3过时):

另一个绊脚石是你正在使用Spring Boot并@EnableAutoConfiguration明确地打开@EnableAspectJAutoProxy,并关闭了SpringJ方面的AspectJ编织.我实际上不知道这是否是预期的副作用@EnableAspectJAutoProxy,但您可以通过从autoconfig中排除它来禁用它,例如

@ComponentScan
@EnableAutoConfiguration(exclude=AopAutoConfiguration.class)
public class Application {    
    ...
}
Run Code Online (Sandbox Code Playgroud)

注意,如果您忘记排除此配置,您可能不会注意到编织已关闭,因为Spring会为您创建代理,并且您的许多方面都会正常工作.