使用@Autowired与AspectJ和Spring Boot

时间:2014-01-25 13:09:24

标签: 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());

   }
}

我已经尝试将@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>

这是我的应用类:

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

感谢您的帮助

2 个答案:

答案 0 :(得分:16)

设置AspectJ编织非常棘手,所以这里可能有些错误。我建议您在@Component使用@Aspect(或至少确保将其排除在@ComponentScan之外)。原因是您必须创建该类型的@Bean并显式使用AspectJ所执行的相同创建机制,以便Spring和AspectJ同意单例实例的值。我相信正确的方法是在Aspects定义中使用@Bean中的静态便捷方法。 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,并放弃插件。你可以根据什么有效来决定自己。

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

以前(使用Spring Boot 1.3已废弃):

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

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

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

答案 1 :(得分:-1)

这是我的配置:

@Component
@Aspect
public class WebControllerAop {
    @Autowired
    private PersonService personService;
    //匹配com.zkn.learnspringboot.web.controller包及其子包下的所有类的所有方法
    @Pointcut("execution(* com.zkn.learnspringboot.web.controller..*.*(..))")
    public void executeService(){

    }
}

@RestController
@EnableAutoConfiguration
@ComponentScan
public class FirstExample {
    public static void main(String[] args) {
        SpringApplication.run(FirstExample.class, args);
    }
}

<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>1.4.0.RELEASE</version>
</parent>

<dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-aop</artifactId>
  </dependency>

它可以很好地工作。