为什么Spring AOP不会在运行时编织外部jar?

我有一个基于Spring 3的java应用程序构建。这个项目有另一个jar作为依赖。

此依赖项包含@org.aspectj.lang.annotation.Aspect类(例如, com.aspectprovider.aspects.MyAspect )。 有一个@Before建议从实现接口Foo类编织一个方法。 就像是:

 @Before("execution(* com.project.Foo.save(..))") 

Foo接口可以在“项目”内或在另一个jar中。 这个例子没关系。

我的项目包含实现Foo类。 当然,那些是我希望它编织的类。

My Spring应用程序上下文配置文件( applicationContext.xml )包含以下行:

  

我还将方面声明为bean,并注入一些属性:

    

通过日志记录,我可以看到MyAspect已实例化并且属性已注入。 但方法保存不被截获。 这就是问题。

如果我将方面类从jar复制到具有Spring的应用程序,它可以工作。 当这些方面包含在外部jar中时,方法save不会被截获。 有什么线索吗?

编辑:我如何调用Foo的保存方法:

 //in a JSF managed bean @Inject private Foo myFoo; //there's a implementation of Foo in a package that spring is looking at. So it is injected correctly. public String someAction() { myFoo.save("something"); //the @Before advice is only called if the class containing the aspect is not in an external jar } //in a class with a main method void main(String[] ars) { ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml"); //right after the previous line, I can see in the log that MyAspect is instantiated. Foo myFoo = ac.getBean(Foo.class); myFoo.save("something"); //the @Before advice is only called if the class containing the aspect is not in an external jar } 

基本上,我的applicationContext.xml有以下几行:

        

我认为我不需要做任何类似的事情

    

我也有同样的问题。 我用maven解决了这个问题。 检查aspectj-maven-plugin和选项weaveDependency

http://mojo.codehaus.org/aspectj-maven-plugin/weaveJars.html

考虑到当应用程序和spring打包类时,它的工作完全正常,我只能认为这是一个类加载问题。

如果它在您的应用程序中捆绑时工作正常,那么当AOP扫描它必须监视的所有类时,它将引用具有所有正确jar的正确类加载器。 但现在当你删除它并将其设置为JAR时,它会在类加载器下扫描所有其他第三方jar。

我不是100%确定如何绘制出来但它可能是这样的:

 Bootstrap Classloader <- Third Party Classloader <- Application Class Loader (with all your classes) \ \ aspectj.jar spring.jar 

如果它的aspect.jar只在其类加载器下扫描,那么它将无法看到“所有类”。 您可以尝试确认这一点的一种方法是获取应用程序的堆转储。 针对Eclipse MAT运行它,查看Class Loader资源管理器并查找方面类。 如果它们不与您的应用程序位于同一个类加载器下,则必须查看让tomcat告诉应用程序类的第三方库的方法。

您可以尝试使用aspectJ LTW而不是Spring AOP代理。 为此,请向META-INF添加aop.xml

            

这是配置的spring部分:

详情请见: http : //static.springsource.org/spring/docs/3.0.x/spring-framework-reference/html/aop.html#aop-aj-ltw

从ActionJ中的AspectJ开始:与基于代理的AOP(使用@AspectJ或基于XML的语法声明)一起使用的方面是Spring bean,不应该使用aspectOf()方法进行实例化。

正常声明并查看它是否成功:

    

我最终在spring的applicationContext xml配置中声明了方面并删除了注释。

到目前为止工作的是为maven使用aspectj插件,但每次我在eclipse中更改一个类时,我必须运行$ mvn compile (因为eclipse不知道方面,并且正在编译没有它们的类),那就是对任何会使用MyAspect人说一个可怕的事情。

然后我创建了一个配置文件并记录:要使用MyAspect ,只需将此配置规则导入spring的上下文配置即可。

看看ApectWerks,它确实加载时编织: http ://aspectwerkz.codehaus.org/weaving.html