背景
今天在分析同事遇到一个springboot的注解和方法锁一起用而导致的问题(@Transaction和synchronized用在同一个方法中由于事务先于锁进入后于锁释放而可能引发的数据问题)中而突然思考到spring的Aspect是怎么样的执行顺序,本文介绍java中其中一种(InvocationHandler)利用动态代理的方式实现的代理的方法,从而类似的机制我们推测出spring的切面其实也是在代理类中执行了切面的函数并在invoke之前或者之后去执行定义的点,而之所以能够自动扫描切面应该是类似spring rabbitmq的实现扫面一遍所有的component bean获取所有的注解然后执行,后续再仔细分析Aspect的实现,本文我们尝试实现aspect注解从而实现捕获函数执行前参数和执行后结果并打印出来
代码
package com.oujiangping.leetcode;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@Retention(RetentionPolicy.RUNTIME)
public @interface aspect {
}
package com.oujiangping.leetcode;
@aspect
public interface TestAspect {
public String test(String sr);
}
package com.oujiangping.leetcode;
@aspect
public class TestAspectImpl implements TestAspect {
@Override
public String test(String sr) {
System.out.println("run TestAspectImpl.test " + sr);
return sr;
}
}
package com.oujiangping.leetcode;
@aspect
public class TestAspectImplA implements TestAspect {
@Override
public String test(String sr) {
System.out.println("run TestAspectImplA.test " + sr);
return sr;
}
}
package com.oujiangping.leetcode;
package com.oujiangping.leetcode;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
public class MyAspect implements InvocationHandler {
Object instance;
public Object aspect(Object instance) {
this.instance = instance;
return Proxy.newProxyInstance(instance.getClass().getClassLoader(), instance.getClass().getInterfaces(),this);
}
public void befor(Method method, Object[] args) {
System.out.println("~~~~ befor: " + method.getName() + " " + args);
}
public void after(Object object) {
System.out.println("~~~~ after: " + object);
}
public static void init() {
Field[] fields= MyAspect.class.getDeclaredFields();
for(int i=0;i<fields.length;i++){
MyAspect myAspect = new MyAspect();
aspect aspects = fields[i].getType().getAnnotation(aspect.class);
if(aspects != null) {
fields[i].setAccessible(true);
try {
fields[i].set(myAspect, new MyAspect().aspect(fields[i].get(myAspect)));
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
}
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
Object result=null;
befor(method, args);
result = method.invoke(instance, args);
after(result);
return null;
}
public static TestAspect testAspect = new TestAspectImpl();
public static TestAspect testAspectA = new TestAspectImplA();;
public static void main(String []args) {
init();
testAspect.test("I'm TestAspectImpl");
testAspectA.test("I'm TestAspectImplA");
}
}
结果:
~~~~ befor: test [Ljava.lang.Object;@49476842
run TestAspectImpl.test I'm TestAspectImpl
~~~~ after: I'm TestAspectImpl
~~~~ befor: test [Ljava.lang.Object;@78308db1
run TestAspectImplA.test I'm TestAspectImplA
~~~~ after: I'm TestAspectImplA