cglib介绍

  CGLIB包的底层是通过使用一个小而快的字节码处理框架ASM,来转换字节码并生成新的类。除了CGLIB包,脚本语言例如Groovy和BeanShell,也是使用ASM来生成java的字节码。JDK动态代理只能代理实现了接口有类,而cglib没有这个限制。

  cglib代理原理是对指定的目标类生成一个子类,并覆盖其中方法实现增强,但因为采用的是继承,所以不能对final修饰的类进行代理。

使用方法:

public interface PersonBean {
    String getName();
    void   setName(String name);
}

//没有实现PersonBean接口
public class PersonBean2 {
    private String name;
    
    public String getName() {
        // TODO Auto-generated method stub
        return this.name;
    }

    public void setName(String name) {
        // TODO Auto-generated method stub
        this.name = name;
    }
}

public class ProxyByCGLIB implements MethodInterceptor{
    private Enhancer enhancer = new Enhancer();
    /**
     * 获得代理
     * @param clazz 目标对象类
     * @return 代理对象
     */
    public Object getProxy(Class clazz) {
        enhancer.setSuperclass(clazz); //设置需要创建子类的类
        enhancer.setCallback(this);
        return enhancer.create();   //通过字节码技术动态创建子类实例
    }
    
    @Override
    public Object intercept(Object obj, Method method, Object[] args,
            MethodProxy proxy) throws Throwable {
        // TODO Auto-generated method stub
        System.out.println("dynamic invoke begin...");
        Object result= proxy.invokeSuper(obj, args); // 通过代理类调用父类中的方法    
        System.out.println("before dynamic end...");
        return result;
    }

}
public class ProxyByCGLIBTest {

    /**
     * @param args
     */
    public static void main(String[] args) {
        // TODO Auto-generated method stub
        ProxyByCGLIB proxyByCGLIB = new ProxyByCGLIB();
        PersonBeanImpl proxy = (PersonBeanImpl) proxyByCGLIB.getProxy(PersonBeanImpl.class);
        
        proxy.setName("aaa");
        System.out.println(proxy.getName());
    }

}

 

 

 

cglib源码

    1、通过AbstractClassGenerator类的create()生成代理类字节码,并加载到JVM中,类似JDK动态代理生成过程

protected Object create(Object key) {
        try {
            Class gen = null;
            
            synchronized (source) {
                ClassLoader loader = getClassLoader();
                Map cache2 = null;
                cache2 = (Map)source.cache.get(loader);
                if (cache2 == null) {
                    cache2 = new HashMap();
                    cache2.put(NAME_KEY, new HashSet());
                    source.cache.put(loader, cache2);
                } else if (useCache) {
                    Reference ref = (Reference)cache2.get(key);
                    gen = (Class) (( ref == null ) ? null : ref.get()); 
                }
                if (gen == null) {
                    Object save = CURRENT.get();
                    CURRENT.set(this);
                    try {
                        this.key = key;
                        
                        if (attemptLoad) {
                            try {
                                gen = loader.loadClass(getClassName());
                            } catch (ClassNotFoundException e) {
                                // ignore
                            }
                        }
                        if (gen == null) {
                //生成字节码,并加载到JVM
byte[] b = strategy.generate(this); String className = ClassNameReader.getClassName(new ClassReader(b)); getClassNameCache(loader).add(className); gen = ReflectUtils.defineClass(className, b, loader); } if (useCache) { cache2.put(key, new WeakReference(gen)); } return firstInstance(gen); } finally { CURRENT.set(save); } } } return firstInstance(gen); } catch (RuntimeException e) { throw e; } catch (Error e) { throw e; } catch (Exception e) { throw new CodeGenerationException(e); } }