cglib动态代理
示例代码
package com.cglib.dao;
public class CglibIndexDao1 {
}
package com.cglib.dao;
public class CglibIndexDao {
}
package com.cglib;
public class A {
public void get(){
System.out.println("A method");
}
}
package com.cglib;
public class MyMethodInterceptor implements MethodInterceptor {
@Override
public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
System.out.println("cglib");
return methodProxy.invokeSuper( o,null );
}
}
package com.cglib;
@Configuration
@ComponentScan("com.cglib")
public class CglibAppConfig {
@Bean
public CglibIndexDao cgDao(){
System.out.println("cgDao");
return new CglibIndexDao();
}
@Bean
public CglibIndexDao1 cgDao1(){
System.out.println("cgDao1");
cgDao();
return new CglibIndexDao1();
}
}
package com.cglib;
public class TestCglib {
public static void main(String[] args) throws Exception {
AnnotationConfigApplicationContext ac =
new AnnotationConfigApplicationContext( CglibAppConfig.class );
CglibAppConfig bean = ac.getBean( CglibAppConfig.class );
System.out.println(bean);
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(A.class);
enhancer.setCallback( new MyMethodInterceptor() );
enhancer.setUseFactory(false);
enhancer.setCallbackType( MyMethodInterceptor.class );
A cglib = (A) enhancer.create();
cglib.get();
byte[] bytes= ProxyGenerator.generateProxyClass("$proxy",new Class[]{bean.getClass()} );
System.out.println(CglibAppConfig.class);
FileOutputStream fileOutputStream = new FileOutputStream( "c://$proxy.class" );
fileOutputStream.write( bytes );
fileOutputStream.close();
}
}
生成的代理字节码文件
//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by Fernflower decompiler)
//
import com.cglib.A..EnhancerByCGLIB..a3f6b2d1;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.lang.reflect.UndeclaredThrowableException;
import org.springframework.cglib.core.Signature;
import org.springframework.cglib.proxy.Callback;
import org.springframework.cglib.proxy.MethodProxy;
public final class $proxy extends Proxy implements a3f6b2d1 {
private static Method m1;
private static Method m5;
private static Method m2;
private static Method m4;
private static Method m3;
private static Method m6;
private static Method m10;
private static Method m12;
private static Method m0;
private static Method m7;
private static Method m11;
private static Method m9;
private static Method m8;
public $proxy(InvocationHandler var1) throws {
super(var1);
}
public final boolean equals(Object var1) throws {
try {
return (Boolean)super.h.invoke(this, m1, new Object[]{var1});
} catch (RuntimeException | Error var3) {
throw var3;
} catch (Throwable var4) {
throw new UndeclaredThrowableException(var4);
}
}
public final void CGLIB$SET_THREAD_CALLBACKS(Callback[] var1) throws {
try {
super.h.invoke(this, m5, new Object[]{var1});
} catch (RuntimeException | Error var3) {
throw var3;
} catch (Throwable var4) {
throw new UndeclaredThrowableException(var4);
}
}
public final String toString() throws {
try {
return (String)super.h.invoke(this, m2, (Object[])null);
} catch (RuntimeException | Error var2) {
throw var2;
} catch (Throwable var3) {
throw new UndeclaredThrowableException(var3);
}
}
public final void CGLIB$SET_STATIC_CALLBACKS(Callback[] var1) throws {
try {
super.h.invoke(this, m4, new Object[]{var1});
} catch (RuntimeException | Error var3) {
throw var3;
} catch (Throwable var4) {
throw new UndeclaredThrowableException(var4);
}
}
public final void get() throws {
try {
super.h.invoke(this, m3, (Object[])null);
} catch (RuntimeException | Error var2) {
throw var2;
} catch (Throwable var3) {
throw new UndeclaredThrowableException(var3);
}
}
public final MethodProxy CGLIB$findMethodProxy(Signature var1) throws {
try {
return (MethodProxy)super.h.invoke(this, m6, new Object[]{var1});
} catch (RuntimeException | Error var3) {
throw var3;
} catch (Throwable var4) {
throw new UndeclaredThrowableException(var4);
}
}
public final Class getClass() throws {
try {
return (Class)super.h.invoke(this, m10, (Object[])null);
} catch (RuntimeException | Error var2) {
throw var2;
} catch (Throwable var3) {
throw new UndeclaredThrowableException(var3);
}
}
public final void notifyAll() throws {
try {
super.h.invoke(this, m12, (Object[])null);
} catch (RuntimeException | Error var2) {
throw var2;
} catch (Throwable var3) {
throw new UndeclaredThrowableException(var3);
}
}
public final int hashCode() throws {
try {
return (Integer)super.h.invoke(this, m0, (Object[])null);
} catch (RuntimeException | Error var2) {
throw var2;
} catch (Throwable var3) {
throw new UndeclaredThrowableException(var3);
}
}
public final void wait() throws InterruptedException {
try {
super.h.invoke(this, m7, (Object[])null);
} catch (RuntimeException | InterruptedException | Error var2) {
throw var2;
} catch (Throwable var3) {
throw new UndeclaredThrowableException(var3);
}
}
public final void notify() throws {
try {
super.h.invoke(this, m11, (Object[])null);
} catch (RuntimeException | Error var2) {
throw var2;
} catch (Throwable var3) {
throw new UndeclaredThrowableException(var3);
}
}
public final void wait(long var1) throws InterruptedException {
try {
super.h.invoke(this, m9, new Object[]{var1});
} catch (RuntimeException | InterruptedException | Error var4) {
throw var4;
} catch (Throwable var5) {
throw new UndeclaredThrowableException(var5);
}
}
public final void wait(long var1, int var3) throws InterruptedException {
try {
super.h.invoke(this, m8, new Object[]{var1, var3});
} catch (RuntimeException | InterruptedException | Error var5) {
throw var5;
} catch (Throwable var6) {
throw new UndeclaredThrowableException(var6);
}
}
static {
try {
m1 = Class.forName("java.lang.Object").getMethod("equals", Class.forName("java.lang.Object"));
m5 = Class.forName("com.cglib.A$$EnhancerByCGLIB$$a3f6b2d1").getMethod("CGLIB$SET_THREAD_CALLBACKS", Class.forName("[Lorg.springframework.cglib.proxy.Callback;"));
m2 = Class.forName("java.lang.Object").getMethod("toString");
m4 = Class.forName("com.cglib.A$$EnhancerByCGLIB$$a3f6b2d1").getMethod("CGLIB$SET_STATIC_CALLBACKS", Class.forName("[Lorg.springframework.cglib.proxy.Callback;"));
m3 = Class.forName("com.cglib.A$$EnhancerByCGLIB$$a3f6b2d1").getMethod("get");
m6 = Class.forName("com.cglib.A$$EnhancerByCGLIB$$a3f6b2d1").getMethod("CGLIB$findMethodProxy", Class.forName("org.springframework.cglib.core.Signature"));
m10 = Class.forName("com.cglib.A$$EnhancerByCGLIB$$a3f6b2d1").getMethod("getClass");
m12 = Class.forName("com.cglib.A$$EnhancerByCGLIB$$a3f6b2d1").getMethod("notifyAll");
m0 = Class.forName("java.lang.Object").getMethod("hashCode");
m7 = Class.forName("com.cglib.A$$EnhancerByCGLIB$$a3f6b2d1").getMethod("wait");
m11 = Class.forName("com.cglib.A$$EnhancerByCGLIB$$a3f6b2d1").getMethod("notify");
m9 = Class.forName("com.cglib.A$$EnhancerByCGLIB$$a3f6b2d1").getMethod("wait", Long.TYPE);
m8 = Class.forName("com.cglib.A$$EnhancerByCGLIB$$a3f6b2d1").getMethod("wait", Long.TYPE, Integer.TYPE);
} catch (NoSuchMethodException var2) {
throw new NoSuchMethodError(var2.getMessage());
} catch (ClassNotFoundException var3) {
throw new NoClassDefFoundError(var3.getMessage());
}
}
}
配置类增强
对配置类CglibAppConfig进行cglib代理
debug分析
1、invokeBeanFactoryPostProcessors 执行bean工厂后置处理器
PostProcessorRegistrationDelegate#invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory, BeanFactoryPostProcessor>)
2、postProcessBeanFactory 执行处理bean工厂方法
postProcessBeanFactory.png
3、enhanceConfigurationClasses 增强配置类
ConfigurationClassPostProcessor#postProcessBeanFactory
enhanceConfigurationClasses.png
4、设置beanDefinition属性值
beanDefsetAttribute.png
5、createClass
newEnhance.png
6、newEnhancer
newEnhancer.png
7、设置beanDefinition的beanClass
beanDefsetBeanClass.png
CglibAppConfig配置类的实例化过程,经历与其他一般class相同的的生命周期
生成增强类
class com.cglib.CglibAppConfigc67d1aaa
@Bean处理
根据示例代码,分析创建cgDao的过程
配置类加了@Bean的中方法调用只会创建一次bean
调用链
PostProcessorRegistrationDelegate#invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory, List<BeanFactoryPostProcessor>)
PostProcessorRegistrationDelegate#invokeBeanDefinitionRegistryPostProcessors
ConfigurationClassPostProcessor#postProcessBeanDefinitionRegistry
ConfigurationClassPostProcessor#processConfigBeanDefinitions
ConfigurationClassParser#parse(Set<BeanDefinitionHolder>)
ConfigurationClassParser#parse(AnnotationMetadata, String)
ConfigurationClassParser#processConfigurationClass
ConfigurationClassParser#doProcessConfigurationClass
debug分析
1、doProcessConfigurationClass处理配置类的@bean
processBean.png
2、retrieveBeanMethodMetadata 查找@Bean注解
在ConfigurationClassParser#doProcessConfigurationClass方法内
retrieveBeanMethodMetadata.png
3、configClass 配置类集合添加bean方法
在ConfigurationClassParser#parse(Set<BeanDefinitionHolder>)方法解析之后放到Set<ConfigurationClass>集合
configClassaddBeanMethod.png
4、加载configClass 中类
ConfigurationClassBeanDefinitionReader#loadBeanDefinitions加载
loadBeanDefinition.png
5、loadBeanDefinitionsForConfigurationClass
loadBeanDefinitionsForConfigurationClass.png
6、加载第一个@bean方法
对beanMethod中第一个cgDao加载处理
loadBeanDefinitionsForBeanMethod.png
7、设置cgDao的BeanDefinition和注册到bean工厂
beanName是方法名cgDao
registerBeanDefinition.png
8、第一个@bean方法的实例化
cgDao的实例化,getFactoryMethodName工厂方法名不为null
getFactoryMethodName.png
9、instantiateUsingFactoryMethod 用工厂方法实例化
instantiateUsingFactoryMethod.png
10、首先获取工厂bean和工厂类
factoryClassfactoryBean.png
11、获取FactoryMethod
遍历所有方法,符合是工厂方法的
candidateList.png
12、对可用的工厂、参数等赋值
factoryMethodToUse.png
13、storeCache存储缓存
storeCache.png isCurrentlyInvokedFactoryMethod.png
14、instantiate 根据默认实例化策略实例化
instantiate.png
15、设置当前执行的线程并执行invoke方法
currentlyInvokedFactoryMethod.set(factoryMethod);
factoryMethodinvoke.png
16、对invoke方法拦截处理
在BeanMethodInterceptor#intercept进行拦截处理
查看是否有scope注解
Scope.png
17、是否是FactoryBean工厂bean
BeanFactory.png
18、当前方法是否在执行
首先得到currentlyInvokedFactoryMethod线程正在执行的方法,此时是cgDao()方法。method是当前执行的方法
isCurrentlyInvokedFactoryMethod2.png
19、当前执行与线程正在执行相同
isCurrentlyInvokedFactoryMethod(beanMethod)为true
执行cglibMethodProxy.invokeSuper(enhancedConfigInstance, beanMethodArgs)方法
cglibMethodProxyinvokeSuper.png
20、MethodProxy
MethodProxy.png
经过内部代理类调用最终执行到提供的方法
MethodInterceptor#intercept 执行结束
21、CglibAppConfig内方法执行
CglibAppConfig.png
22、currentlyInvokedFactoryMethod移除
currentlyInvokedFactoryMethodremove.png
23、cgDao1方法执行与cgDao的工厂方法执行步骤相同
24、直接到达示例代码中cgDao1()方法里的cgDao()方法调用
当执行到cgDao1()方法里的cgDao()方法调用时,进入BeanMethodInterceptor拦截
25、isCurrentlyInvokedFactoryMethod 是否正在执行 方法判断
此时,当前执行的方法是cgDao()。currentlyInvokedFactoryMethod正在执行线程的工厂方法是cgDao1。
所以,返回fasle
isCurrentlyInvokedFactoryMethodcgDao11.png
26、resolveBeanReference 查询
isCurrentlyInvokedFactoryMethod(beanMethod)返回false
resolveBeanReference.png
27、beanFactory bean工厂查找
beanFactorygetBean.png
28、注册bean依赖
registerDependentBean.png
所以,在配置类中无论在其他地方调用几次@Bean的工厂方法,只会实例化一次
总结:
cglib动态代理使用enhance类进行增强
设置Callback,执行被增强类方法前调用intercept方法