I have a java application build upon Spring 3. This project has another jar as a dependency.
This dependency contains a @org.aspectj.lang.annotation.Aspect class (lets say, com.aspectprovider.aspects.MyAspect). There’s a @Before advice to weave a method from classes that implements the interface Foo. Something like:
@Before("execution(* com.project.Foo.save(..))")
The Foo interface can be inside the “project” or in another jar. It doesn’t matter for this example.
My project contains classes that implements Foo. Those are the classes that I want it to be weaved, of course.
My Spring application context configuration file (applicationContext.xml) contains the line:
<aop:aspectj-autoproxy />
I also declare the aspect as a bean, and inject some properties:
<bean id="myAspect" class="com.aspectprovider.aspects.MyAspect"
factory-method="aspectOf" >
<property name="someproperty" value="somevalue" />
</bean>
Trough logging I can see that MyAspect is instantiated and the properties are injected. But the method save is not intercepted. This is the problem.
If I copy the aspect classes from the jar to the application that has Spring, it works. When those aspects are contained in external jars, the method save is not intercepted. Any clues?
edit: how I am calling Foo’s save method:
//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
}
Basically, my applicationContext.xml has the following lines:
<context:annotation-config />
<context:component-scan base-package="com.project" />
<context:component-scan base-package="com.aspectprovider.aspects" />
<aop:aspectj-autoproxy />
<bean id="myAspect" class="com.aspectprovider.aspects.MyAspect" factory-method="aspectOf" >
<property name="someproperty" value="somevalue" />
</bean>
I don’t think I need to put anything like
<context:component-scan base-package="com.project">
<context:include-filter type="aspectj" expression="com.aspectprovider.aspects.*" />
</context:component-scan>
I’ve ended up declaring the aspects in the spring’s applicationContext xml config and removing the annotations.
What was working so far was using the aspectj plugin for maven, but everytime I changed a class in eclipse, I had to run
$ mvn compile(because eclipse doesn’t know the aspects, and was compiling the classes without them), and that’s an awful thing to say to anybody that will useMyAspect.Then I just created a config file and documented: to use
MyAspect, just import this config rules to your spring’s context configuration.