java反射学习(2):反射与代理模式
一 基本代理設(shè)計模式
代理模式核心思路,一個接口有兩個子類,一個子類完成業(yè)務(wù)需求,另一個完成輔助功能
假設(shè)實現(xiàn)一個功能,張三吃飯
代碼如下:
接口 PersonDao.java
業(yè)務(wù)類 Person.java
package com.learing._02;/*** 業(yè)務(wù)類* */ 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();}}
輸出結(jié)果
現(xiàn)在增加一個需求,吃飯前要洗手,吃完飯后要洗碗,但是要求不能修改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();}}
輸出結(jié)果
以上就是一個簡單代理的代理模式了,Person這個類實現(xiàn)eat()方法, ProxyPerson 這個輔助類實現(xiàn) "吃飯前要洗手" 和?"吃飯前要洗手"這兩個功能,這樣
以后要添加什么功能,可以直接在?ProxyPerson代理中增加,而不用改變Person的任何代碼,那么這有什么用呢?舉個例子,在實際開發(fā)中,比如有個刪除數(shù)據(jù)功能,這個功能已經(jīng)上線很久了,有一天領(lǐng)導(dǎo)說,要增加一個日志功能,那么創(chuàng)建一個輔助類,在這個輔助類中寫日志代碼,隔了一段時間候,領(lǐng)導(dǎo)又需要增加個某某功能啥的,嘿嘿。。。
但是這里存在一個問題,就是每一個業(yè)務(wù)類,都必須有一個輔助類(既代理類),假設(shè)有100個類都要求有吃飯前洗手和吃完飯后洗碗這兩個功能,那么就得寫100次,加入又新增了一個晚上7點散步功能,則100個代理類都要新增一個7點散步的功能方法,這簡直是一個噩夢啊,可以用JDK動態(tài)代理解決該問題.
二 JDK動態(tài)代理 (采用反射)
動態(tài)代理代碼 ?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個業(yè)務(wù)類)public Object bind(Object target){this.target = target; //返回與當(dāng)前傳入對象結(jié)構(gòu)相同的代理對象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); //采用反射調(diào)用 eat()用method代理,并進(jìn)行調(diào)用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();}}
輸出結(jié)果
這里只建了一個類,采用反射,可以替代前面的100多個類,但JDK動態(tài)代理存在的問題,就是被代理的對象必須實現(xiàn)接口,而普通對象則不能代理,采用CGLIB對所有類都進(jìn)行代理.
三 CGLIB動態(tài)代理
Person類
package com.learing._02;/*** 業(yè)務(wù)類* */ public class Person{private String name;public Person() {}public void eat(){System.out.println("吃飯");} }
CGLIB動態(tài)代理代碼 ?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();}}輸出結(jié)果
總結(jié)
以上是生活随笔為你收集整理的java反射学习(2):反射与代理模式的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: java反射学习(1):反射的基本操作
- 下一篇: (1)hibenrate入门例子