一、前言:
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 + '\'' +
'}';
}
}
代码调试:
三、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);
}
}