Java静态代理&动态代理&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 interface Person {
 9     void sayHello(String content, int age);
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 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 }

二、动态代理

如果不能在代码的编译阶段就去确定需要代理的类是哪一个的话,就可以使用类的动态代理机制,在代码运行期间去动态加载类的信息。

Java动态代理和Cglib方式的代理的重要区别:

Java动态代理只能对接口进行代理,如果要代理的类是一个普通的类,没有接口则需要使用Cglib来实现。
Java动态代理是利用反射机制生成一个实现代理接口的匿名类,在调用具体方法前调用InvokeHandler来处理。
Cglib动态代理是利用asm开源包,对代理对象类的class文件加载进来,通过修改其字节码生成子类来处理。

创建接口:

 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 }

三、基于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 }

原文地址:https://www.cnblogs.com/jiaqingshareing/p/9355796.html