日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

java反射学习(2):反射与代理模式

發布時間:2024/1/23 编程问答 15 豆豆
生活随笔 收集整理的這篇文章主要介紹了 java反射学习(2):反射与代理模式 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

一 基本代理設計模式

代理模式核心思路,一個接口有兩個子類,一個子類完成業務需求,另一個完成輔助功能

假設實現一個功能,張三吃飯

代碼如下:


接口 PersonDao.java

package com.learing._02;public interface PersonDao {public void eat();}
業務類 Person.java

package com.learing._02;/*** 業務類* */ public class Person implements PersonDao {private String name;public Person(String name) {this.name = name;} @Overridepublic void eat(){System.out.println(this.name + "吃飯");} }


測試類? Demo.java

package com.learing._02;public class Demo {public static void main(String args[]){PersonDao zhangsan = new Person("張三");zhangsan.eat();}}


輸出結果



現在增加一個需求,吃飯前要洗手,吃完飯后要洗碗,但是要求不能修改Person任何代碼情況下,完成該功能,那么需要一個輔助類來完成了


ProxyPerson.java

package com.learing._02;public class ProxyPerson implements PersonDao {private PersonDao personDao;public ProxyPerson bind(PersonDao personDao){this.personDao = personDao;return this;}@Overridepublic void eat() {this.beforeEat();this.personDao.eat();this.afterEat();}public void beforeEat(){System.out.println("吃飯前要洗手");}public void afterEat(){System.out.println("吃完飯要洗碗");} }
測試類?Demo.java?

package com.learing._02;public class Demo {public static void main(String args[]){PersonDao zhangsan = new ProxyPerson().bind(new Person("張三")) ;zhangsan.eat();}}
輸出結果



以上就是一個簡單代理的代理模式了,Person這個類實現eat()方法, ProxyPerson 這個輔助類實現 "吃飯前要洗手" 和?"吃飯前要洗手"這兩個功能,這樣

以后要添加什么功能,可以直接在?ProxyPerson代理中增加,而不用改變Person的任何代碼,那么這有什么用呢?舉個例子,在實際開發中,比如有個刪除數據功能,這個功能已經上線很久了,有一天領導說,要增加一個日志功能,那么創建一個輔助類,在這個輔助類中寫日志代碼,隔了一段時間候,領導又需要增加個某某功能啥的,嘿嘿。。。

但是這里存在一個問題,就是每一個業務類,都必須有一個輔助類(既代理類),假設有100個類都要求有吃飯前洗手和吃完飯后洗碗這兩個功能,那么就得寫100次,加入又新增了一個晚上7點散步功能,則100個代理類都要新增一個7點散步的功能方法,這簡直是一個噩夢啊,可以用JDK動態代理解決該問題.


二 JDK動態代理 (采用反射)

動態代理代碼 ?ProxyPerson.java

package com.learing._02;import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy;public class ProxyPerson implements InvocationHandler {private Object target ; //要代理對象(代替這100個業務類)public Object bind(Object target){this.target = target; //返回與當前傳入對象結構相同的代理對象return Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), this);}@Overridepublic Object invoke(Object proxy, Method method, Object[] args)throws Throwable {this.beforeEat();Object obj = method.invoke(this.target, args); //采用反射調用 eat()用method代理,并進行調用this.afterEat();return obj;}public void beforeEat(){System.out.println("吃飯前要洗手");}public void afterEat(){System.out.println("吃完飯要洗碗");}}
測試類? Demo.java

package com.learing._02;public class Demo {public static void main(String args[]){PersonDao zhangsan = (PersonDao) new ProxyPerson().bind(new Person("張三")) ;zhangsan.eat();}}

輸出結果



這里只建了一個類,采用反射,可以替代前面的100多個類,但JDK動態代理存在的問題,就是被代理的對象必須實現接口,而普通對象則不能代理,采用CGLIB對所有類都進行代理.


三 CGLIB動態代理

Person類

package com.learing._02;/*** 業務類* */ public class Person{private String name;public Person() {}public void eat(){System.out.println("吃飯");} }


CGLIB動態代理代碼 ?CGLIBProxyPerson.java

package com.learing._02;import java.lang.reflect.Method;import net.sf.cglib.proxy.Enhancer; import net.sf.cglib.proxy.MethodInterceptor; import net.sf.cglib.proxy.MethodProxy;public class CGLIBProxyPerson implements MethodInterceptor{private Object target; /** * 創建代理對象 * * @param target * @return */ public Object getInstance(Object target) { this.target = target; Enhancer enhancer = new Enhancer(); enhancer.setSuperclass(this.target.getClass()); // 回調方法 enhancer.setCallback(this); // 創建代理對象 return enhancer.create(); } @Overridepublic Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {this.beforeEat();proxy.invokeSuper(obj, args); this.afterEat();return obj; }public void beforeEat(){System.out.println("吃飯前要洗手");}public void afterEat(){System.out.println("吃完飯要洗碗");}}

測試類?Demo.java

package com.learing._02;public class Demo {public static void main(String args[]){Person zhangsan = (Person) new CGLIBProxyPerson().getInstance(new Person()) ;zhangsan.eat();}}
輸出結果


采用CGLIB對沒有實現接口的普通Person.java類進行代理






總結

以上是生活随笔為你收集整理的java反射学习(2):反射与代理模式的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。