1.代理模式readMe:
代理設計模式: 是java中常用的設計模式! 特點: 01.委托類和代理類有相同的接口或者共同的父類! 02.代理類為委托類負責處理消息,並將消息轉發給委托類! 03.委托類和代理類對象通常存在關聯關系! 一個代理類對象與一個委托類對象關聯! 04.代理類本身並不是真正的實現者!而是通過調用委托類的方法, 來實現功能! 按照代理類創建的時機,代理類分為兩種: 01.靜態代理:由我們程序猿或者特定的工具自動生成了源代碼, 在程序運行之前,.class文件已經存在了! (serviceImpl 調用了 dao層的方法! 真正的實現是Dao) 02.動態代理:在程序運行期間,通過反射的方式動態的創建出來! 按照我們的使用方式: 是由共同的接口還是公共的父類? 01.jdk動態代理 (接口) 必須知道一個類和一個接口 001.InvocationHandler接口只有一個方法 public Object invoke(Object proxy, Method method, Object[] args) throws Throwable; proxy:代理類對象 method:被代理的方法 args:被代理的方法的參數列表 002.Proxy 類: public static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces,InvocationHandler h)throws IllegalArgumentException loader:類加載器 interfaces:代理類實現的所有接口 h:InvocationHandler接口的一個實例 this當前對象 因為我們想使用jdk動態代理 必須是 代理類 實現 InvocationHandler! 它讓我們傳遞父接口 我們傳遞 自身! 02.cglib動態代理(接口+父類) 必須知道一個類和一個接口 001.MethodInterceptor接口 public Object intercept(Object obj, Method method,Object[] args,MethodProxy proxy) throws Throwable; intercept是所有攔截器執行的方法,類似於jdk動態代理中的invoke 002. Enhancer類 設置委托類和代理類的公共接口或者公共的父類 public void setSuperclass(Class superclass) { if (superclass != null && superclass.isInterface()) { setInterfaces(new Class[]{ superclass }); } else if (superclass != null && superclass.equals(Object.class)) { // affects choice of ClassLoader this.superclass = null; } else { this.superclass = superclass; } } 代理類執行完畢 通知委托類 public void setCallback(final Callback callback) { setCallbacks(new Callback[]{ callback }); } 在Enhancer類的父類AbstractClassGenerator中有一個方法 創建我們需要的代理類 protected Object create(Object key)
2.靜態代理:
01.接口代碼:
package cn.pb.dao; /** * 動物類 父接口 */ public interface Animal { //主業務 void eat(); void sleep(); }
02.實現類代碼:
package cn.pb.dao.impl; /** * 狗狗類 實現了Animal接口 */ import cn.pb.dao.Animal; public class Dog implements Animal { public void eat() { System.out.println("狗狗在啃骨頭!"); } public void sleep() { System.out.println("狗狗在午休!"); } }
03.靜態代理類:
package cn.pb.staticproxy; import cn.pb.dao.Animal; import cn.pb.dao.impl.Dog; /** * 狗狗的靜態代理類 */ public class AnimalStaticProxy implements Animal { private Dog dog; public void sleep() { System.out.println("主人在召喚"); //系統級業務 dog.sleep(); System.out.println("主人離開"); //系統級業務 } public void eat() { System.out.println("主人在召喚"); //系統級業務 dog.eat(); System.out.println("主人離開"); //系統級業務 } public Dog getDog() { return dog; } public void setDog(Dog dog) { this.dog = dog; } /** * 我們發現的問題 * 01:代碼冗余 * 02:把冗余的代碼提取成公共的方法 * 03:有可能小貓咪也有這些方法 * 04:提取成一個工具類中的方法 * 05:現在有一個小貓咪 也需要執行 sleep和eat 以及系統級業務方法 * 06:我們又得創建一個小貓咪對應的代理類 * 07:動物有很多 ,難道需要我們創建N個代理類嗎??肯定! */ }
04.測試類代碼:
/** * 靜態代理的測試方法 */ @Test public void testStaticProxy(){ AnimalStaticProxy proxy = new AnimalStaticProxy(); Dog dog=new Dog(); proxy.setDog(dog); proxy.eat(); System.out.println("*************"); proxy.sleep(); }
3.JDK動態代理:
01.接口代碼:
package cn.pb.dao; /** * 動物類 父接口 */ public interface Animal { //主業務 void eat(); void sleep(); }
02.實現類代碼:
package cn.pb.dao.impl; /** * 狗狗類 實現了Animal接口 */ import cn.pb.dao.Animal; public class Dog implements Animal { public void eat() { System.out.println("狗狗在啃骨頭!"); } public void sleep() { System.out.println("狗狗在午休!"); } }
03.動態代理類代碼:
package cn.pb.jdkdynamicproxy; /** * JDK的動態代理類 */ import cn.pb.dao.Animal; import cn.pb.dao.impl.Dog; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy; public class AnimalJdkDynamicProxy implements InvocationHandler { /** * 01.我們不確定委托類是誰?委托類的類型 是Object * 和委托類建立關聯關系 */ private Object target; /** * 02.給我一個委托類,我返回一個代理類對象 */ public Object createProxy(Object target){ //根據傳遞的參數 進行對象的關聯 this.target=target; return Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), this); } /** * * @param proxy :代理對象 * @param method :方法名 * @param args : 參數列表 * @return */ public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { System.out.println("主人在召喚"); //系統級業務 開始事務 Object result= method.invoke(target,args); // 主業務 System.out.println("主人離開"); //系統級業務 日志處理 關閉事務 return result; } //創建測試方法 public static void main(String[] args) { AnimalJdkDynamicProxy proxy=new AnimalJdkDynamicProxy(); Animal dog= (Animal) proxy.createProxy(new Dog()); dog.eat(); System.out.println("**************************"); dog.sleep(); } }
04.測試代碼:
@Test public void testJdkDynamicProxy(){ AnimalJdkDynamicProxy proxy=new AnimalJdkDynamicProxy(); Animal dog= (Animal) proxy.createProxy(new Dog()); dog.eat(); System.out.println("**************************"); dog.sleep(); }
4.cglib動態代理:
01.接口代碼:
package cn.pb.dao; /** * 動物類 父接口 */ public interface Animal { //主業務 void eat(); void sleep(); }
02.實現類代碼:
package cn.pb.dao.impl; /** * 狗狗類 實現了Animal接口 */ import cn.pb.dao.Animal; public class Dog implements Animal { public void eat() { System.out.println("狗狗在啃骨頭!"); } public void sleep() { System.out.println("狗狗在午休!"); } }
03.動態代理類代碼:
package cn.pb.cglibdynamicproxy; /** * Cglib動態代理 */ import cn.pb.dao.Animal; import cn.pb.dao.impl.Dog; import net.sf.cglib.proxy.Enhancer; import net.sf.cglib.proxy.MethodInterceptor; import net.sf.cglib.proxy.MethodProxy; import java.lang.reflect.Method; public class AnimalCglibDynamicProxy implements MethodInterceptor { /** * 在enhancer中有一個setCallBack(this) * 這樣就實現了代理類和委托類的關聯 */ private Enhancer enhancer=new Enhancer(); /** * 創建代理類對象 */ public Object createProxy(Class clazz){ //設置公共的接口或者公共的類 enhancer.setSuperclass(clazz); //建立關聯關系 enhancer.setCallback(this); return enhancer.create(); } /** * 類似於我們jdk中的invoke */ public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable { System.out.println("主人在召喚"); //系統級業務 開始事務 Object result= proxy.invokeSuper(obj,args); // 主業務 System.out.println("主人離開"); //系統級業務 日志處理 關閉事務 return result; } //創建測試方法 public static void main(String[] args) { AnimalCglibDynamicProxy proxy=new AnimalCglibDynamicProxy(); //這里的參數可以傳三種形式01:new Dog().getClass() // 02:Class.forName("cn.pb.dao.impl.Dog") 03.Dog.class Animal dog= (Animal) proxy.createProxy(new Dog().getClass()); dog.eat(); System.out.println("**************************"); dog.sleep(); } }
04.測試代碼:
@Test public void testCglibDynamicProxy(){ AnimalJdkDynamicProxy proxy=new AnimalJdkDynamicProxy(); Animal dog= (Animal) proxy.createProxy(new Dog()); dog.eat(); System.out.println("**************************"); dog.sleep(); }