java - AspectJ 和 Spring LTW 在向上转换时不起作用

标签 java spring aspectj load-time-weaving

我使用 AspectJ 设置了 LTW,并且 spring 非常快速且成功。这是设置: beans.xml:

<context:annotation-config />
<aop:aspectj-autoproxy />
<context:spring-configured />
<context:load-time-weaver />
<context:component-scan base-package="com.test.service" />

我的服务将自动连接到一个类:

@Service
public class MyService {
}

父类:

public class Bar {
}

可配置类, Autowiring 服务并扩展 Bar。

@Configurable
public class BarExtended extends Bar{
    @Autowired
    private MyService service;
    public MyService getWeavedInObject(){
        return service;
    }
}

并且只是一个引用父类 Bar 的类:

public class Foo {
    private Bar bar;
    public void setBar(Bar bar) {
        this.bar = bar;
    }
}

以及一个成功的测试用例。它只是创建一个 BarExtended 实例并检查 LTW 是否有效。 Foo 类不执行任何操作。

@Test
public void simple(){
    Foo foo = new Foo();
    BarExtended barExtended = new BarExtended();
    assertNotNull("LTW didn't work.", barExtended.getWeavedInObject());
}

此测试运行绿色。但以下测试失败:

@Test
public void simple(){
    Foo foo = new Foo();
    BarExtended barExtended = new BarExtended();
    foo.setBar(barExtended);
    assertNotNull("LTW didn't work.", barExtended.getWeavedInObject());
}

我只是插入 BarExtended 类设置为 Foo 的行。沮丧使 AspjectJ 无法工作。

顺便说一句,当我更改 Foo 类以使用 BarExtended 类时(因此不需要向上转换):

public class Foo {
    private BarExtended bar;
    public void setBar(BarExtended bar) {
        this.bar = bar;
    }
}

上面的测试是有效的。有谁知道为什么当可配置对象向上转型时 AspjectJ 的行为如此奇怪?

编辑:以下也失败:

@Test
public void simple() {
    Foo foo = new Foo();
    BarExtended barExtended = new BarExtended();
    Bar bar = (Bar) new BarExtended();
    foo.setBar(bar);
    assertNotNull("LTW didn't work.", barExtended.getWeavedInObject());
}

另一个 BarExtended 对象被设置为 Foo,并且第一个 barExtended 对象被 AspectJ 忽略。 但是使用反射来实例化 BarExtended 是有效的:

@Test
public void simple() throws InstantiationException, IllegalAccessException{
    Foo foo = new Foo();
    Bar barExtended = (Bar) BarExtended.class.newInstance();
    foo.setBar(barExtended);
    assertNotNull("LTW didn't work.", ((BarExtended)barExtended).getWeavedInObject());
}

很奇怪,不是吗?

非常感谢

问候,

安德烈亚斯

最佳答案

我过去遇到过麻烦,我认为 LTW 已配置,但事实并非如此,原因我不太确定。因此,我现在在配置中 100% 明确地对您的配置文件进行以下更改,看看是否一切正常。

  <context:load-time-weaver aspectj-weaving="on" />

删除<aop:aspectj-autoproxy />从您的配置来看,您不需要它,因为 LTW 确实正在运行。

当您运行 JUnit 测试时,您是否传入 vm 参数来告诉 JUnit LTW 代理在哪里?如果没有,那么 LTW 就没有运行。

以下是文档中关于 <context:load-time-weaver /> 的内容

Activates a Spring LoadTimeWeaver for this application context, available as a bean with the name "loadTimeWeaver". Any bean that implements the LoadTimeWeaverAware interface will then receive the LoadTimeWeaver reference automatically; for example, Spring's JPA bootstrap support. The default weaver is determined automatically. As of Spring 2.5: detecting Sun's GlassFish, Oracle's OC4J, Spring's VM agent and any ClassLoader supported by Spring's ReflectiveLoadTimeWeaver (for example, the TomcatInstrumentableClassLoader). The activation of AspectJ load-time weaving is specified via a simple flag (the 'aspectj-weaving' attribute), with the AspectJ class transformer registered through Spring's LoadTimeWeaver. AspectJ weaving will be activated by default if a "META-INF/aop.xml" resource is present in the classpath. This also activates the current application context for applying dependency injection to non-managed classes that are instantiated outside of the Spring bean factory (typically classes annotated with the @Configurable annotation). This will only happen if the AnnotationBeanConfigurerAspect is on the classpath (i.e. spring-aspects.jar), effectively activating "spring-configured" by default. See Javadoc for org.springframework.context.annotation.EnableLoadTimeWeaving for information on code-based alternatives to bootstrapping load-time weaving support.

总而言之,<context:load-time-weaver />似乎实际上是定义一个 id 为 loadTimeWeaver 的 bean 并扫描类路径寻找像 aop.xml 这样的特殊文件来确定是否应该打开aspectJ。为了确保aspectJ已打开,您确实需要设置aspectj-weaving="on"这样,如果它因某种原因无法打开方面J,它将在启动时失败,这正是您想要的。在我的网络应用程序中,我有一个在网络应用程序启动时运行的测试,以确保aspectJ正在运行,如果没有运行,它就会提示。

关于java - AspectJ 和 Spring LTW 在向上转换时不起作用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9422200/

相关文章:

java - Spring Maven DispatcherServlet noHandlerFound

java - 在 Linux 系统上安装 Spring Boot 应用程序

java - 当 maven build 运行测试时,Spring boot 项目抛出 *$$EnhancerBySpringCGLIB is not an @AspectJ Aspect

java - 我应该学习Scala吗?

java - "Failed to instantiate WebApplicationInitializer class"如何解决

java - Spring Boot 应用程序在外部 TOMCAT 中启动后立即关闭

maven - 在 Maven 项目中放置方面的地方

java - 程序在 Thread.sleep() 期间和计时器卡住

java - @Singleton、@Startup、@PostConstruct 不适用于 EJB3.1 和 Glassfishv3.0.1

java - Spring AOP 关于注解 Controller 的建议