在@Aspect中使用Spring @Profile [英] using Spring @Profile in @Aspect

查看:260
本文介绍了在@Aspect中使用Spring @Profile的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

所以我想要的是在配置文件处于活动状态时将特定的Spring Aspect应用于我的班级,但是我找不到解决方案,我尝试使用

我的观点:

//TESTING IN ALL THIS WAYS BUT NOTHING
//@Component
//@Profile("asdasd")
@Configurable
//@Configuration
@Aspect
public class TestAspect{
    public static final Logger LOGGER = LogManager.getLogger(testControllerEX.class);

    @Autowired
    private testService testService;

    public TestAspect() {
        LOGGER.info("TEST ASPECT INITIALIZED");
    }

    /*@Before("execution(* demo.testControllerEX.test(*)) && args(param)")
    public void beforeSampleMethod(Object param) {
        LOGGER.info("ASPECT" + param.getClass());
    }*/

    @Before("execution(demo.testControllerEX.new())")
    public void constructor(JoinPoint point) {
        LOGGER.info("ASPECT CONSTRUCTOR" + point.getThis().getClass().getAnnotation(Controller.class));
        LOGGER.info("SERVICE" + testService);
    }

    @Around("execution(* demo.testControllerEX.testPrevent(*)) && args(param)")
    public String prevent(ProceedingJoinPoint point, String param) throws Throwable{
        //LOGGER.info("ASPECT AROUND" + param);
        LOGGER.info("ASPECT AROUND " + testService);
        String result = (String)point.proceed();
        return result;
    }

    /*@DeclareParents(value="(demo.testControllerEX)",defaultImpl=testControllersssImpl.class)
    private ITestControllerEX itestControllerEX;*/
}

最后,我尝试将我的方面应用于控制器的构造函数,它可以工作,但是我需要在配置文件处于活动状态时应用,而我发现的另一个错误是我的testService在构造函数切入点之后初始化了null,但是在方法testPrevent可以正常工作的情况下,服务显然是在初始化之前完成的,我可以接受实现所需功能的其他形式

编辑

我知道我的testService是在构造函数切入点之后加载的,但仍为null:

@Configuration
    @ComponentScan(basePackages= {
            "demo",
            "demo.aspect"
    })
    @EnableAutoConfiguration(exclude=AopAutoConfiguration.class)
    @EnableAspectJAutoProxy(proxyTargetClass=true)
    public class Application {

    @Autowired
    private testService testService;
    ...

解决方案

不幸的是,对于您来说,实现您想做的事情是不可能的.使用纯Spring AOP无法将建议应用于构造函数调用,因此您唯一的方法是将LTW(加载时间编织)与AspectJ一起使用.

链接到Spring AOP参考(Spring AOP功能和目标)

Spring AOP当前仅支持方法执行连接点(建议在Spring Bean上执行方法).

您可能已经了解了有关LTW的信息,以拦截您的构造函数调用,但您的Aspect将不是Spring Bean,因此您将无法注入TestService.以同样的方式,您尝试将Profile设置为非Spring Bean(因为您的建议将不会由Spring管理),因此您将无法根据其活动的Spring配置文件将其激活.

顺便说一句,完全支持将配置文件与Spring AOP结合使用,只要您继续使用Spring管理的方面.

了解更多关于您想做什么的事情可能会很有趣,也许您尝试做的是无需使用构造函数调用拦截器就可以做到的!

So what i want is to apply an specific Spring Aspect to my classes when an profile is active, but i can't find a solution, i try the way proposed in http://city81.blogspot.com/2012/05/using-spring-profile-with.html but is quite old and don't work in my case, i have a Spring Started project for testing and i do the following based on the link:

configuring the Application:

@Configuration
@ComponentScan(basePackages= {
        "demo",
        "demo.aspect"
})
@EnableAutoConfiguration(exclude=AopAutoConfiguration.class)
@EnableAspectJAutoProxy(proxyTargetClass=true)
public class Application {

    @Bean
    @Profile("asdasd") //testing profile to bean level
    public TestAspect testAspect() { //this allow @autowired in my aspect
        TestAspect aspect = Aspects.aspectOf(TestAspect.class);
        return aspect;
    }

    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }
}

My Aspect:

//TESTING IN ALL THIS WAYS BUT NOTHING
//@Component
//@Profile("asdasd")
@Configurable
//@Configuration
@Aspect
public class TestAspect{
    public static final Logger LOGGER = LogManager.getLogger(testControllerEX.class);

    @Autowired
    private testService testService;

    public TestAspect() {
        LOGGER.info("TEST ASPECT INITIALIZED");
    }

    /*@Before("execution(* demo.testControllerEX.test(*)) && args(param)")
    public void beforeSampleMethod(Object param) {
        LOGGER.info("ASPECT" + param.getClass());
    }*/

    @Before("execution(demo.testControllerEX.new())")
    public void constructor(JoinPoint point) {
        LOGGER.info("ASPECT CONSTRUCTOR" + point.getThis().getClass().getAnnotation(Controller.class));
        LOGGER.info("SERVICE" + testService);
    }

    @Around("execution(* demo.testControllerEX.testPrevent(*)) && args(param)")
    public String prevent(ProceedingJoinPoint point, String param) throws Throwable{
        //LOGGER.info("ASPECT AROUND" + param);
        LOGGER.info("ASPECT AROUND " + testService);
        String result = (String)point.proceed();
        return result;
    }

    /*@DeclareParents(value="(demo.testControllerEX)",defaultImpl=testControllersssImpl.class)
    private ITestControllerEX itestControllerEX;*/
}

Finally i'm try to apply my aspect to the constructor of a controller, it works but i need to applying when a profile is active, and another bug i find is that my testService is initialized after the constructor pointcut so it is null, but in the method testPrevent works obviously the service is initialized before, i can accept other form that accomplished what i want

EDIT

i got that my testService is loaded befome my constructor pointcut but remains null:

@Configuration
    @ComponentScan(basePackages= {
            "demo",
            "demo.aspect"
    })
    @EnableAutoConfiguration(exclude=AopAutoConfiguration.class)
    @EnableAspectJAutoProxy(proxyTargetClass=true)
    public class Application {

    @Autowired
    private testService testService;
    ...

解决方案

Unfortunately for you it's not going to be possible to achieve what you want to do. With pure Spring AOP there is no way to apply advice to constructor call so your only way is to use LTW (Load Time Weaving) with AspectJ.

Link to Spring AOP reference (Spring AOP capabilities and goals)

Spring AOP currently supports only method execution join points (advising the execution of methods on Spring beans).

You may have already read about LTW to intercept your constructor call but your Aspect will not be a Spring Bean so you won't be able to inject your TestService. In the same way you are trying to set a Profile to a non Spring Bean (as your advice is not going to be managed by Spring) so you won't be able make it active depending on you active spring profiles.

By the way, using profiles in conjunction with Spring AOP is totally supported as long as you stay with spring managed aspects.

It would be interesting to know more about what you want to do, may be what you are trying to do is doable without using constructor call interceptor !

这篇关于在@Aspect中使用Spring @Profile的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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