spring 静态AOP切第三方jar包

示例需求:当我们调用fastjson里面的toJSONString方法时,我们在这个方法上加上环绕通知,众所周知,这个方法是第三方jar包fastjson里面提供的一个方法,我们要做的就是切到这个方法上,然后加环绕通知。步骤如下:

1、写一个服务,该服务使用了fastjson里面的toJSONString方法,代码如下:

public class JSONService {
	public String parse2String(Object obj){
		return JSON.toJSONString(obj);
	}
}

2、写一个切面,并在该切面上配置环绕通知,代码如下:

@Aspect
public class JSONAspect {
	
	public static JSONAspect ajc$perSingletonInstance;

	private static Throwable ajc$initFailureCause;

	static {
		try {
			ajc$postClinit();
		} catch (Throwable localThrowable) {
			ajc$initFailureCause = localThrowable;
		}
	}

	private static void ajc$postClinit() {
		ajc$perSingletonInstance = new JSONAspect();
	}

	public static JSONAspect aspectOf() {
		if (ajc$perSingletonInstance == null)
			throw new NoAspectBoundException("com.chhliu.myself.spring.staticaop.JSONAspect", ajc$initFailureCause);
		return ajc$perSingletonInstance;
	}
	
	/**
	 * attention:
	 * Details:切入到第三方jar包对应的具体方法上,同时配置环绕通知
	 * @author chhliu
	 * 创建时间:2016-7-26 下午5:25:06
	 * @param join
	 * @param obj
	 * @return
	 * String
	 */
	@Around("execution(* com.alibaba.fastjson.JSON.toJSONString(java.lang.Object)) && args(obj)")
	public String parse2String(ProceedingJoinPoint join, Object obj){
		System.out.println("parse to String before");
		String str = "";
		try {
			str = (String) join.proceed(new Object[]{obj});
			System.out.println("result:"+str);
		} catch (Throwable e) {
			e.printStackTrace();
		}
		System.out.println("parse to String after");
		return str;
	}
}
注意:代码中标蓝的部分是AspectJ反编译后的代码,必须加上,否则会出问题,切不进去,感觉是spring 整合AspectJ时的一个bug。如果将我们的工程转成AspectJ Project的话,反编译出来的类就会自动的加上上面标蓝的代码。

3、在META-INF下增加切面的配置文件,如下:

工程结构目录如下:




    
        
        
    
    
        
        
    

4、编写测试类,代码如下:

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = { "classpath:applicationContext.xml" })
public class JSONAspectTest {
	
	@Resource(name="jsonService")
	private JSONService service;
	
	@Test
	public void test(){
		User u = new User();
		u.setName("chhliu");
		u.setPassword("123456");
		service.parse2String(u);
	}
}
5、增加jvm启动项,在虚拟机启动的时候,就启动AOP切面,如下: spring 静态AOP切第三方jar包_第1张图片

6、测试结果如下:

[AppClassLoader@40d7b9] info AspectJ Weaver Version 1.7.2 built on Friday Feb 15, 2013 at 18:40:45 GMT
[AppClassLoader@40d7b9] info register classloader sun.misc.Launcher$AppClassLoader@40d7b9
[AppClassLoader@40d7b9] info using configuration /D:/NTF/spring_test/target/classes/META-INF/aop.xml
[AppClassLoader@40d7b9] info using configuration file:/D:/SoftWare/java%20software/apache-maven-3.0.5-bin/apache-maven-3.0.5/repository/org/springframework/spring-aspects/3.2.5.RELEASE/spring-aspects-3.2.5.RELEASE.jar!/META-INF/aop.xml
[AppClassLoader@40d7b9] info register aspect com.chhliu.myself.spring.staticaop.JSONAspect
[AppClassLoader@40d7b9] info register aspect org.springframework.beans.factory.aspectj.AnnotationBeanConfigurerAspect
[AppClassLoader@40d7b9] info register aspect org.springframework.scheduling.aspectj.AnnotationAsyncExecutionAspect
[AppClassLoader@40d7b9] info register aspect org.springframework.transaction.aspectj.AnnotationTransactionAspect
[AppClassLoader@40d7b9] info register aspect org.springframework.cache.aspectj.AnnotationCacheAspect
log4j:WARN No appenders could be found for logger (org.springframework.test.context.junit4.SpringJUnit4ClassRunner).
log4j:WARN Please initialize the log4j system properly.
log4j:WARN See http://logging.apache.org/log4j/1.2/faq.html#noconfig for more info.
[AppClassLoader@40d7b9] warning javax.* types are not being woven because the weaver option '-Xset:weaveJavaxPackages=true' has not been specified
around before
beforeTest
parse to String before
result:{"name":"chhliu","password":"123456"}
parse to String after
蓝色字体部分说明,在启动的时候,AppClassLoader将我们自己写的切面加载进去了,并且在调用fastjson的toJSONString方法的时候,切面启了作用,如果我们用spring的动态AOP,是很难切入到第三方jar包里面的方法的。

从上面的示例中,我们可以看到,使用Spring AOP来实现回归测试是可行的,当我们测试完之后,我们把测试的用例都存起来(文件或Redis),当我们在调用真正方法之前,我们截取该方法的参数,从而获取相关的请求报文信息,然后和Redis中的报文头进行一个匹配,匹配成功之后,我们并不真正的执行目的方法,而是直接将匹配的报文返回给用户,从而实现了mock测试,供大家参考。

你可能感兴趣的:(spring)