java反射学习(2):反射与代理模式
一 基本代理設計模式
代理模式核心思路,一個接口有兩個子類,一個子類完成業務需求,另一個完成輔助功能
假設實現一個功能,張三吃飯
代碼如下:
接口 PersonDao.java
業務類 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 + "吃飯");} }
package com.learing._02;public class Demo {public static void main(String args[]){PersonDao zhangsan = new Person("張三");zhangsan.eat();}}
輸出結果
現在增加一個需求,吃飯前要洗手,吃完飯后要洗碗,但是要求不能修改Person任何代碼情況下,完成該功能,那么需要一個輔助類來完成了
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
測試類?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();}}輸出結果
總結
以上是生活随笔為你收集整理的java反射学习(2):反射与代理模式的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: java反射学习(1):反射的基本操作
- 下一篇: (1)hibenrate入门例子