1. 首先建一个目标类Dao
public class Dao {
public void update(String name) {
System.out.println("Dao.update()");
}
public void select() {
System.out.println("Dao.select()");
}
}
2. 实现一个方法拦截器DaoProxy
/**
* cglib实现动态代理,对被代理对象方法进行拦截
*
*/
public class DaoProxy implements MethodInterceptor {
/**
* Object:cglib生成的代理对象
* Method:被代理对象的方法
* Object[]:方法参数
* MethodProxy:代理对象的方法
*/
@Override
public Object intercept(Object object, Method method, Object[] objects, MethodProxy proxy) throws Throwable {
System.out.println("Before Method Invoke");
proxy.invokeSuper(object, objects);
System.out.println("After Method Invoke");
return object;
}
}
3. 创建代理对象
public class CglibTest {
public static void main(String[] args) {
// 生成的代理类文件存入本地磁盘
System.setProperty(DebuggingClassWriter.DEBUG_LOCATION_PROPERTY, "D:\\IdeaProjects\\demo\\com\\cglib");
// 通过CGLIB动态代理获取代理对象的过程
Enhancer enhancer = new Enhancer();
// 设置enhancer对象的父类
enhancer.setSuperclass(Dao.class);
// 设置enhancer的回调对象
enhancer.setCallback(new DaoProxy());
// 创建代理对象
Dao dao = (Dao)enhancer.create();
// // 通过代理对象调用目标方法
dao.update("yukang");
dao.select();
}
}
4. 输出结果
Before Method Invoke
Dao.update()
After Method Invoke
Before Method Invoke
Dao.select()
After Method Invoke
1. 设置父类(目标类)、设置回调对象(方法拦截器),并生成代理类的字节码文件
2. 使用ClassLoader将字节码文件加载到JVM
3. 创建代理类实例对象,执行对象的目标方法
自定义的方法拦截器要实现该接口,重写intercept
方法
public class DaoProxy implements MethodInterceptor {
/**
* Object:cglib生成的代理对象
* Method:被代理对象方法
* Object[]:方法入参
* MethodProxy:代理的方法
*/
@Override
public Object intercept(Object object, Method method, Object[] objects, MethodProxy proxy) throws Throwable {
System.out.println("Before Method Invoke");
proxy.invokeSuper(object, objects);
System.out.println("After Method Invoke");
return object;
}
}
// 通过CGLIB动态代理获取代理对象的过程
Enhancer enhancer = new Enhancer();
// 设置enhancer对象的父类
enhancer.setSuperclass(Dao.class);
// 设置enhancer的回调对象
enhancer.setCallback(new DaoProxy());
// 创建代理对象
Dao dao = (Dao)enhancer.create();
Enhancer有个静态代码块会被先执行,然后执行create()
public Object create() {
this.classOnly = false;
this.argumentTypes = null;
return this.createHelper();
}
private Object createHelper() {
// 验证,不重要
this.validate();
if (this.superclass != null) {
this.setNamePrefix(this.superclass.getName());
} else if (this.interfaces != null) {
this.setNamePrefix(this.interfaces[ReflectUtils.findPackageProtected(this.interfaces)].getName());
}
// Enhancer.EnhancerKey KEY_FACTORY在静态代码块中被初始化,通过CGLIB动态生成的实现类
// 父类使用EnhancerKey创建对象
return super.create(KEY_FACTORY.newInstance(this.superclass != null ? this.superclass.getName() : null, ReflectUtils.getNames(this.interfaces), this.filter, this.callbackTypes, this.useFactory, this.interceptDuringConstruction, this.serialVersionUID));
}
protected Object create(Object key) {
try {
Class gen = null;
AbstractClassGenerator.Source var3 = this.source;
synchronized(this.source) {
// 获取加载器,就是Enhancer.EnhancerKey的类加载器
ClassLoader loader = this.getClassLoader();
Map cache2 = null;
// 使用WeakHashMap缓存,以classLoader为key
cache2 = (Map)this.source.cache.get(loader);
if (cache2 == null) {
cache2 = new HashMap();
((Map)cache2).put(NAME_KEY, new HashSet());
this.source.cache.put(loader, cache2);
} else if (this.useCache) {
Reference ref = (Reference)((Map)cache2).get(key);
gen = (Class)(ref == null ? null : ref.get());
}
// 缓存中如果存在该代理类,则直接返回代理类对象
if (gen == null) {
Object save = CURRENT.get();
CURRENT.set(this);
Object var24;
try {
this.key = key;
// 第一次attemptLoad为false
if (this.attemptLoad) {
try {
// 使用ClassLoader加载到JVM
gen = loader.loadClass(this.getClassName());
} catch (ClassNotFoundException var17) {
;
}
}
if (gen == null) {
// 生成字节,经过这里attemptLoad变为true,会再次执行create(Object key)方法
byte[] b = this.strategy.generate(this);
// 生成类名称
String className = ClassNameReader.getClassName(new ClassReader(b));
// 放入缓存
this.getClassNameCache(loader).add(className);
// 反射生成代理类class
gen = ReflectUtils.defineClass(className, b, loader);
}
if (this.useCache) {
((Map)cache2).put(key, new WeakReference(gen));
}
// 实例化代理类对象,在Enhance中执行
var24 = this.firstInstance(gen);
} finally {
CURRENT.set(save);
}
return var24;
}
}
return this.firstInstance(gen);
} catch (RuntimeException var20) {
throw var20;
} catch (Error var21) {
throw var21;
} catch (Exception var22) {
throw new CodeGenerationException(var22);
}
}
生成字节码byte[] b = this.strategy.generate(this);
public byte[] generate(ClassGenerator cg) throws Exception {
ClassWriter cw = this.getClassWriter();
this.transform(cg).generateClass(cw);
return this.transform(cw.toByteArray());
}
其中getClassWriter();
protected ClassWriter getClassWriter() throws Exception {
return new DebuggingClassWriter(true);
}
DebuggingClassWriter重写了toByteArray()
方法,调用父类ClassWriter的toByteArray()
方法生成字节
public byte[] toByteArray() {
return (byte[])AccessController.doPrivileged(new PrivilegedAction() {
public Object run() {
byte[] b = DebuggingClassWriter.super.toByteArray();
if (DebuggingClassWriter.debugLocation != null) {
String dirs = DebuggingClassWriter.this.className.replace('.', File.separatorChar);
try {
(new File(DebuggingClassWriter.debugLocation + File.separatorChar + dirs)).getParentFile().mkdirs();
File file = new File(new File(DebuggingClassWriter.debugLocation), dirs + ".class");
BufferedOutputStream out = new BufferedOutputStream(new FileOutputStream(file));
try {
out.write(b);
} finally {
out.close();
}
// asm技术生成class文件
if (DebuggingClassWriter.traceEnabled) {
file = new File(new File(DebuggingClassWriter.debugLocation), dirs + ".asm");
out = new BufferedOutputStream(new FileOutputStream(file));
try {
ClassReader cr = new ClassReader(b);
PrintWriter pw = new PrintWriter(new OutputStreamWriter(out));
TraceClassVisitor tcv = new TraceClassVisitor((ClassVisitor)null, pw);
cr.accept(tcv, false);
pw.flush();
} finally {
out.close();
}
}
} catch (IOException var17) {
throw new CodeGenerationException(var17);
}
}
return b;
}
});
}
首先看DebuggingClassWriter.debugLocation
,默认null,可以设置路径,只有不为null时才会在本地生成class文件
private static String debugLocation = System.getProperty("cglib.debugLocation");
本想打断点看一下AccessController.doPrivileged
的执行流程,结果debugger直接跳过了,后来发现这个方法是native
public static native T doPrivileged(PrivilegedAction action);
首先 DebuggingClassWriter有个静态代码块,除了打印日志显示代理类class文件生成目录外,还判断cglib包下的是否存在TraceClassVisitor类(注意jdk下有一个一样的类),存在的的话赋值traceEnabled = true
,然后会用asm技术去生成class文件
static {
if (debugLocation != null) {
System.err.println("CGLIB debugging enabled, writing to '" + debugLocation + "'");
try {
Class.forName("net.sf.cglib.asm.util.TraceClassVisitor");
traceEnabled = true;
} catch (Throwable var1) {
;
}
}
}
直接看this.firstInstance(gen);
怎么实例化
protected Object firstInstance(Class type) throws Exception {
return this.classOnly ? type : this.createUsingReflection(type);
}
private Object createUsingReflection(Class type) {
setThreadCallbacks(type, this.callbacks);
Object var2;
try {
if (this.argumentTypes == null) {
// 参数类型为空的实例化方法,这里指的是代理类的构造方法参数
var2 = ReflectUtils.newInstance(type);
return var2;
}
// 参数不为空的实例化方法
var2 = ReflectUtils.newInstance(type, this.argumentTypes, this.arguments);
} finally {
setThreadCallbacks(type, (Callback[])null);
}
return var2;
}
我们创建代理类对象时有两种方法
create()
就表示代理类用默认的构造函数实例化对象
create(Class[] argumentTypes, Object[] arguments)
就表示代理类用有参的构造函数实例化对象
最后会调用ReflectUtils.newInstance(Constructor cstruct, Object[] args)
实例化代理类对象
public static Object newInstance(Constructor cstruct, Object[] args) {
boolean flag = cstruct.isAccessible();
Object var4;
try {
cstruct.setAccessible(true);
Object result = cstruct.newInstance(args);
var4 = result;
} catch (InstantiationException var10) {
throw new CodeGenerationException(var10);
} catch (IllegalAccessException var11) {
throw new CodeGenerationException(var11);
} catch (InvocationTargetException var12) {
throw new CodeGenerationException(var12.getTargetException());
} finally {
cstruct.setAccessible(flag);
}
return var4;
}
生成了好多代理类,具体看目标类的代理类
代理类中Method为被代理对象方法,MethodProxy为代理的方法,可以看到是一 一对应的
private static final Method CGLIB$update$0$Method;
private static final MethodProxy CGLIB$update$0$Proxy;
private static final Object[] CGLIB$emptyArgs;
private static final Method CGLIB$select$1$Method;
private static final MethodProxy CGLIB$select$1$Proxy;
private static final Method CGLIB$finalize$2$Method;
private static final MethodProxy CGLIB$finalize$2$Proxy;
private static final Method CGLIB$equals$3$Method;
private static final MethodProxy CGLIB$equals$3$Proxy;
private static final Method CGLIB$toString$4$Method;
private static final MethodProxy CGLIB$toString$4$Proxy;
private static final Method CGLIB$hashCode$5$Method;
private static final MethodProxy CGLIB$hashCode$5$Proxy;
private static final Method CGLIB$clone$6$Method;
private static final MethodProxy CGLIB$clone$6$Proxy;
在静态代码块中被初始化
static void CGLIB$STATICHOOK1() {
CGLIB$THREAD_CALLBACKS = new ThreadLocal();
Class var0;
ClassLoader var10000 = (var0 = Class.forName("com.yk.demo.dynamicProxy.cglibProxy.Dao$$EnhancerByCGLIB$$f018efe")).getClassLoader();
CGLIB$emptyArgs = new Object[0];
CGLIB$update$0$Proxy = MethodProxy.create(var10000, (CGLIB$update$0$Method = Class.forName("com.yk.demo.dynamicProxy.cglibProxy.Dao").getDeclaredMethod("update", Class.forName("java.lang.String"))).getDeclaringClass(), var0, "(Ljava/lang/String;)V", "update", "CGLIB$update$0");
CGLIB$select$1$Proxy = MethodProxy.create(var10000, (CGLIB$select$1$Method = Class.forName("com.yk.demo.dynamicProxy.cglibProxy.Dao").getDeclaredMethod("select")).getDeclaringClass(), var0, "()V", "select", "CGLIB$select$1");
CGLIB$finalize$2$Proxy = MethodProxy.create(var10000, (CGLIB$finalize$2$Method = Class.forName("java.lang.Object").getDeclaredMethod("finalize")).getDeclaringClass(), var0, "()V", "finalize", "CGLIB$finalize$2");
CGLIB$equals$3$Proxy = MethodProxy.create(var10000, (CGLIB$equals$3$Method = Class.forName("java.lang.Object").getDeclaredMethod("equals", Class.forName("java.lang.Object"))).getDeclaringClass(), var0, "(Ljava/lang/Object;)Z", "equals", "CGLIB$equals$3");
CGLIB$toString$4$Proxy = MethodProxy.create(var10000, (CGLIB$toString$4$Method = Class.forName("java.lang.Object").getDeclaredMethod("toString")).getDeclaringClass(), var0, "()Ljava/lang/String;", "toString", "CGLIB$toString$4");
CGLIB$hashCode$5$Proxy = MethodProxy.create(var10000, (CGLIB$hashCode$5$Method = Class.forName("java.lang.Object").getDeclaredMethod("hashCode")).getDeclaringClass(), var0, "()I", "hashCode", "CGLIB$hashCode$5");
CGLIB$clone$6$Proxy = MethodProxy.create(var10000, (CGLIB$clone$6$Method = Class.forName("java.lang.Object").getDeclaredMethod("clone")).getDeclaringClass(), var0, "()Ljava/lang/Object;", "clone", "CGLIB$clone$6");
}
// 创建代理对象
Dao dao = (Dao)enhancer.create();
// // 通过代理对象调用目标方法
dao.update("yukang");
代理类执行update方法时
public final void update(String var1) {
// 这里获取的就是自定义方法拦截器DaoProxy,一开始就初始化的
MethodInterceptor var10000 = this.CGLIB$CALLBACK_0;
if (this.CGLIB$CALLBACK_0 == null) {
CGLIB$BIND_CALLBACKS(this);
var10000 = this.CGLIB$CALLBACK_0;
}
if (var10000 != null) {
var10000.intercept(this, CGLIB$update$0$Method, new Object[]{var1}, CGLIB$update$0$Proxy);
} else {
super.update(var1);
}
}
var10000.intercept(this, CGLIB$update$0$Method, new Object[]{var1}, CGLIB$update$0$Proxy);
,执行的是自定义方法拦截器DaoProxy**.intercept
**
/**
* Object:cglib生成的代理对象
* Method:被代理对象方法
* Object[]:方法入参
* MethodProxy:代理的方法
*/
@Override
public Object intercept(Object object, Method method, Object[] objects, MethodProxy proxy) throws Throwable {
System.out.println("Before Method Invoke");
proxy.invokeSuper(object, objects);
System.out.println("After Method Invoke");
return object;
}
proxy.invokeSuper(object, objects);
执行的是MethodProxy**.invokeSuper
**
public Object invokeSuper(Object obj, Object[] args) throws Throwable {
try {
// f2代理类FastClass
return this.f2.invoke(this.i2, obj, args);
} catch (InvocationTargetException var4) {
throw var4.getTargetException();
}
}
这里的f2通过代理对象生成的,是在静态代码块中执行MethodProxy**.create
传递进来的**
// c1被代理对象,c2代理对象
public static MethodProxy create(ClassLoader loader, Class c1, Class c2, String desc, String name1, String name2) {
final Signature sig1 = new Signature(name1, desc);
Signature sig2 = new Signature(name2, desc);
FastClass f1 = helper(loader, c1);// 被代理类FastClass
FastClass f2 = helper(loader, c2);// 代理类FastClass
int i1 = f1.getIndex(sig1);// 被代理类的方法签名(index)
int i2 = f2.getIndex(sig2);// 代理类的方法签名(index)
MethodProxy proxy;
if (i1 < 0) {
proxy = new MethodProxy() {
public Object invoke(Object obj, Object[] args) throws Throwable {
throw new IllegalArgumentException("Protected method: " + sig1);
}
};
} else {
proxy = new MethodProxy();
}
proxy.f1 = f1;
proxy.f2 = f2;
proxy.i1 = i1;
proxy.i2 = i2;
proxy.sig = sig1;
proxy.superName = name2;
return proxy;
}
this.f2.invoke(this.i2, obj, args);
,执行的就是代理类的FastClass**.invok
**
根据方法签名(index)快速找到代理类的方法
public Object invoke(int var1, Object var2, Object[] var3) throws InvocationTargetException {
f018efe var10000 = (f018efe)var2;
int var10001 = var1;
try {
switch(var10001) {
case 0:
return new Boolean(var10000.equals(var3[0]));
.
.
.
case 16:
var10000.CGLIB$update$0((String)var3[0]);
return null;
.
.
.
}
} catch (Throwable var4) {
throw new InvocationTargetException(var4);
}
throw new IllegalArgumentException("Cannot find matching method/constructor");
}
执行代理类的CGLIB$update$0
方法,最后执行父类(被代理类)的方法
final void CGLIB$update$0(String var1) {
super.update(var1);
}