JAVA动态代理详解
问题
1:什么是静态代理,动态代理?
2:动态代理的好处?
什么是静态代理
以生活中例子来看,我作为某某品牌面膜的北京区代理,我替厂家卖面膜,我属于代理,厂家属于委托方。
联系到JAVA中就是,我作为一个代理类,我替委托类去调用方法,同时可以添加一些附加的功能。
如果一个代理类在程序运行之前就已经存在了,那么这种代理方式被称为静态代理。
先上代码
父接口:
publicinterfacePerson{/**
* 吃饭
*/voideat();/**
* 拉稀
*/voidshit();}
委托类:
classZhangsanimplementsPerson{@Overridepublicvoideat(){System.out.println("我每天都会吃饭;");}@Overridepublicvoidshit(){System.out.println("我偶尔会拉稀;");}}
静态代理类:
classDynamicPersonimplementsPerson{/**
* 委托类
*/privateZhangsan zhangsan;@Overridepublicvoideat(){System.out.println("附加功能");
zhangsan.eat();}@Overridepublicvoidshit(){}}
由上代码可知,代理类中将委托类引入了进来,但是怎么保证代理类的方法列表和委托类的方法列表一致呢,这里是通过接口约束了方法列表。
静态代理的弊端:对于委托类的每一个方法,都得重新编辑同时加入自己的附加功能,委托类方法过多时,效率太低。
动态代理引入
动态代理的引入就是在静态代理的基础上,添加了一个中间处理类,当调用委托类的方法时,优先进入中间处理类,自定义的附加功能放在中间处理类中即可。
动态代理的优势在于可以很方便的对代理类的函数进行统一的处理,而不用修改每个代理类的函数。
中间处理类:
classHandleimplementsInvocationHandler{/**
* 委托类
*/privateObject obj;/**
* 构造方法
* @param obj 委托类对象
*/publicHandle(Object obj){this.obj= obj;}@OverridepublicObjectinvoke(Object proxy,Method method,Object[] args)throwsThrowable{//自定义添加内容System.out.println("我每天先刷牙;");//调用委托类的方法Object result= method.invoke(obj, args);return result;}
测试类:
publicstaticvoidmain(String[] args){//获取中间处理类Handle handle=newHandle(newZhangsan());//获取动态代理实例 向上转型Person person=(Person)Proxy.newProxyInstance(Person.class.getClassLoader(),newClass[]{Person.class}, handle);
person.shit();}
测试结果:
我每天先刷牙;
我偶尔会拉稀;Process finishedwithexit code0
注意点
方法内部调用方法的情况:
classZhangsanimplementsPerson{@Overridepublicvoideat(){System.out.println("我每天都会吃饭;");}@Overridepublicvoidshit(){System.out.println("我偶尔会拉稀;");}@OverridepublicvoideatAndShit(){eat();shit();}}
输出结果:
我每天先刷牙;
我每天都会吃饭;
我偶尔会拉稀;Process finishedwithexit code0
对于委托类方法中的嵌套方法调用,是走方法内部调用,没有代理对象
动态代理分类
那么在Spirng当中动态代理有两种
第一种是JDK自带的动态代理
1.JDK动态代理是利用反射机制生成一个实现代理接口的匿名类,在调用具体方法前调用InvokeHandler来处理. 需要指定一个类加载器,然后生成的代理对象实现类的接口或类的类型,接着处理额外功能. JDK是基于接口第二种是Cglib的动态代理
2.Cglib是动态代理利用asm的开源包,对代理对象的Class文件加载进来,通过修改其字节码生成的子类来处理 Cglib是基于继承父类生成的代理类.
两种代理方式的区别:
1:JDK动态代理制能对实现了接口的类生成代理,而不是针对类
2:CGLIB是针对类实现代理,主要对指定的类生成一个子类,覆盖其中的方法,添加额外功能,因为是继承,所以该类方法不能用final来声明.
对于具体CHLIB的代码示例参考:
https://blog.csdn.net/qq_42807370/article/details/87354522