spring

cglib动态代理

2019-11-08  本文已影响0人  loveFXX

示例代码

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>)

invokeBeanFactoryPostProcessors.png
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方法

上一篇下一篇

猜你喜欢

热点阅读