记录一下动态代理

静态代理

说动态代理之前咱看看静态代理是啥吧,毕竟各个关于动态代理的文章都会提到静态代理。

我理解的静态代理就是:

比如我有一个类A,然后现在需要给A添加一些操作,但是又不想去修改A本来的代码,那么咱可以写一个A的代理类AProxy,在代理类中注入A的对象,再对A的操作进行维护。

听上去还是挺有用的哈,但是如果使用很多很多静态代理的话,系统中的类会非常多,不便于维护。那咋办呢,所以才要有动态代理嘛。

 

动态代理

第一次听说这个词呢还是力哥给我讲项目的时候提到的,然后介绍了下在我们项目中应用的场景:

Mybatis中,我们想要获取sqlsession之后,只执行一次mapper就关闭sqlsession,于是去动态代理了MapperProxy,在其自带的功能上,附加上了自动关闭sqlsession的功能。

 

与静态代理相比,功能其实都是为现有的类添加功能,但是也有区别:

静态代理的类是程序运行前就存在的,动态代理是在运行时,通过反射去实现的。

动态代理做了啥呢:

比如我们有一个obj1,动态代理其实就是要在obj1的基础上生成一个obj2对象,obj2与obj1具有相同的类型,但obj2对象可以在其invoke方法里面对obj1的方法进行进一步的操作。

以下给出一个动态代理的例子:

// 一个接口
public interface Sister {
    void getName();
    void speak();
}



//一个接口实现类
public class XinYi implements Sister {
    @Override
    public void getName() {
        System.out.println("心怡妹妹");
    }

    @Override
    public void speak() {
        System.out.println("不要天天早上都迟到!!!");
    }
}



//一个动态代理类
public class SisterProxy implements InvocationHandler {
    Object obj1;
    public SisterProxy(Object obj1){
        this.obj1=obj1;
    }

    /**
     * @param proxy  被代理后的对象,而不是代理之前的对象,这里就是指的obj2对象
     * @param method 被代理obj1的方法
     * @param args   被代理的obj1方法的参数
     */
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        Object cc= method.invoke(this.obj1, args);
        System.out.println("这里是代理");
        return cc;
    }
}



//测试类
public class TestSister {

    public static void main(String[] args) {
        Sister xinyi = new XinYi();
        Sister sister =
(Sister)Proxy.newProxyInstance(SisterProxy.class.getClassLoader(), new Class[]{Sister.class}, new SisterProxy(xinyi));
        sister.getName();
        sister.speak();
    }
}

输出结果:

心怡妹妹
这里是代理
不要天天早上都迟到!!!
这里是代理

可以看到上面使用了 Proxy.newProxyInstance创建了一个sister对象,而本来的xinyi对象运行输出应该只有两句话,而经过动态代理之后,输出有了四句话,多出来的“这里是代理”就是在代理类的invoke方法中添加的。

Proxy.newProxyInstance的三个参数分别是,类加载器,接口列表,动态代理类,以下分别介绍:

1. 类加载器:一般使用应用类加载器,这里使用的当前类的加载器,结果都是一样的

2. 接口列表:被代理的类所继承的接口列表,Class[]类型,注意一定是接口,不能是类,不然得用CGLIB去代理,当前咱这样是JDK代理。Proxy会通过反射去找到对应的方法,进行代理。

3. 动态代理类:也就是实现InvocationHandler的对象,代理的时候会去只行其中的invoke方法。

 

以上就是今天学的动态代理内容(其实学了很多次了,没总结就会忘。。),内容多来自力哥博客:https://www.jianshu.com/p/2b442b818b16

还有我没看完但是感觉很详细的对newProxyInstance的剖析:https://my.oschina.net/u/2264912/blog/1592613

 

然后今天为什么会想到学动态代理呢,是因为在学设计模式的时候,那个pdf里面的抽象工厂模式,举的例子为Redis集群,各个集群的操作redis的方法不一样,通过设计了响应的适配类(继承自同一个接口),来实现方法调用的统一。然后最后测试在选择调用哪个类型的时候,使用的是动态代理去获取的具体对象。

当时看着好牛逼,就回头来学动态代理,结果学完发现好像是在脱了裤子放屁,都把适配类写好了,动态代理类里面也啥都没干,就是用来创建对象了。(后边怀疑是模仿Redis集群的真实环境,需要用动态代理里面的反射去创建不同地方的对象?)

结果又一看,好像抽象工厂模式和pdf里面讲的根本不一样,好家伙,我直接好家伙。。。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值