spring源码阅读(2)-aop之jdk动态代理深入解析

续spring源码阅读(2)-aop之j动态代理

我们从需求作为动态代理发展的切入吧

现在有5个已经投产了的run100m的实现,我们新的需求需要监控不同实现的运行性能,如果我们针对这五个实现分别去添加性能监控的代码,如此就造成两个问题:

一个是已经稳定的代码需要重新测试,

一个是设计上相同的代码出现在项目的各个地方,以后需要修改就需要修改5个地方,如果有新加实现就需要修改更多的处理点。

伟大的程序设计大师早就解决了这个问题,我们可以代理的方式,也就是我们的代理模式,我们来看下代理的uml类图

上面是一个代理的uml类关系图, 我们来看下ProxyRace的伪代码大概就清楚代理了

public class ProxyRace implement Race{
    private Race race;

    @Override
    public void race100m(){
        performancemonitor.start();
        race.run100m();
        performancemonitor.end();
    }
}

看到这里对静态代理是不是一下就清晰了。

代理的关键在于接口,代理,实现类都实现了相同的接口,代理类关联了一个实现类,由代理去调用实现类的方法,如此代理类就可以添加自己的业务了。

回到性能监控的需求上面,可见使用代理的模式是不是使上面的需求一下变得简单易于维护了,以后对于性能监控的代码只要修改代理类这一处就ok了。也减少了代码的改动点,从而减少测试工作,并且以后的实现还是只要关注run100m的业务就好,不用关注性能方面的业务,也免去了其他业务代码的侵入,松了耦合。

如果我们以后不断的在各种现有实现功能的基础上做各种代理操作,也会造成代理类的数量过多的情形,此时我们就想要做一个通用的代理工具:

这就引出了一个我们这篇博文需要重点讨论的问题:动态代理

从上面的代理我们得出,代理某个类我们需要新建一个代理类对接口功能做包括:所以动态代理就需要支持一个非常重要的功能,动态创建类。

然后我们再想想jdk的Proxy.newProxyInstance的实现原理

从InvocationHandler的invoke方法分析:(我们是在这个接口方法里做代理业务处理的)

public Object invoke(Object proxy, Method method, Object[] args){
method.invoke(target, args);
}

然后根据我们实现的静态代理类如何改造成上面的结构:

新建一个InvocationHandler类,把race属性移到这个类里,且这个类添加一个方法invoke(method,arg),我们再改造ProxyRace,添加一个方法newProxyInstance方法,我们编写一个伪代码

newProxyInstance(Class itfs, invocationHandler){
invocationHandler.invoke(method, );
    //制作一个类字符串
    String classStr = public class $Proxy1 implements itfs{
        private InvcationHander ih;
        //构造方法传入invocationHandler
        public $Proxy(InvocationHander ih){
            this.ih = it;
        }

        //遍历接口的所有方法
        for (Method m:itfs.getMethods()){
            public void m.getName()(){
                //这个里面调用invocationHandler的invoke方法,注意这里是对象直接调用
                ih.invoke(this, m);
            }
        }
    }
    //写入到文件
    File clsf = createClassFile(classStr);
    //java编译
    CompileClassFile(clsf);
    //使用类加载器加载类
    loadclass();
}

这个是简略写的jdk反射的原理概要,再次确认了接口对于jdk太重要了,所有的核心操作都是针对接口设计的,

在看看cglib实现的动态代理

cglib实现的原理与jdk稍微有点不一样,jdk是基于接口的关联的方式实现的代理,而cglib是继承的方式,子类覆盖父类方法实现代理

我们来看看cglib针对如上业务的实现吧

public class CglibProxy implements MethodInterceptor {
    private Enhancer enhancer;
    private long startt;
    public Object getProxy(Class proxyClass){
        enhancer = new Enhancer();
        enhancer.setSuperclass(proxyClass);
        enhancer.setCallback(this);
        return enhancer.create();
    }

    private void begin(){
        this.startt = System.currentTimeMillis();
        System.out.println("开始时间:" + this.startt);
    }

    private void end(){
        long endt=System.currentTimeMillis();
        System.out.println("结束时间:"+endt+" 执行消耗:"+(endt-startt));
    }

    @Override
    public Object intercept(Object target, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
        begin();
        Object ret =  methodProxy.invokeSuper(target, args);
        end();
        return ret;
    }
}

执行结果

开始时间:1539966285203
human run 100m
结束时间:1539966295222 执行消耗:10019

使用System.setProperty(DebuggingClassWriter.DEBUG_LOCATION_PROPERTY, "E:\\\\swap");生成代理类class

我们看看看看这个class内容

