【问题标题】:AspectJ and Spring LTW doesn't work when upcastingAspectJ 和 Spring LTW 在向上转换时不起作用
【发布时间】:2012-02-23 22:12:27
【问题描述】:

我用 AspectJ 设置了 LTW,并且很快就成功了。这是设置: bean.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 {
}

可配置类,自动装配服务并扩展 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 在向上转换可配置对象时表现得如此奇怪?

编辑:Folwing 也失败了:

@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());
}

很奇怪,不是吗?

非常感谢

问候,

安德烈亚斯

【问题讨论】:

  • 你使用什么版本的 Java、AspectJ?
  • 我使用 Java 1.6、aspectj 1.6.12 和 Spring 3.1.0.RELEASE。
  • 该死的,我也遇到了这个问题。我刚刚在他们的 JIRA 中提出了这个问题以及可重现的测试用例:jira.spring.io/browse/SPR-12901
  • 你解决过这个问题吗?我的日程很紧

标签: java spring aspectj load-time-weaving


【解决方案1】:

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

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

从您的配置中删除&lt;aop:aspectj-autoproxy /&gt;,您不需要它,您已经真正运行了 LTW。

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

这是文档对&lt;context:load-time-weaver /&gt; 的评价

为此应用程序上下文激活 Spring LoadTimeWeaver,可作为具有名称的 bean “加载时间韦弗”。任何实现 LoadTimeWeaverAware 接口的 bean 都会收到 LoadTimeWeaver 自动引用;例如,Spring 的 JPA 引导程序支持。默认编织器是 自动确定。从 Spring 2.5 开始:检测 Sun 的 GlassFish、Oracle 的 OC4J、Spring 的 VM 代理和 Spring 的 ReflectiveLoadTimeWeaver 支持的任何 ClassLoader(例如, TomcatInstrumentableClassLoader)。 AspectJ 加载时编织的激活是通过一个简单的 标志('aspectj-weaving' 属性),通过 Spring 注册的 AspectJ 类转换器 加载时间韦弗。如果存在“META-INF/aop.xml”资源,则默认情况下将激活 AspectJ 编织 在类路径中。这也激活了当前应用程序上下文以将依赖注入应用到 在 Spring bean 工厂之外实例化的非托管类(通常是带注释的类 带有@Configurable 注释)。仅当 AnnotationBeanConfigurerAspect 位于 类路径(即 spring-aspects.jar),默认情况下有效地激活“spring-configured”。请参阅 Javadoc org.springframework.context.annotation.EnableLoadTimeWeaving 获取基于代码的信息 引导加载时编织支持的替代方案。

所以总而言之,&lt;context:load-time-weaver /&gt; 似乎真的是关于定义一个 id 为 loadTimeWeaver 的 bean 并扫描类路径以查找特殊文件(如 aop.xml)以确定是否应该打开 aspectJ。为了确保aspectJ已经打开,你真的需要设置aspectj-weaving="on",如果它不能打开aspectJ,无论出于什么原因它都会在启动时失败,这正是你想要的。在我的网络应用程序中,我有一个在网络应用程序启动时运行的测试,以确保 aspectJ 正在运行,如果不是,它会抱怨。

【讨论】:

  • 感谢您的长回答。设置 explizit aspetj-weaving="on" 没有帮助。我也玩过 aop.xml:没有成功。这似乎真的是一个向上转换的问题。
【解决方案2】:

我在使用标准弹簧仪器设置的 JUnit 设置中遇到了同样的问题。 当使用 WebSphereLoadTimeWeaver 在 WebSphere 容器中运行相同的代码时,没问题!

我的 openJPA 代码增强了构建时间。 我的@Configurable 和其他一些方面都是加载时间完成的。

我最好的猜测是,openjpa 继承策略的增强稍后会与 LTW 发生冲突,因此结合 @Configuarable 会给我一些空指针问题。

JUNIT 示例

AbstactWhatEver x = new Concrete(); // @Configurable 正在工作

AbstactWhatEver x = new Concrete(); x.callAnyMethod(); // 在 openjpa 抽象上给出 LTW 问题,因此 @Configurable 不起作用

以上两个示例都适用于 WEBSPHERE ENV。

你解决过这个问题吗?

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-01-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-02-10
    • 1970-01-01
    相关资源
    最近更新 更多