一尘不染

在AspectJ和Springboot中使用@Autowired

spring-boot

我想在@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在我的方面类之上添加内容,但是我有同样的错误。

如果我不使用方面类,而是使用方面类,则@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在我的应用程序类之上添加

谢谢你的帮助


阅读 335

收藏
2020-05-30

共1个答案

一尘不染

设置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;
}

另外,您将需要aop.xml确保编译的方面位于AspectJ韦弗路径上。可能就是您使用Maven
AspectJ插件所做的事情,但是如果是我这样做,则可能只需要aop.xml手动创建,使用@EnableLoadTimeWeaving并抛弃该插件即可。您可能可以根据有效的方法来决定自己。

如果方面需要拦截在构建应用程序上下文期间使用的内容,则还可能存在生命周期问题。您可以通过不依赖任何@Bean方法上的拦截来避免这种情况,否则您最终@DependsOn会尝试强制执行特定的Bean创建顺序而玩游戏。您的应用是否受此困扰,我无法确定。

以前(在Spring Boot 1.3中已作废):

另一个绊脚石是您正在使用Spring
Boot并且@EnableAutoConfiguration显式打开@EnableAspectJAutoProxy,并且关闭了Spring
bean方面的AspectJ编织。我实际上不知道这是否是的预期副作用@EnableAspectJAutoProxy,但是您可以通过将其从自动配置中排除来禁用它,例如

@ComponentScan
@EnableAutoConfiguration(exclude=AopAutoConfiguration.class)
public class Application {    
    ...
}

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

2020-05-30