public class HumanRace$$EnhancerByCGLIB$$bb1a6f1f extends HumanRace implements Factory {
    
    
    final void CGLIB$race100m$0() {
        super.race100m();
    }

    public final void race100m() {
        //回调类实现了MethodInterceptor接口
        MethodInterceptor var10000 = this.CGLIB$CALLBACK_0;
        var10000.intercept(this, CGLIB$race100m$0$Method, CGLIB$emptyArgs, CGLIB$race100m$0$Proxy);
        super.race100m();
        
    }
   
    final boolean CGLIB$equals$2(Object var1) {
        return super.equals(var1);
    }

    public final boolean equals(Object var1) {
        MethodInterceptor var10000 = this.CGLIB$CALLBACK_0;
        if (this.CGLIB$CALLBACK_0 == null) {
            CGLIB$BIND_CALLBACKS(this);
            var10000 = this.CGLIB$CALLBACK_0;
        }

        if (var10000 != null) {
            Object var2 = var10000.intercept(this, CGLIB$equals$2$Method, new Object[]{var1}, CGLIB$equals$2$Proxy);
            return var2 == null ? false : (Boolean)var2;
        } else {
            return super.equals(var1);
        }
    }

    final String CGLIB$toString$3() {
        return super.toString();
    }

    public final String toString() {
        MethodInterceptor var10000 = this.CGLIB$CALLBACK_0;
        if (this.CGLIB$CALLBACK_0 == null) {
            CGLIB$BIND_CALLBACKS(this);
            var10000 = this.CGLIB$CALLBACK_0;
        }

        return var10000 != null ? (String)var10000.intercept(this, CGLIB$toString$3$Method, CGLIB$emptyArgs, CGLIB$toString$3$Proxy) : super.toString();
    }

    final int CGLIB$hashCode$4() {
        return super.hashCode();
    }

    public final int hashCode() {
        MethodInterceptor var10000 = this.CGLIB$CALLBACK_0;
        if (this.CGLIB$CALLBACK_0 == null) {
            CGLIB$BIND_CALLBACKS(this);
            var10000 = this.CGLIB$CALLBACK_0;
        }

        if (var10000 != null) {
            Object var1 = var10000.intercept(this, CGLIB$hashCode$4$Method, CGLIB$emptyArgs, CGLIB$hashCode$4$Proxy);
            return var1 == null ? 0 : ((Number)var1).intValue();
        } else {
            return super.hashCode();
        }
    }

    final Object CGLIB$clone$5() throws CloneNotSupportedException {
        return super.clone();
    }

    protected final Object clone() throws CloneNotSupportedException {
        MethodInterceptor var10000 = this.CGLIB$CALLBACK_0;
        if (this.CGLIB$CALLBACK_0 == null) {
            CGLIB$BIND_CALLBACKS(this);
            var10000 = this.CGLIB$CALLBACK_0;
        }

        return var10000 != null ? var10000.intercept(this, CGLIB$clone$5$Method, CGLIB$emptyArgs, CGLIB$clone$5$Proxy) : super.clone();
    }

    //这里在enhancer.setCallback();中设置的回调
    public void setCallback(int var1, Callback var2) {
        switch(var1) {
        case 0:
            this.CGLIB$CALLBACK_0 = (MethodInterceptor)var2;
        default:
        }
    }
}

从这个类我们应该能看出cglib的实现原理,我们根据我们的实现代码加上这个类慢慢剖析:

public class HumanRace$$EnhancerByCGLIB$$bb1a6f1f extends HumanRace

这里继承了我们要代理的类,印证了cglib的代理是基于继承的,我们继续看看继承是如何实现代理的

public void setCallback(int var1, Callback var2)

我们应用中有一个enhancer.setCallback(this);就是设置的一个回调类,我们继续看看这个类怎么使用的

final void CGLIB$race100m$0() {
        super.race100m();
    }

    public final void race100m() {
        //回调类实现了MethodInterceptor接口
        MethodInterceptor var10000 = this.CGLIB$CALLBACK_0;

        if (var10000 != null) {
            var10000.intercept(this, CGLIB$race100m$0$Method, CGLIB$emptyArgs, CGLIB$race100m$0$Proxy);
        } else {
            super.race100m();
        }
        
    }

从这个类看每个方法都实现了两个,一个使用了一个做了下别名,一个就是原方法名,我们只研究我们关注的方法,其他的toString,equal之类的我们暂不看。

CGLIB$race100m$0()根据cglib的一个规则重新命名,直接调用父类的super.race100m()方法,一个是覆盖了父类的方法,这里使用了我们上面的回调,如果回调不为空,调用回调是实现的intercept方法,我们就是在这个方法了实现代理的。

至此cglib的实现原理和方式我想您也应该清楚了吧。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值