Tuesday, February 18, 2014

Use maven aspectj plugin to look inside of Spring

Along with spring development with more and more features, the code is more complex. Sometimes, developer wants to have some customized tracing information that spring debug logging does not provide. Aspectj, as an instrumental tool could help in this field, while maven aspectj plugin is able to quickly setup the project and get the instrumentation done. In this article, I will demo how to use maven aspectj plugin to instrument spring code.

The parent pom has two modules, aspectj and spring, while aspectj is the one to instrument the spring project.

 
 ---aspectj-spring
    --aspectj
      --src
        --main
          --aspect
            --packageName
              --AspectL.java
      pom.xml
    --spring
      --src
        --main
          --java
            --..clases
      pom.xml
    pom.xml 
The spring project is to use a Main class to bootstrap an application context. The pom.xml underneath spring enables a maven exec plugin to execute Main class
                        <plugin>
    <groupId>org.codehaus.mojo</groupId>
    <artifactId>exec-maven-plugin</artifactId>
    <version>1.2.1</version>
    <executions>
     <execution>
      <goals>
       <goal>java</goal>
      </goals>
     </execution>
    </executions>
    <configuration>
     <mainClass>org.shaozhen.sample.Main</mainClass>
    </configuration>
   </plugin>
The aspectj project has only one Aspect (AspectJ.java) that intercept all the DefaultListableBeanFactory.registerBeanDefinition method execution and print out the bean names and class names.
@Aspect
public class AspectL {

    @Pointcut("execution(* org.springframework.beans.factory.support.DefaultListableBeanFactory.registerBeanDefinition(..))")
    public void defineEntryPoint() {
     
    }
        

    @Before("defineEntryPoint()")
    public void aaa(JoinPoint joinPoint) {
     String beanName = (String) joinPoint.getArgs()[0];
     BeanDefinition beanDefinition = (BeanDefinition) joinPoint.getArgs()[1];
        System.out.println("Register BeanName" + beanName + " with: " + beanDefinition.getBeanClassName());
    }
The apsectj pom.xml enable the aspectj plugin to do the load time weaving, since the spring class is already compiled into the jar. In order to do the load time weaving, the plugin has to include the binary jar as a dependency under <weaveDependency>
                       <plugin>
    <groupId>org.codehaus.mojo</groupId>
    <artifactId>aspectj-maven-plugin</artifactId>
    <version>1.6</version>
    <executions>
     <execution>
      <goals>
       <goal>compile</goal>  
       <goal>test-compile</goal>
      </goals>
      <configuration>
       <complianceLevel>1.6</complianceLevel>
       <source>1.6</source>
       <target>1.6</target>
       <weaveDependencies>
        <weaveDependency>
         <groupId>org.springframework</groupId>
         <artifactId>spring-beans</artifactId>
        </weaveDependency>        
       </weaveDependencies>
                      <showWeaveInfo>true</showWeaveInfo>       
      </configuration>
     </execution>
    </executions>
   </plugin>
To Run the example:
In parent module: mvn clean install
In aspect module: mvn exec:java would print all the tracing information.....

Register BeanNamepropertyBean with: org.shaozhen.sample.PropertyFactoryBean
Register BeanNametest with: org.shaozhen.sample.TestFactoryBean
Register BeanNamecomponents with: org.shaozhen.sample.component.Components
Register BeanNameorg.springframework.context.annotation.internalConfigurationAnnotationProcessor with: org.springframework.context.annotation.ConfigurationClassPostProcessor
Register BeanNameorg.springframework.context.annotation.internalAutowiredAnnotationProcessor with: org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor
Register BeanNameorg.springframework.context.annotation.internalRequiredAnnotationProcessor with: org.springframework.beans.factory.annotation.RequiredAnnotationBeanPostProcessor
Register BeanNameorg.springframework.context.annotation.internalCommonAnnotationProcessor with: org.springframework.context.annotation.CommonAnnotationBeanPostProcessor
Register BeanNameorg.springframework.context.annotation.ConfigurationClassPostProcessor.importAwareProcessor with: org.springframework.context.annotation.ConfigurationClassPostProcessor$ImportAwareBeanPostProcessor

The code can be accessed from here: https://github.com/datianshi/aspectj-spring

No comments:

Post a Comment