"; */ ?>

Running Spring AspectJ Tests with Maven

You need to use a real AspectJ aspect with Spring, where you would like to inject some dependencies into this aspect as a Spring container starts up.

Here is an AspectJ aspect:

@Aspect
public class VeryImportantAspect {
    ...
    public void setSomeDependency( SomeDependency dependency ) {
        this.dependency = dependency;
    }
    ...
}

Now let’s define it as a bean and inject “someDependency”:

<bean id="veryImportantAspect" 
         class="org.dotkam.VeryImportantAspect"
         factory-method="aspectOf">
 
         <property name="someDependency" ref="someDependency"/>
</bean>

Notice factory-method=”aspectOf” that tells Spring to use a real AspectJ ( not Spring AOP ) aspect to create this bean. In reality, if the “VeryImportantAspect” was already woven in, it will have an “aspectOf” method.

Hence if you get this error at some point:

No matching factory method found: factory method 'aspectOf()'

That would mean that the aspect was not woven by AspectJ weaver.

We also need to tell Spring to use load time weaving:

<context:load-time-weaver/>

If you run with the above configuration without doing anything, you would get a following error:

ClassLoader does NOT provide an 'addTransformer(ClassFileTransformer)' method

That tells you ( well not explicitly 🙂 ) to include a “spring-instrument.jar” javaagent.

So at this point two things need to be added: AspectJ weaver and Spring Instrument agent. Build / Continues integration server does not use any IDE, so it is not as simple as downloading AspectJ plugin for IDEA / Eclipse and including VM arguments in Run Configurations… It is simpler: just add the two in your POM file.

Adding an AspectJ plugin:

<plugin>
     <groupId>org.codehaus.mojo</groupId>
     <artifactId>aspectj-maven-plugin</artifactId>
     <version>1.3</version>
     <executions>
         <execution>
             <configuration>
                <source>1.6</source>
                <target>1.6</target>
            </configuration>                     
             <goals>
                 <goal>compile</goal>       <!-- use this goal to weave all your main classes -->
                 <goal>test-compile</goal>  <!-- use this goal to weave all your test classes -->
             </goals>
         </execution>
    </executions>
</plugin>

Adding a Spring Instrument agent to participate in a test execution:

<plugin>
	<groupId>org.apache.maven.plugins</groupId>
	<artifactId>maven-surefire-plugin</artifactId>
	<version>2.4</version>
	<configuration>
            <forkMode>once</forkMode>
            <argLine>
                 -javaagent:"${settings.localRepository}/org/springframework/spring-instrument/${spring.framework.version}/spring-instrument-${spring.framework.version}.jar"
	    </argLine>
            <useSystemClassloader>true</useSystemClassloader>
	</configuration>
</plugin>

And all that work, just too see a couple of lines from Maven:

[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESSFUL
[INFO] ------------------------------------------------------------------------