zoukankan      html  css  js  c++  java
  • 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 }

  • 相关阅读:
    “随手记”APP与已经发布的记账软件“鲨鱼记账”的差距
    团队绩效打分
    “随手记”改进方案
    “随手记”第一阶段成果展示
    “随手记”意见整理
    针对每个团队的项目意见或建议
    “随手记”开发记录day10
    团队十日冲刺8
    团队十日冲刺7
    团队十日冲刺6
  • 原文地址:https://www.cnblogs.com/jiaqingshareing/p/9355796.html
Copyright © 2011-2022 走看看