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

    运行时创建一个对象

  • 相关阅读:
    springboot文件上传: 单个文件上传 和 多个文件上传
    Eclipse:很不错的插件-devStyle,将你的eclipse变成idea风格
    springboot项目搭建:结构和入门程序
    POJ 3169 Layout 差分约束系统
    POJ 3723 Conscription 最小生成树
    POJ 3255 Roadblocks 次短路
    UVA 11367 Full Tank? 最短路
    UVA 10269 Adventure of Super Mario 最短路
    UVA 10603 Fill 最短路
    POJ 2431 Expedition 优先队列
  • 原文地址:https://www.cnblogs.com/strongmore/p/13510530.html
Copyright © 2011-2022 走看看