欢迎光临散文网 会员登陆 & 注册

分享给大家Spring中两种动态代理(笔记留存,收藏备用)

2021-10-27 13:26 作者:爱三连真的会好运  | 我要投稿

动态代理

相较于静态代理,动态代理更为灵活,在程序运行期间产生代理类(动态生成不固定) 通过使用放射的机制

可以理解为全能中介的作用吧.代理行为均可以增强目标对象的行为

1.Jdk动态代理

和cglib的区别在于: 目标对象是否有接口的实现 若有就选择jdk动态代理

首先 自定义一个代理对象接口 我这里写的是ProxyInter  将目标对象实现这个接口

我将得到代理对象提取成一个类中的方法

public class JdkProxy {
   //目标对象
   private Object target;

   public JdkProxy(Object target) {
       this.target = target;
   }
/**
*
/**
    * ClassLoader loader 类加载器
    * Class[] interfaces 目标对象的接口数组
    *InvocationHandler是由代理实例的调用处理程序实现的接口。
    * 每个代理实例都有一个关联的调用处理程序。 当在代理实例上调用方法时,方法调用将被编码并分派到其调用处理    *程序的invoke方法
    * @return
    */
   public Object getProxy() {
       ClassLoader loader = this.getClass().getClassLoader();
       Class[] interfaces = target.getClass().getInterfaces();
       InvocationHandler invocationHandler = new InvocationHandler() {
           @Override
           public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
               Object result = method.invoke(target, args);

               return result;
           }
       };
       ;
       Object proxy = Proxy.newProxyInstance(loader, interfaces, invocationHandler);
       return proxy;

   }
}

这样做 主程序中只需要new出目标对象 将目标对象放入得到代理对象后  代理对象再执行其方法即可

public static void main(String[] args) {
   //目标对象
   Zhangsan zs = new Zhangsan();
   //得到代理对象类
   JdkProxy jdkProxy = new JdkProxy(zs);
   //得到代理对象
   ProxyInter proxy = (ProxyInter) jdkProxy.getProxy();
   //通过代理对象调用目标对象的方法
   proxy.method();
}
增强方式就是在 invocationHandler类中的invoke方法上下进行增强即可

2. Cglib动态代理

与jdk动态代理不同,他不需要实现接口类

运行过程中只会生成目标对象的子类Enhancer enhancer 运用继承的方式实现动态代理

首先 定义一个目标对象

public class Person {

    public  void eat(){

        System.out.println("吃饭...");

    }

}

想jdk代理一样 我们将方法提取到一个类中

public class CglibProxy {
   //目标对象
   private Object target;
   public CglibProxy(Object target) {
       this.target = target;
   }
   //得到代理对象
   public Object getProxy() {
       //得到目标类的代理类
       Enhancer enhancer = new Enhancer();
       //设置父类
       enhancer.setSuperclass(target.getClass());

       MethodInterceptor methodInterceptor = new MethodInterceptor() {
           /**
            * 当代理对象调用任意方法时 都会将调用信息传递到形参中
            * @param obj 代理对象
            * @param method 目标对象的方法
            * @param args 目标对象方法列表
            * @param proxy 子类中目标方法的引用
            * @return
            * @throws Throwable
            */
           @Override
           public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
               System.out.println("饭前洗手...");
               Object result = method.invoke(target, args);
               System.out.println("饭后洗碗...");
               return result;
           }
       };
       //设置Callback回调
       enhancer.setCallback(methodInterceptor);
       //生成类
       return enhancer.create();
   }
}

主程序我们执行

public class Starts {
   public static void main(String[] args) {
       //目标对象
       Person person = new Person();
       CglibProxy cglibProxy = new CglibProxy(person);
       Person proxy = (Person) cglibProxy.getProxy();
       proxy.eat();
   }
}

那么cglib动态代理完成了


3.两者的区别

在我看来,但凡目标对象有实现的接口就会选择jdk动态代理的方式,因为效率更高

没有接口只能借助第三方的cglib了(使用之前一定要配置pom哦)

<dependency>

    <groupId>cglib</groupId>

    <artifactId>cglib</artifactId>

    <version>2.2</version>

</dependency>


分享给大家Spring中两种动态代理(笔记留存,收藏备用)的评论 (共 条)

分享到微博请遵守国家法律