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

时间:2012-02-23 22:12:28

标签: java spring aspectj load-time-weaving

我使用AspectJ设置LTW,并且非常快速且成功。这是设置: 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 {
}

可配置类,自动装配服务并扩展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无法正常工作。

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

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

以上测试将有效。当有可配置的对象被提升时,有没有人知道为什么AspjectJ表现得如此奇怪?

编辑:Follwing也失败了:

@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,AspectJ忽略第一个barExtended对象。 但是使用反射来实例化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());
}

奇怪,不是吗?

非常感谢

此致

安德烈亚斯

2 个答案:

答案 0 :(得分:1)

过去我曾经遇到麻烦,我认为LTW已经配置,但这并不是因为我不太确定。所以我现在100%明确在我的配置中对配置文件进行以下更改,看看它是否全部有用。

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

从您的配置中删除<aop:aspectj-autoproxy />,您不需要LTW真正运行LTW。

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

以下是文档对<context:load-time-weaver />

的评论
  

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

所以总结一下,放置<context:load-time-weaver />似乎真的是定义一个id为loadTimeWeaver的bean,并扫描类路径,寻找像aop.xml这样的特殊文件,以确定是否应该打开aspectJ。为了确保开启aspectJ肯定你真的需要设置aspectj-weaving="on"如果它无法打开aspectJ,无论出于何种原因它将在启动时失败,这正是你想要的。在我的网络应用程序中,我有一个测试,我在Web应用程序启动时运行,以确保aspectJ正在运行,如果不是它抱怨。

答案 1 :(得分:1)

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

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

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

JUNIT EXAMPLE

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

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

以上两个示例在WEBSPHERE ENV中工作。

你有没有解决这个问题?