1、靜態代理java
根據被代理的類的時機的不一樣,若是在編譯階段就能肯定下來的被代理的類是哪個,那麼,就可使用靜態代理的方式。ide
申明一個接口:this
1 /** 2 * @author jiaqing.xu@hand-china.com 3 * @version 1.0 4 * @name 5 * @description 6 * @date 2018/7/23 7 */ 8 public interface Person { 9 void sayHello(String content, int age); 10 }
實現類,即須要被代理的類:spa
1 /** 2 * @author jiaqing.xu@hand-china.com 3 * @version 1.0 4 * @name 5 * @description 須要被代理的類 實現接口 6 * @date 2018/7/23 7 */ 8 public class Student implements Person { 9 @Override 10 public void sayHello(String content, int age) { 11 System.out.println("student say hello " + content + " "+ age); 12 } 13 }
實現類:代理
1 /** 2 * @author jiaqing.xu@hand-china.com 3 * @version 1.0 4 * @name 5 * @description 6 * @date 2018/7/23 7 */ 8 public class StaticProxyTest implements Person{ 9 //接口對象 10 private Person o; 11 12 public StaticProxyTest(Person o){ 13 this.o = o; 14 } 15 16 public static void main(String[] args) { 17 // TODO Auto-generated method stub 18 //s爲被代理的對象,某些狀況下 咱們不但願修改已有的代碼,咱們採用代理來間接訪問 19 //在代理類中引入被代理的對象 20 Student s = new Student(); 21 //建立代理類對象 s是接口的實例 22 StaticProxyTest proxy = new StaticProxyTest(s); 23 //調用代理類對象的方法 24 proxy.sayHello("welcome to java", 20); 25 } 26 27 @Override 28 public void sayHello(String content, int age) { 29 // TODO Auto-generated method stub 30 System.out.println("ProxyTest sayHello begin"); 31 //在代理類的方法中 間接訪問被代理對象的方法 32 o.sayHello(content, age); 33 System.out.println("ProxyTest sayHello end"); 34 } 35 }
2、動態代理code
若是不能在代碼的編譯階段就去肯定須要代理的類是哪個的話,就可使用類的動態代理機制,在代碼運行期間去動態加載類的信息。對象
Java動態代理和Cglib方式的代理的重要區別:blog
Java動態代理只能對接口進行代理,若是要代理的類是一個普通的類,沒有接口則須要使用Cglib來實現。
Java動態代理是利用反射機制生成一個實現代理接口的匿名類,在調用具體方法前調用InvokeHandler來處理。
Cglib動態代理是利用asm開源包,對代理對象類的class文件加載進來,經過修改其字節碼生成子類來處理。接口
建立接口:ip
1 /** 2 * @author jiaqing.xu@hand-china.com 3 * @version 1.0 4 * @name 5 * @description 6 * @date 2018/7/23 7 */ 8 public interface IStudent { 9 void action(); 10 }
1 /** 2 * @author jiaqing.xu@hand-china.com 3 * @version 1.0 4 * @name 5 * @description 6 * @date 2018/7/23 7 */ 8 public class StudentImpl implements IStudent{ 9 @Override 10 public void action() { 11 System.out.println("Student action"); 12 } 13 }
基於jdk的動態代理 該動態代理必定要實現InvocationHandler
1 /** 2 * @author jiaqing.xu@hand-china.com 3 * @version 1.0 4 * @name 5 * @description 基於jdk的動態代理 該動態代理必定要實現InvocationHandler 6 * @date 2018/7/23 7 */ 8 public class JavaProxy implements InvocationHandler { 9 private Object target; 10 11 /** 12 * 綁定委託對象並返回一個代理類 13 * 14 * @param target 15 * @return 16 */ 17 public Object bind(Object target) { 18 this.target = target; 19 return Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), this); // 要綁定接口 20 } 21 22 @Override 23 public Object invoke(Object proxy, Method method, Object[] args) 24 throws Throwable { 25 Object result; 26 //在這裏能夠作攔截前的操做 27 System.out.println("【java代理】調用實際方法前"); 28 // 執行方法 29 result = method.invoke(target, args); 30 //在這裏能夠作攔截後的操做 31 System.out.println("【java代理】調用實際方法後"); 32 return result; 33 } 34 }
1 /** 2 * @author jiaqing.xu@hand-china.com 3 * @version 1.0 4 * @name 5 * @description 6 * @date 2018/7/23 7 */ 8 public class TestProxy { 9 public static void main(String[] args) { 10 //建立代理對象 11 JavaProxy proxy = new JavaProxy(); 12 //綁定接口對象 13 IStudent student = (IStudent) proxy.bind(new StudentImpl()); 14 //調用接口方法 15 student.action(); 16 } 17 }
3、基於cglib的動態代理
能夠對任何的普通類進行代理
1 /** 2 * @author jiaqing.xu@hand-china.com 3 * @version 1.0 4 * @name 5 * @description 一個普通類 6 * @date 2018/7/23 7 */ 8 public class StudentImpl { 9 public void action() { 10 System.out.println("[Student]實際方法。。。"); 11 } 12 }
代理類要去實現MethosInterceptor接口:
1 /** 2 * @author jiaqing.xu@hand-china.com 3 * @version 1.0 4 * @name 5 * @description 6 * @date 2018/7/23 7 */ 8 public class CgLibProxy implements MethodInterceptor { 9 private Object target; 10 11 /** 12 * 建立代理對象 13 * 14 * @param target 15 * @return 16 */ 17 public Object getInstance(Object target) { 18 this.target = target; 19 Enhancer enhancer = new Enhancer(); 20 enhancer.setSuperclass(this.target.getClass()); 21 // 回調方法 22 enhancer.setCallback(this); 23 // 建立代理對象 24 return enhancer.create(); 25 } 26 27 // 回調方法 攔截方法 在調用具體的業務邏輯前和後 進行其餘的相關處理 28 @Override 29 public Object intercept(Object obj, Method method, Object[] args, 30 MethodProxy proxy) throws Throwable { 31 System.out.println("[cglib代理]調用實際方法前"); 32 proxy.invokeSuper(obj, args); 33 System.out.println("[cglib代理]調用實際方法後"); 34 return null; 35 } 36 }
1 /** 2 * @author jiaqing.xu@hand-china.com 3 * @version 1.0 4 * @name 5 * @description 6 * @date 2018/7/23 7 */ 8 public class TestProxy { 9 public static void main(String[] args) { 10 CgLibProxy cglib = new CgLibProxy(); 11 StudentImpl student = (StudentImpl) cglib.getInstance(new StudentImpl()); 12 student.action(); 13 } 14 }