首先看aop是虾米:
aop使用过程中,需要用到动态代理,而jdk自带的动态代理,是通过反射的方法,通过反射获取要代理的method,然后在执行过程中动态执行了类似before after之类的方法,以实现目的。但是局限于只能用于interface,为了解决这个问题,aspect采用了GCLib这个库。
GCLib:gclib原理有所不同(实际上源码我搞的并不是很明白),在编译成字节码之后,GCLib会进行改造最终生成新的对象。CLASSA在改造后,实际上是CLASSAXXX,方法也成为了被改造后的方法。所以,它的效率也会比反射高,而且可以改造所有非final method。
实现过程:
一.注解Aspect
Class<? extends Annotation> value();
接收的value为一个class(比较菜鸡,不支持正则表达式)
二.接口Proxy
public interface Proxy { Object doProxy(ProxyChain proxyChain) throws Throwable; }
三.ProxyChain
它的主要功能是连接 Proxy 和 被代理(改造)的class,最终生成weaving后的object。
它有以下参数
//目标类 private final Class<?> targetClass; //以下四个参数是 gclib的 enhance传递进来的 private final Object targetObject; private final Method targetMethod; /** * 方法代理对象 会在doProxyChain中用到 */ private final MethodProxy methodProxy; private final Object[] methodParams; //代理的列表 private List<Proxy> proxyList = new ArrayList<Proxy>(); private int proxyIndex = 0;
另外它有方法
public Object doProxyChain() throws Throwable { Object methodResult; if(proxyIndex < proxyList.size()){ methodResult = proxyList.get(proxyIndex++).doProxy(this); }else{ methodResult = methodProxy.invokeSuper(targetObject,methodParams); } return methodResult; }
这个方法遍历了proxylist,因为可能同一个target会有多个proxy,这些proxy都要织入进去。所以,所有的proxy都执行了一遍doProxy方法,那么我们来看doProxy做了虾米。
三.Proxy的实现类AspectProxy
最核心内容就是doProxy了
@Override public Object doProxy(ProxyChain proxyChain) throws Throwable { Object result = null; Class<?> clazz = proxyChain.getTargetClass(); Method method = proxyChain.getTargetMethod(); Object[] params = proxyChain.getMethodParams(); begin(); try{ if(intercept(clazz,method,params)){ before(clazz,method,params); result = proxyChain.doProxyChain(); after(clazz,method,params); }else{ result = proxyChain.doProxyChain(); } }catch(Exception e){ log.error("proxy failure",e); error(clazz,method,params,e); throw e; }finally { end(); } return result; }
里面的begin,before等等方法,自然是继承之后重写的。这里形成了一个递归,如下:
p1.before
p1.result = p2.before
p2.result = pn.before
pn.result = methodProxy.invokeSuper(targetObject,methodParams);
pn.after
return pn.result
p2.after
return p2.result
p1.after
return p1.result;
好了,proxy的实现就差不多了。
四.最后,实现aop的helper
1.获取到所有的切面,通过beanhelper,获取到extends AspectProxy而且有@Aspect注解的类,得到一个
Map<Class<?>,Set<Class<?>>> proxyMap
得到proxy和它的target
2.把刚才得到的代理类和目标类转成
Map<Class<?>,List<Proxy>> targetMap
key为targetclass value为proxy的实例,形成一个目标类对应多个代理实例的关系。
3.遍历map,
Enhancer.create(targetClass, (MethodInterceptor) (o, method, objects, methodProxy) -> new ProxyChain(targetClass,o,method,methodProxy,objects,proxyList).doProxyChain());
创建weaving后的实例,并且调用setBean函数,用weaving后的bean替换掉原本的bean。
结束。
2.