JDK动态代理与Cglib的区别

一、前言:

CGLIB(Code Generation Library)是一个开源项目,是一个强大的,高性能,高质量的Code生成类库。它可以在运行期扩展Java类与实现Java接口。cglib封装了asm,可以在运行期动态生成新的class,cglib用于AOP;

JDK动态代理,是java反射工具包自带的工具类;

简单对比:

从实现机制角度出发:

     1)JDK代理类需要实现InvocationHandler接口,重写invoke方法;

     2)相比JDK这个特征,cglib却没有这个限制, 可以是普通Java类,但是注意的是不能是非final Java类,cglib是通过继承来实现的代码增强,所代理类的方法不能使用private来修饰。

 

二、代码示例(话不多,一不如意就上源码)

    1、JDK动态代理,参考我的设计模式动态代理章节:https://blog.csdn.net/jason_jiahongfei/article/details/97048971

 

    2、我们重点说一下Cglib: 

package com.jason.reflect.cglib;

import com.jason.reflect.Student;
import net.sf.cglib.core.DebuggingClassWriter;
import net.sf.cglib.proxy.Enhancer;

/**
 * @program: mybatis
 * @description
 * @author: 大龄程序猿
 * @create: 2020-05-16 10:53
 **/
public class CglibObjectFactory {

    public static  T getProxyInstance(Class clazz) {
        Enhancer en = new Enhancer();
        // set target proxy
        en.setSuperclass(clazz);
        // set proxy interceptor
        en.setCallback(new CglibAroundAdvice());
        // create proxy instance
        T o = (T)en.create();
        //System.setProperty(DebuggingClassWriter.DEBUG_LOCATION_PROPERTY, "R:\\a.class");
        return o;//class com.jason.reflect.cglib.Student$$EnhancerByCGLIB$$5bca626a
    }

    public static void main(String[] args) {
           Student student=CglibObjectFactory.getProxyInstance(Student.class);
           student.getName();

           student.testCglib("helloword!");
    }
}
package com.jason.reflect.cglib;
import net.sf.cglib.core.DebuggingClassWriter;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;

import java.lang.reflect.Method;

/**
 * @program: mybatis
 * @description
 * @author: 大龄程序猿
 * @create: 2020-05-16 11:00
 **/
public class CglibAroundAdvice implements MethodInterceptor {
    public Object intercept(Object target, Method method, Object[] args,
                            MethodProxy proxy) throws java.lang.Throwable {
        System.out.println("-------before execute ,transaction start ...");
        //execute target object method and save target object return value
//		Object rvt = proxy.invokeSuper(target, new String[] { "new parameter" });
        Object rvt = proxy.invokeSuper(target, args);
        System.out.println("-------after execute, transaction end ...");
        System.setProperty(DebuggingClassWriter.DEBUG_LOCATION_PROPERTY, "R:\\");
        return rvt;
    }
}
package com.jason.reflect;

/**
 * @program: mybatis
 * @description
 * @author: 大龄程序猿
 * @create: 2020-05-14 20:04
 **/
public class Student {
     private long sid;
     private String name;
     private int age;
     private String remark;

    public long getSid() {
        return sid;
    }

    public void setSid(long sid) {
        this.sid = sid;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public String getRemark() {
        return remark;
    }

    public void setRemark(String remark) {
        this.remark = remark;
    }

    public void testCglib(String str)
    {
        System.out.println("cglib study  "+str);
    }

    @Override
    public String toString() {
        return "Student{" +
                "sid=" + sid +
                ", name='" + name + '\'' +
                ", age=" + age +
                ", remark='" + remark + '\'' +
                '}';
    }
}

 代码调试:

JDK动态代理与Cglib的区别_第1张图片

三、Spring-Ioc中动态代理,源码分析:

//使用初始化策略实例化Bean对象
	@Override
	public Object instantiate(RootBeanDefinition bd, @Nullable String beanName, BeanFactory owner) {
		// Don't override the class with CGLIB if no overrides.
		//如果Bean定义中没有方法覆盖,则就不需要CGLIB父类类的方法
		if (!bd.hasMethodOverrides()) {
			Constructor constructorToUse;
			synchronized (bd.constructorArgumentLock) {
				//获取对象的构造方法或工厂方法
				constructorToUse = (Constructor) bd.resolvedConstructorOrFactoryMethod;
				//如果没有构造方法且没有工厂方法
				if (constructorToUse == null) {
					//使用JDK的反射机制,判断要实例化的Bean是否是接口
					final Class clazz = bd.getBeanClass();
					if (clazz.isInterface()) {
						throw new BeanInstantiationException(clazz, "Specified class is an interface");
					}
					try {
						if (System.getSecurityManager() != null) {
							//这里是一个匿名内置类,使用反射机制获取Bean的构造方法
							constructorToUse = AccessController.doPrivileged(
									(PrivilegedExceptionAction>) () -> clazz.getDeclaredConstructor());
						}
						else {
							constructorToUse =	clazz.getDeclaredConstructor();
						}
						bd.resolvedConstructorOrFactoryMethod = constructorToUse;
					}
					catch (Throwable ex) {
						throw new BeanInstantiationException(clazz, "No default constructor found", ex);
					}
				}
			}
			//使用BeanUtils实例化,通过反射机制调用”构造方法.newInstance(arg)”来进行实例化
			return BeanUtils.instantiateClass(constructorToUse);
		}
		else {
			// Must generate CGLIB subclass.
			//使用CGLIB来实例化对象
			return instantiateWithMethodInjection(bd, beanName, owner);
		}
	}

 

你可能感兴趣的:(面试宝典)