Java的代理模式之静态代理和动态代理
文章目錄
- 靜態代理
- 動態代理
- jdk生成代理對象
- cglib代理
代理模式簡介:
代理(Proxy)是一種設計模式,提供了對目標對象另外的訪問方式;即通過代理對象訪問目標對象.這樣做的好處是:可以在目標對象實現的基礎上,增強額外的功能操作,即擴展目標對象的功能.
這里使用到編程中的一個思想:不要隨意去修改別人已經寫好的代碼或者方法,如果需改修改,可以通過代理的方式來擴展該方法
舉例說明:我們買房子可以通過房產中介去購買,而不需要直接去找地產開發商去購買,其中中介就是我們的代理對象。
代理模式按類別可以分為三類:
- 靜態代理
- 動態代理
動態代理可以分為:jdk api動態代理和cglib動態代理
靜態代理
靜態代理在使用時,需要定義接口或者父類,被代理對象與代理對象一起實現相同的接口或者是繼承相同父類.
代碼示例:
代理接口UserDao
目標對象UserDaoImpl
package com.sl.proxy;/*** @author shuliangzhao* @Title: UserDaoImpl* @ProjectName spring-boot-learn* @Description: TODO* @date 2019/10/19 17:02*/ public class UserDaoImpl implements UserDao {@Overridepublic void delete() {System.out.println("刪除數據");} }代理對象UserDaoProxy
package com.sl.proxy;/*** 代理對象* @author shuliangzhao* @Title: UserDaoProxy* @ProjectName spring-boot-learn* @Description: TODO* @date 2019/10/19 17:03*/ public class UserDaoProxy implements UserDao {private UserDao target;public UserDaoProxy(UserDao target) {this.target = target;}@Overridepublic void delete() {System.out.println("開始操作");target.delete();System.out.println("結束操作");} }測試類App
public class App {public static void main(String[] args) {UserDaoImpl userDao = new UserDaoImpl();UserDaoProxy userDaoProxy = new UserDaoProxy(userDao);userDaoProxy.delete();} }總結:調用代理對象的方法來調用目標對象.需要注意的是,代理對象與目標對象要實現相同的接口,然后通過調用相同的方法來調用目標對象的方法。
1.可以做到在不修改目標對象的功能前提下,對目標功能擴展.
2.缺點:因為代理對象需要與目標對象實現一樣的接口,所以會有很多代理類,類太多.同時,一旦接口增加方法,目標對象與代理對象都要維護.
動態代理
動態代理特點:
1、代理對象,不需要實現接口
2、代理對象的生成,是利用JDK的API,動態的在內存中構建代理對象
jdk生成代理對象
JDK實現代理只需要使用Proxy.newProxyInstance方法,但是該方法需要接收三個參數,完整的寫法是:
static Object newProxyInstance(ClassLoader loader, Class<?>[]
interfaces,InvocationHandler h )
- ClassLoader loader,:指定當前目標對象使用類加載器,獲取加載器的方法是固定的
- Class<?>[] interfaces,:目標對象實現的接口的類型,使用泛型方式確認類型
- InvocationHandler h:事件處理,執行目標對象的方法時,會觸發事件處理器的方法,會把當前執行目標對象的方法作為參數傳入
示例代碼
創建UserDaoInvocationHandler類,實現InvocationHandler接口,這個類中持有一個被代理對象的實例target
創建代理工廠類
package com.sl.jdkproxy;import java.lang.reflect.Proxy;/*** @author shuliangzhao* @Title: ProxyFactory* @ProjectName spring-boot-learn* @Description: TODO* @date 2019/10/19 17:19*/ public class ProxyFactory {//維護一個目標對象private Object target;public ProxyFactory(Object target){this.target=target;}//給目標對象生成代理對象public Object getProxyInstance() {return Proxy.newProxyInstance(target.getClass().getClassLoader(),target.getClass().getInterfaces(),new UserDaoInvocationHandler(target));} }測試類App
package com.sl.jdkproxy;import com.sl.staticproxy.UserDao; import com.sl.staticproxy.UserDaoImpl;/*** @author shuliangzhao* @Title: App* @ProjectName spring-boot-learn* @Description: TODO* @date 2019/10/19 17:22*/ public class App {public static void main(String[] args) {UserDao userDao = new UserDaoImpl();UserDao proxyInstance = (UserDao) new ProxyFactory(userDao).getProxyInstance();System.out.println(proxyInstance.getClass());// 執行方法 【代理對象】proxyInstance.delete();} }總結:代理對象不需要實現接口,但是目標對象一定要實現接口,否則不能用動態代理
cglib代理
上面的靜態代理和動態代理模式都是要求目標對象是實現一個接口的目標對象,但是有時候目標對象只是一個單獨的對象,并沒有實現任何的接口,這個時候就可以使用以目標對象子類的方式類實現代理,這種方法就叫做:Cglib代理
Cglib是一個強大的高性能的代碼生成包,它可以在運行期擴展java類與實現java接口.它廣泛的被許多AOP的框架使用,例如Spring AOP和synaop,為他們提供方法的interception(攔截)
使用cglib代理需要注意:
1.代理的類不能為final,否則報錯
2.目標對象的方法如果為final/static,那么就不會被攔截,即不會執行目標對象額外的業務方法.
示例代碼:
被代理的對象UserDao
創建代理工廠類
public class ProxyFactory implements MethodInterceptor {//維護目標對象private Object target;public ProxyFactory(Object target) {this.target = target;}//給目標對象創建一個代理對象public Object getProxyInstance() {//1.工具類Enhancer enhancer = new Enhancer();//2.設置父類enhancer.setSuperclass(target.getClass());//3.設置回調函數enhancer.setCallback(this);//4.創建子類return enhancer.create();}@Overridepublic Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {System.out.println("開始事務...");//執行目標對象的方法Object returnValue = method.invoke(target, objects);System.out.println("提交事務...");return returnValue;} }測試類
public class App {public static void main(String[] args) {UserDao userDao = new UserDao();UserDao proxyInstance = (UserDao) new ProxyFactory(userDao).getProxyInstance();proxyInstance.delete();} }總結
以上是生活随笔為你收集整理的Java的代理模式之静态代理和动态代理的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: SpringBoot @Value、 @
- 下一篇: Spring BeanFactoryPo