代理学习
代理學習
1、靜態代理
測試類:
package com.example.demo.proxy;public class StaticProxy implements UserDao {private UserDao userdao;public UserDao getUserdao() {return userdao;}public void setUserdao(UserDao userdao) {this.userdao = userdao;}@Overridepublic void getUser() {System.out.println("代理類進入");userdao.getUser();System.out.println("代理類退出");}public static void main(String[] args) {StaticProxy sp = new StaticProxy();UserDao userDao = new UserDaoImpl();sp.setUserdao(userDao);sp.getUser();} }userdao:
package com.example.demo.proxy;public interface UserDao {void getUser(); }userdaoimpl:
package com.example.demo.proxy;public class UserDaoImpl implements UserDao {@Overridepublic void getUser() {System.out.println("userdao impl");} }運行測試類:
代理類進入 userdao impl 代理類退出?
2、jdk動態代理
測試類:
userdao和userdaoimpl同上
運行測試類:
進入proxy userdao impl 退出proxyJDK動態代理局限性
通過反射類Proxy和InvocationHandler回調接口實現的jdk動態代理,要求委托類必須實現一個接口,但事實上并不是所有類都有接口,對于沒有實現接口的類,便無法使用該方方式實現動態代理。
3、cglib動態代理
靜態代理和jdk動態代理模式都是要求目標對象實現一個接口,Cglib代理,也叫作子類代理,是基于asm框架,實現了無反射機制進行代理,利用空間來換取了時間,代理效率高于jdk ,它是在內存中構建一個子類對象從而實現對目標對象功能的擴展.
它有如下特點: JDK的動態代理有一個限制,就是使用動態代理的對象必須實現一個或多個接口,如果想代理沒有實現接口的類,就可以使用Cglib實現.
Cglib是一個強大的高性能的代碼生成包,它可以在運行期擴展java類與實現java接口.它廣泛的被許多AOP的框架使用,例如Spring AOP和synaop,為他們提供方法的interception(攔截)
Cglib包的底層是通過使用一個小而塊的字節碼處理框架ASM來轉換字節碼并生成新的類.不鼓勵直接使用ASM,因為它要求你必須對JVM內部結構包括class文件的格式和指令集都很熟悉. 注意
需要引入cglib的jar文件,但是Spring的核心包中已經包括了Cglib功能,所以直接引入pring-core-3.2.5.jar即可.
引入功能包后,就可以在內存中動態構建子類
代理的類不能為final,否則報錯
目標對象的方法如果為final/static,那么就不會被攔截,即不會執行目標對象額外的業務方法. 測試類: package com.example.demo.proxy;import org.springframework.cglib.proxy.Enhancer; import org.springframework.cglib.proxy.MethodInterceptor; import org.springframework.cglib.proxy.MethodProxy;import java.lang.reflect.Method;/*** 實現methodInterceptor方法,并重寫interceptor方法*/ public class CglibDynamicProxy implements MethodInterceptor {//維護一個被代理的對象private Object target;public Object getinstance() {Enhancer enhancer = new Enhancer();enhancer.setSuperclass(target.getClass());//回調方法指定當前類即可(實現了methodInterceptor接口的類)enhancer.setCallback(this);return enhancer.create();}@Overridepublic Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {System.out.println("cglib代理開始");Object invoke = method.invoke(target, objects);System.out.println("cglib代理結束");return invoke;}public static void main(String[] args) {CglibDynamicProxy cg = new CglibDynamicProxy();UserWithoutInterface u = new UserWithoutInterface();cg.setTarget(u);UserWithoutInterface instance = (UserWithoutInterface) cg.getinstance();instance.getuser();}public Object getTarget() {return target;}public void setTarget(Object target) {this.target = target;} }
被代理對象UserwithoutInterface:
package com.example.demo.proxy;public class UserWithoutInterface {public void getuser(){System.out.println("執行userwithoutInterface中的getuser方法");} }執行測試類結果:
cglib代理開始 執行userwithoutInterface中的getuser方法 cglib代理結束?
?
參考:http://ifeve.com/java-reflection-11-dynamic-proxies/
?
posted @ 2019-06-13 21:49 巡山小妖N 閱讀(...) 評論(...) 編輯 收藏總結
- 上一篇: vue - blog开发学7
- 下一篇: mybatis默认的数据源连接池(Poo