Java靜態代理&動態代理&Cglib代理詳解

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 }

相關文章
相關標籤/搜索