zoukankan      html  css  js  c++  java
  • cglib的使用

       cglib大名在java界如雷贯耳,众多优秀的开源项目均使用其来实现各自的功能(spring aop,hibernate等等),这里主要简单介绍一下cglib的使用,对比一下java原生的proxy还有javaassist. 

      说到cglib第一印象就是动态代理(啥是动态代理?请百度<设计模式>),没错,这是它牛逼的功能之一,

    使用cglib构建动态代理核心类就是Enhancer,作用如其名:增强.它能够对目标类的方法进行增强.上代码:

    /**
     * Created by wally on 3/1/18.
     */
    public abstract class Animal {
    
        private String name;
    
        public Animal() {
        }
    
        public Animal(String name) {
            this.name = name;
        }
    
        public abstract void  eat();
    
        public void live(){
    
            System.out.println("i'm " + name);
    
            eat();
    
        }
    }
    
    public class Duck extends Animal {
    
        public Duck() {
        }
    
        public Duck(String name) {
            super(name);
        }
    
        @Override
        public void eat() {
            System.out.println("i'm eat fish!");
        }
    }
    
    /**
     * Created by wally on 3/1/18.
     */
    public class ProxyCreator {
    
    
        public static <T> T createProxy(Class<T> target,T instance){
            Enhancer enhancer = new Enhancer();
            enhancer.setSuperclass(target);
            CallbackHelper callbackHelper = new CallbackHelper(Duck.class,new Class[0]) {
                @Override
                protected Object getCallback(Method method) {
                    if(method.getName().equals("live")){
                        return NoOp.INSTANCE;
                    }
                    return new DuckProxy();
                }
            };
            enhancer.setCallbackFilter(callbackHelper);
            enhancer.setCallbacks(callbackHelper.getCallbacks());
            return (T)enhancer.create(new Class[]{String.class},new String[]{"唐老鸭"});
        }
    }

    /**
    * Created by wally on 3/1/18.
    */
    public class Starter {
    public static void main(String[] args) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
    Duck duck = ProxyCreator.createProxy(Duck.class,null);
    duck.live();
    }
    }
     

    上述栗子的输出:

    i'm 唐老鸭
    say gua gua!
    i'm eat fish!

    可以看到Duck类的eat行为发生变化了。在不调整原有代码的基础上改变原有对象的行为(严格意义上原有行为并没有变,只是包装了一层,是的,装饰者模式可以看做一种特殊的代理!)。这有什么用呢,我们来看一下大家都是怎么用的。

    在hibernate中,使用cglib对bean进行代理,从而实现延迟加载,我们会发现,hibernate正真执行sql的时候往往不是我们调用查询方法的时候,而是在调用查询结果的时候采取真正执行。

    在spring中,当我们通过注解@EnableAspectJAutoProxy开启aop时,可以指定是使用java原生proxy还是使用cglib,通过设置proxyTargetClass=true/false(使用cglib/使用java proxy).

    通过代理,可以将业务逻辑与通用逻辑解耦,例如日志打印,数据库链接等等。

    cglib除了强大的动态代理,还有一个功能:动态生成对象

    /**
     * Created by wally on 3/1/18.
     */
    public class Beangenerator {
    
    
        public static Object generateBean(Map<String, Class<?>> params, Class<?> superClass) {
            BeanGenerator generator = new BeanGenerator();
            if (params != null && params.size() != 0) {
                params.forEach(generator::addProperty);
            }
            if (superClass != null)
                generator.setSuperclass(superClass);
            return generator.create();
        }
    }

    cglib是对ASM的封装,ASM是一个字节码生成工具,所以cglib可以实现动态字节码生成,上面栗子通过BeanGenerator实例来生成指定属性的对象,该对象会自带setter和getter方法,可以通过反射获取。

    值得一提的是,由于cglib是生成字节码,我们知道java的类信息释放在permanent edition中的,通过cglib生成的类信息也不例外,所以在使用cglib生成代理类或者bean时,需要注意,平凡的创建有可能导致pem 区的oom。

    java proxy对比cglib:

    java proxy由于是java自身支持的,在生成代理类时速度比cglib快,但是cglib是通过插入字节码来实现代理的,在调用速度上cglib要比java proxy快

    在功能上,java proxy仅仅支持接口级别的代理,而cglib没有这个限制,目标类可以是接口可以是普通类,并且可以精确到方法级别(上面的栗子可以看出)。

  • 相关阅读:
    Python学习笔记(三)
    自己出的一套前端笔试题
    Vue 数组封装和组件data定义为函数一些猜测
    前端Mvvm QC 上传了测试版
    为什么我们的web前端变的越来越复杂
    grootJsAPI文档
    grootjs 简明教程
    深入grootJs(进阶教程)
    也议 js闭包和ie内存泄露原理
    此utf8 非彼utf8 ——谈http协议里的编码问题
  • 原文地址:https://www.cnblogs.com/foreveravalon/p/8489907.html
Copyright © 2011-2022 走看看