• CGLIB实现动态代理


    介绍

    cglib是一个强大的,受欢迎的,高性能的代码生成类库,它的底层就是asm(字节码框架),可以用来动态修改class和创建class,Spring AOP实现动态代理的一种方式就是cglib,hibernate使用cglib对持久化对象创建代理。

    实现动态代理

    引入maven依赖

    <dependency>
       <groupId>cglib</groupId>
       <artifactId>cglib</artifactId>
       <version>3.3.0</version>
    </dependency>
    

    实现

    public class Client {
      public static void main(String[] args) {
    //设置cglib生成的源码目录
        System.setProperty(DebuggingClassWriter.DEBUG_LOCATION_PROPERTY, "D:\");
        Enhancer enhancer = new Enhancer();
    //设置父类
        enhancer.setSuperclass(Singer.class);
    //设置方法拦截处理器
        enhancer.setCallback(new SingerMethodInterceptor());
    //创建代理对象
        Singable singable = (Singable) enhancer.create();
        singable.sing();
      }
    
      public static class SingerMethodInterceptor implements MethodInterceptor {
    
        @Override
        public Object intercept(Object obj, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
          System.out.println("cglib before");
          Object result = methodProxy.invokeSuper(obj, objects);
          System.out.println("cglib after");
          return result;
        }
      }
    }
    

    输出结果为

    cglib before
    I am singing...
    cglib after
    

    可以看到确实实现了动态代理的功能,JDK动态代理创建的类默认继承Proxy类,所以不能继承其他类,cglib没有这个限制,可以通过继承类的方式代理类。
    方法拦截器的参数依次为:

    1. obj,表示创建的代理对象
    2. method,代理的方法,如sing
    3. objects,方法参数
    4. methodProxy,封装了代理方法,代理对象和原对象

    创建不可变对象

    public class Client {
      public static void main(String[] args) {
        User user = new User("lisi");
    //根据user对象创建一个不可变对象
        User immutableUser = (User) ImmutableBean.create(user);
        System.out.println(immutableUser);
    //当我们修改了原对象,不可变对象也被修改了
        user.setName("lisi3");
        System.out.println(immutableUser);
        immutableUser.setName("lisi2");
        System.out.println(immutableUser);
      }
    
      @Getter
      @Setter
      @AllArgsConstructor
      @NoArgsConstructor
      @ToString
      public static class User {
    
        private String name;
      }
    }
    

    当我们修改不可变对象时,会抛出异常

    Exception in thread "main" java.lang.IllegalStateException: Bean is immutable
    	at com.imooc.sourcecode.java.dynamicproxy.cglib.test2.Client$User$$ImmutableBeanByCGLIB$$98871c2c.setName(<generated>)
    	at com.imooc.sourcecode.java.dynamicproxy.cglib.test2.Client.main(Client.java:17)
    

    但是如果我们修改原对象,那么不可变对象也会相应的被修改。这是因为不可变对象是通过继承原类,然后重写Getter,setter方法实现的,Getter直接调用原对象的Getter,setter直接抛出异常。

    对象生成器

    public class Client {
      public static void main(String[] args) throws Exception {
        BeanGenerator beanGenerator = new BeanGenerator();
        beanGenerator.addProperty("name", String.class);
        Object bean = beanGenerator.create();
        Method setNameMethod = bean.getClass().getMethod("setName", String.class);
        setNameMethod.invoke(bean,"lisi");
        Method getNameMethod = bean.getClass().getMethod("getName");
        System.out.println(getNameMethod.invoke(bean));
      }
    }
    

    运行时创建一个对象

  • 相关阅读:
    树上倍增求LCA(最近公共祖先)
    NOI题库分治算法刷题记录
    NOI题库刷题日志 (贪心篇题解)
    O(nlogn)LIS及LCS算法
    BLOG搬家
    『素数 Prime判定和线性欧拉筛法 The sieve of Euler』
    『扩展欧几里得算法 Extended Euclid』
    『NOIP2018普及组题解』
    P25、面试题1:赋值运算符函数
    字符串转成整数
  • 原文地址:https://www.cnblogs.com/strongmore/p/13510530.html
Copyright © 2020-2023  润新知