【问题标题】:AspectJ + @ConfigurableAspectJ + @Configurable
【发布时间】:2015-10-26 21:17:45
【问题描述】:

尝试在 Spring 应用程序中同时使用 AspectJ 和 @Configurable

  • 如果我在一个类上加载带有@Component 注释的Spring,AspectJ 包装器会工作并包装所有目标方法,而@Autowired 注释会导致注入依赖项。但是该类无法在运行时使用 new 关键字进行实例化,并且无法注入依赖项。
  • 如果我在没有 AspectJ bean 的情况下加载 @Configurable 类,则所有依赖项都会正确注入到 new,但没有任何方法通过 AspectJ 代理。

我怎样才能做到这两点?

这是我的代码。配置:

@Configuration
@ComponentScan(basePackages="com.example")
@EnableSpringConfigured
@EnableAspectJAutoProxy
@EnableLoadTimeWeaving
public class TestCoreConfig {

    @Bean
    public SecurityAspect generateSecurityAspect(){
        return new SecurityAspect();
    }


    @Bean
    public SampleSecuredClass createSampleClass(){
        return new SampleSecuredClass();
    }
}

方面:

@Aspect
public class SecurityAspect {

    @Pointcut("execution(public * *(..))")
    public void publicMethod() {}


    @Around("publicMethod()")
    public boolean test (ProceedingJoinPoint joinPoint) throws Throwable {
        System.out.println("Here!");
        joinPoint.proceed();
        return true;    
    }

}

示例类:

//@Configurable
@Component
public class SampleSecuredClass {

    @Autowired
    public SecurityService securityService;

    public boolean hasSecurityService(){
        return securityService != null;
    }

    public boolean returnFalse(){
        return false;
    }
}

还有单元测试:

@ContextConfiguration(classes={TestCoreConfig.class})
@RunWith(SpringJUnit4ClassRunner.class)
public class SecurityAspectComponentTest {

    @Autowired
    private SampleSecuredClass sampleSecuredClass;

    @Test
    public void testSecurityRoles(){
        //SampleSecuredClass sampleSecuredClass = new SampleSecuredClass();

        assertTrue("We need to ensure the the @Configurable annotation injected the services correctly", sampleSecuredClass.hasSecurityService());

        assertTrue("We need to ensure the the method has been overwritten", sampleSecuredClass.returnFalse());
    }

}
  • 如果我摆脱了TestCoreConfig 中的bean,并使用new 在测试中创建SampleSecuredClass 的实例,并将其注释更改为@Configurable,则注入服务,但方面不是已应用。
  • 如果我在此处按原样运行(通过将SampleSecuredClass 作为 bean 注入),则切面工作并注入服务,但随后必须在框架启动时创建所有对象。我想使用@Configurable 注释。
  • 如果同时使用 @Configurable 注释和 Aspect,则会收到 illegal type in constant pool 错误并且上下文不会启动。

其他信息。

  • 我尝试了几种不同的 java 代理——包括 spring 检测和 aspectjwrapper。没有变化。

  • 如果我包含 aop.xml 文件,则方面有效,但 @Configurable 无效。

【问题讨论】:

  • hmmm 将值设置为 true:没有变化
  • 抱歉,没有通读整个问题,但@Configurable 中有一个autowire() 属性,默认为NO。您是否尝试将其设置为BY_TYPEBY_VALUE
  • 抱歉,您回复时我正试图编辑评论。忘记评论。
  • 是否可以选择使用工厂方法(可能是静态的)而不是 new 来创建新对象?这意味着obj = Factory.createObj(); 而不是obj = new SampleSecuredClass ();
  • 您是否尝试过使用 aspectj 编译器进行编译时编织?您可以将其添加到您的 maven 配置中,也可以简单地将 IDE 编译器配置为使用 ajc

标签: java spring dependency-injection aop aspectj


【解决方案1】:

这似乎是对 docs 等待发生的深入探讨之一 :)

首先,我会为 org.springframework 启用调试日志记录,因为这肯定会提供一些有意义的洞察力来了解 Spring 做什么和什么时候做......

话虽如此,我相信您的问题存在于 Spring 上下文生命周期的迷雾中,所以我会仔细检查文档,尤其是围绕

  1. 手动指定bean依赖于配置方面depends-on="org.springframework.beans.factory.aspectj.AnnotationBeanConfigurerAspect"

  2. ...或@Configurable(preConstruction=true)周围的注释

如果您希望在构造函数主体执行之前注入依赖项

  1. ...或@Configurable(autowire=Autowire.BY_NAME,dependencyCheck=true)

最后,您可以使用dependencyCheck属性为新创建和配置的对象中的对象引用启用Spring依赖检查。

仔细阅读文档,看看这些命中是否适用以及如何适用,请告诉我们您找到的解决方案。它绝对应该是一本非常有趣的读物。

【讨论】:

    猜你喜欢
    • 2017-02-15
    • 2010-10-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-02-08
    相关资源
    最近更新 更多