springtiny aop实现

首先看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.

转载于:https://my.oschina.net/vqishiyu/blog/1827520

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值