在Spring中@Configuration源码深度解析(一)中已经说到了执行代码块4的PostProcessorRegistrationDelegate#invokeBeanFactoryPostProcessors方法的第一个重要方法: invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);会将普通注解类转换成beanDefinition对象。
下面让我们说一下这个方法第二个重要方法:invokeBeanFactoryPostProcessors(registryProcessors, beanFactory);该方法会执行实现了BeanFactoryPostProcessor接口的postProcessBeanFactory方法(由于ConfigurationClassPostProcessor实现BeanDefinitionRegistryPostProcessor接口,而BeanDefinitionRegistryPostProcessor 又继承了BeanFactoryPostProcessor接口,所以在这篇文章的重点是讲ConfigurationClassPostProcessor的postProcessBeanFactory方法)。
代码块1.PostProcessorRegistrationDelegate#invokeBeanFactoryPostProcessors方法
private static void invokeBeanFactoryPostProcessors(
Collection<? extends BeanFactoryPostProcessor> postProcessors, ConfigurableListableBeanFactory beanFactory) {
//执行所有BeanFactoryPostProcessor的postProcessBeanFactory方法
for (BeanFactoryPostProcessor postProcessor : postProcessors) {
postProcessor.postProcessBeanFactory(beanFactory);
}
}
该方法最终调用ConfigurationClassPostProcessor的postProcessBeanFactory方法,完成会加了@Configuration注解类的增强。
代码块2.ConfigurationClassPostProcessor#postProcessBeanFactory方法
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) {
int factoryId = System.identityHashCode(beanFactory);
if (this.factoriesPostProcessed.contains(factoryId)) {
throw new IllegalStateException(
"postProcessBeanFactory already called on this post-processor against " + beanFactory);
}
this.factoriesPostProcessed.add(factoryId);
if (!this.registriesPostProcessed.contains(factoryId)) {
// BeanDefinitionRegistryPostProcessor hook apparently not supported...
// Simply call processConfigurationClasses lazily at this point then.
processConfigBeanDefinitions((BeanDefinitionRegistry) beanFactory);
}
//1. 给加了@Configuration注解的配置类产生cglib代理
enhanceConfigurationClasses(beanFactory);
//2. 向容器中注入ImportAwareBeanPostProcessor,其是一个bean的后置处理器,
beanFactory.addBeanPostProcessor(new ImportAwareBeanPostProcessor(beanFactory));
}
第1步:给加了@Configuration注解的配置类产生cglib代理 ,并给它设置成EnhancedConfiguration的子类,查看代码块3
第2步:向容器中注入ImportAwareBeanPostProcessor,ImportAwareBeanPostProcessor是一个bean的后置处理器,其作用就是判断一个类是不是EnhancedConfiguration的子类,如果是把bean工厂赋值给他,这样加了@Configuration注解的类,就可以直接去容器中获取bean。
代码块3. ConfigurationClassPostProcessor#enhanceConfigurationClasses方法
public void enhanceConfigurationClasses(ConfigurableListableBeanFactory beanFactory) {
//存放所有为full类型的BeanDefinition,也就是加了@Configuration注解的
Map<String, AbstractBeanDefinition> configBeanDefs = new LinkedHashMap<>();
//1.从容器中拿到所有BeanDefinition的名称
for (String beanName : beanFactory.getBeanDefinitionNames()) {
BeanDefinition beanDef = beanFactory.getBeanDefinition(beanName);
//2.判断是否是一个全注解类
//扫描是全注解类?full和lite的关系
if (ConfigurationClassUtils.isFullConfigurationClass(beanDef)) {
if (!(beanDef instanceof AbstractBeanDefinition)) {
throw new BeanDefinitionStoreException("Cannot enhance @Configuration bean definition '" +
beanName + "' since it is not stored in an AbstractBeanDefinition subclass");
}
//3.将为full类型的加到Map中
configBeanDefs.put(beanName, (AbstractBeanDefinition) beanDef);
}
}
//4.没有full类型的就返回
if (configBeanDefs.isEmpty()) {
// nothing to enhance -> return immediately
return;
}
//创建一个增强器
ConfigurationClassEnhancer enhancer = new ConfigurationClassEnhancer();
//5.遍历这个Map
for (Map.Entry<String, AbstractBeanDefinition> entry : configBeanDefs.entrySet()) {
AbstractBeanDefinition beanDef = entry.getValue();
// If a @Configuration class gets proxied, always proxy the target class
beanDef.setAttribute(AutoProxyUtils.PRESERVE_TARGET_CLASS_ATTRIBUTE, Boolean.TRUE);
try {
// Set enhanced subclass of the user-specified bean class
// 6.获取类的Class进行增强
Class<?> configClass = beanDef.resolveBeanClass(this.beanClassLoader);
if (configClass != null) {
//7. 完成对全注解类的cglib代理
Class<?> enhancedClass = enhancer.enhance(configClass, this.beanClassLoader);
if (configClass != enhancedClass) {
//8.将增强后的cglib代理类设置成BeanDefinition的BeanClass
beanDef.setBeanClass(enhancedClass);
}
}
}
catch (Throwable ex) {
throw new IllegalStateException("Cannot load configuration class: " + beanDef.getBeanClassName(), ex);
}
}
}
在第2步会判断是否是full类型的,如果去就加到一个Map中,看代码块4.
在第7步中会完成会full类型的代理,使用的是cglib代理,这是你就知道了为什么加了@Configuration的类不能是final类型的了(使用cglib代理会继承需要增强的类,而你加了final说明这个类不能有子类了)看代码块5.
第8步:将增强后的cglib代理类设置成BeanDefinition的beanClass,因为在后面Spring进行实例化bean的时候,是根据BeanDefinition的beanClass来进行的,所以在此将beanClass改了之后,就能在下面使用这个代理类来进行实例化。
代码块4:ConfigurationClassUtils#isFullConfigurationClass方法
public static boolean isFullConfigurationClass(BeanDefinition beanDef) {
//判断BeanDefinition的CONFIGURATION_CLASS_ATTRIBUTE属性是不是full
return CONFIGURATION_CLASS_FULL.equals(beanDef.getAttribute(CONFIGURATION_CLASS_ATTRIBUTE));
}
在Spring中@Configuration源码深度解析(一)中加了@Configuration注解的类会被设置成full,所以会被加入到configBeanDefs的Map中。
代码块5:ConfigurationClassEnhancer#enhance方法
public Class<?> enhance(Class<?> configClass, @Nullable ClassLoader classLoader) {
//1. isAssignableFrom方式是判断父类.class.isAssignableFrom(子类.class)
//isAssignableFrom()方法是从类继承的角度去判断,是判断是否为某个类的父类
//如果是EnhancedConfiguration的子类,说明被代理过
if (EnhancedConfiguration.class.isAssignableFrom(configClass)) {
return configClass;
}
//2. 没有被代理cglib代理,则进行cglib代理
Class<?> enhancedClass = createClass(newEnhancer(configClass, classLoader));
return enhancedClass;
}
在第2步中有两个方法一个是newEnhancer方法(看代码块6),该方法是创建一个增强对象,一个是createClass方法,根据得到一个增强后的Class对象,
注意在newEnhancer方法会生成一个Enhancer对象,用于在createClass中进行得到一个增强后的Class对象
代码块6:ConfigurationClassEnhancer#newEnhancer方法
private Enhancer newEnhancer(Class<?> configSuperClass, @Nullable ClassLoader classLoader) {
Enhancer enhancer = new Enhancer();
//1. 增强父类,地球人都知道cglib是基于继承来的
//设置需要被增强的对象为代理对象的父类
enhancer.setSuperclass(configSuperClass);
//2. 增强接口,为什么要增强接口?
//便于判断,表示一个类以及被增强了,EnhancedConfiguration继承了BeanFactoryAware接口
//所以代理类可以拿到BeanFactory工厂
enhancer.setInterfaces(new Class<?>[] {EnhancedConfiguration.class});
//不继承Factory接口
enhancer.setUseFactory(false);
enhancer.setNamingPolicy(SpringNamingPolicy.INSTANCE);
// 3. BeanFactoryAwareGeneratorStrategy是一个生成策略
// 主要为生成的CGLIB类中添加成员变量$$beanFactory
// 同时基于接口EnhancedConfiguration的父接口BeanFactoryAware中的setBeanFactory方法,
// 设置此变量的值为当前Context中的beanFactory,这样一来我们这个cglib代理的对象就有了beanFactory
//有了factory就能获得对象,而不用去通过方法获得对象了,因为通过方法获得对象不能控制器过程
//该BeanFactory的作用是在this调用时拦截该调用,并直接在beanFactory中获得目标bean
enhancer.setStrategy(new BeanFactoryAwareGeneratorStrategy(classLoader));
//4. 过滤方法,不能每次都去new
enhancer.setCallbackFilter(CALLBACK_FILTER);
enhancer.setCallbackTypes(CALLBACK_FILTER.getCallbackTypes());
return enhancer;
}
//该类为ConfigurationClassEnhancer的内部类,继承了BeanFactoryAware接口
public interface EnhancedConfiguration extends BeanFactoryAware {
}
在第2步中会给代理类设置一个ConfigurationClassEnhancer的接口,这个接口继承了BeanFactoryAware,让生成的代理类可以拿到BeanFactory对象。
在第3步中会给代理类增加一个public的类型为BeanFactory,名为$$beanFactory字段的属性,看代码块7。
在第4步增强方法拦截器,在执行方法的时候,首先去容器中判断是否有这个bean,如果没有的话,才会执行这个方法,有的话,直接返回容器内部的bean,看代码块8。
代码块7: BeanFactoryAwareGeneratorStrategy类:
private static class BeanFactoryAwareGeneratorStrategy extends DefaultGeneratorStrategy {
@Nullable
private final ClassLoader classLoader;
public BeanFactoryAwareGeneratorStrategy(@Nullable ClassLoader classLoader) {
this.classLoader = classLoader;
}
@Override
protected ClassGenerator transform(ClassGenerator cg) throws Exception {
ClassEmitterTransformer transformer = new ClassEmitterTransformer() {
@Override
public void end_class() {
//给代理类设置public类型为BeanFactory,名称是$$beanFactory的属性
//Constants.ACC_PUBLIC = 0x0001
//BEAN_FACTORY_FIELD = "$$beanFactory"
declare_field(Constants.ACC_PUBLIC, BEAN_FACTORY_FIELD, Type.getType(BeanFactory.class), null);
super.end_class();
}
};
return new TransformingClassGenerator(cg, transformer);
}
//省略了一个方法
}
代码块8:看一下CALLBACK_FILTER
在代码块6中的第4步,就是添加了CALLBACK_FILTER变量,然后这个两个里面有两个方法拦截器,一个是拦截标注了@Configuration注解的类里面的方法,一个是拦截BeanFactoryAware接口的setBeanFactory方法。
对于拦截标注了@Configuration注解的类里面的方法,看代码块9:
代码块9:ConfigurationClassEnhancer.BeanMethodInterceptor类
//ConfigurationClassEnhancer里面的内部类BeanMethodInterceptor
//用于拦截@Bean方法的调用,并直接从BeanFactory中获取目标bean,而不是通过执行方法。
private static class BeanMethodInterceptor implements MethodInterceptor, ConditionalCallback {
@Override
@Nullable
public Object intercept(Object enhancedConfigInstance, Method beanMethod, Object[] beanMethodArgs,
MethodProxy cglibMethodProxy) throws Throwable {
//enhancedConfigInstance 代理
// 1. 通过enhancedConfigInstance中cglib生成的成员变量$$beanFactory获得beanFactory。
ConfigurableBeanFactory beanFactory = getBeanFactory(enhancedConfigInstance);
// 2. 获得@Configuration注解中加了@Bean的bean的名称,如果没有指定,则使用方法作为bean的名称
String beanName = BeanAnnotationHelper.determineBeanNameFor(beanMethod);
// Determine whether this bean is a scoped-proxy
Scope scope = AnnotatedElementUtils.findMergedAnnotation(beanMethod, Scope.class);
if (scope != null && scope.proxyMode() != ScopedProxyMode.NO) {
String scopedBeanName = ScopedProxyCreator.getTargetBeanName(beanName);
if (beanFactory.isCurrentlyInCreation(scopedBeanName)) {
beanName = scopedBeanName;
}
}
//3. 这里是将bean的名称加上"&"判断是不是FactoryBean类型的,如果是的话,就还需要对FactoryBean
//类型再进行一次代理,为什么?因为你获取的就是一个new出来的FactoryBean的,就不能保证单一性,
//所以这这里需要对FactoryBean在进行一次拦截
if (factoryContainsBean(beanFactory, BeanFactory.FACTORY_BEAN_PREFIX + beanName) &&
factoryContainsBean(beanFactory, beanName)) {
Object factoryBean = beanFactory.getBean(BeanFactory.FACTORY_BEAN_PREFIX + beanName);
if (factoryBean instanceof ScopedProxyFactoryBean) {
// Scoped proxy factory beans are a special case and should not be further proxied
}
else {
// It is a candidate FactoryBean - go ahead with enhancement
return enhanceFactoryBean(factoryBean, beanMethod.getReturnType(), beanFactory, beanName);
}
}
//4. 一个非常牛逼的判断
//判断到底是new 还是get
//判断执行的方法和调用方法是不是同一个方法
if (isCurrentlyInvokedFactoryMethod(beanMethod)) {
// The factory is calling the bean method in order to instantiate and register the bean
// (i.e. via a getBean() call) -> invoke the super implementation of the method to actually
// create the bean instance.
//调用父类的方法进行创建这个标注了@Bean注解的bean
return cglibMethodProxy.invokeSuper(enhancedConfigInstance, beanMethodArgs);
}
//5.从容器中拿bean实例
return resolveBeanReference(beanMethod, beanMethodArgs, beanFactory, beanName);
}
private Object resolveBeanReference(Method beanMethod, Object[] beanMethodArgs,
ConfigurableBeanFactory beanFactory, String beanName) {
// The user (i.e. not the factory) is requesting this bean through a call to
// the bean method, direct or indirect. The bean may have already been marked
// as 'in creation' in certain autowiring scenarios; if so, temporarily set
// the in-creation status to false in order to avoid an exception.
//6. 判断它是否正在创建
boolean alreadyInCreation = beanFactory.isCurrentlyInCreation(beanName);
try {
if (alreadyInCreation) {
beanFactory.setCurrentlyInCreation(beanName, false);
}
boolean useArgs = !ObjectUtils.isEmpty(beanMethodArgs);
if (useArgs && beanFactory.isSingleton(beanName)) {
// Stubbed null arguments just for reference purposes,
// expecting them to be autowired for regular singleton references?
// A safe assumption since @Bean singleton arguments cannot be optional...
for (Object arg : beanMethodArgs) {
if (arg == null) {
useArgs = false;
break;
}
}
}
//beanFactory.getBean
//7. 这个方法就是从beanFactory容器中获取bean,beanFactory.getBean方法会去容器中进行查找bean,如果找不到则进行创建bean
Object beanInstance = (useArgs ? beanFactory.getBean(beanName, beanMethodArgs) :
beanFactory.getBean(beanName));
if (!ClassUtils.isAssignableValue(beanMethod.getReturnType(), beanInstance)) {
if (beanInstance.equals(null)) {
beanInstance = null;
}
else {
//省略了这段代码,不重要
throw new IllegalStateException();
}
}
Method currentlyInvoked = SimpleInstantiationStrategy.getCurrentlyInvokedFactoryMethod();
if (currentlyInvoked != null) {
String outerBeanName = BeanAnnotationHelper.determineBeanNameFor(currentlyInvoked);
beanFactory.registerDependentBean(beanName, outerBeanName);
}
return beanInstance;
}
finally {
if (alreadyInCreation) {
beanFactory.setCurrentlyInCreation(beanName, true);
}
}
}
}
在第三步是,需要判断FactoryBean类型,如果是的话就需要二次拦截,为什么?因为加了@Configuration如果在@Bean内部调用了其他@Bean注解的方法,Spring会进行拦截,然然后从容器中获取bean,如股票内部调用的bean是FactoryBean类型,而Spring不去拦截,那么就会根据方法名(此时不带“&”),获取的就是FactoryBean包裹的类型,这样就全错了,所以Spring会对FactoryBean类型进行拦截再判断,关于FactoryBean的使用想要了解更多的可以参考:Spring中FactoryBean的使用。
注意上面的方法不会在创建cglib代理的时候调用,只有在容器创建bean的时候调用,现在只是在动态的生成cglib代理对象。
在第4步中,会判断当前拦截的这个Method方法是不是我们被我们标注了@Bean注解正要被创建的那个bean。说起来很拗口,也可以理解为使用了@bean注解的方法内部,你又去调用了其他标注了@bean注解的方法,这个当你调用其他标注了@bean注解的方法时,会先进行方法拦截器里面进行判断,如果不是,则会通过第5步去容器中通过getBean去获取对象。看一下代码块10.
代码块10:BeanMethodInterceptor#isCurrentlyInvokedFactoryMethod
private boolean isCurrentlyInvokedFactoryMethod(Method method) {
//1.取出通过@Bean注解标注的方式标注的是哪个方法
Method currentlyInvoked = SimpleInstantiationStrategy.getCurrentlyInvokedFactoryMethod();
//2. 判断是否为同一个方法,方法名,参数类型和个数是否都一致
return (currentlyInvoked != null && method.getName().equals(currentlyInvoked.getName()) &&
Arrays.equals(method.getParameterTypes(), currentlyInvoked.getParameterTypes()));
}
第1步会取出来我们在创建@bean注解的bean之前,标注的方法,所以我们来看一下SimpleInstantiationStrategy类是怎么进行标记的,看代码块11
代码块11:SimpleInstantiationStrategy类
public class SimpleInstantiationStrategy implements InstantiationStrategy {
//ThreadLocal类型的,用来保存当前正在调用的工厂方法
private static final ThreadLocal<Method> currentlyInvokedFactoryMethod = new ThreadLocal<>();
//返回当前正在调用的工厂方法,如果没有,则返回{@code null}。
//允许工厂方法实现确定当前调用方是否是容器本身,而不是用户代码
@Nullable
public static Method getCurrentlyInvokedFactoryMethod() {
return currentlyInvokedFactoryMethod.get();
}
//用于设置当前正在调用的工厂方法
@Override
public Object instantiate(RootBeanDefinition bd, @Nullable String beanName, BeanFactory owner,
@Nullable Object factoryBean, final Method factoryMethod, @Nullable Object... args) {
try {
//1. 安全检查
if (System.getSecurityManager() != null) {
AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
ReflectionUtils.makeAccessible(factoryMethod);
return null;
});
}
else {
ReflectionUtils.makeAccessible(factoryMethod);
}
//2. 取出设置的工厂方法
Method priorInvokedFactoryMethod = currentlyInvokedFactoryMethod.get();
try {
//3. 将现在正在调用的工厂方法设置进去
currentlyInvokedFactoryMethod.set(factoryMethod);
//4. 然后调用正在工厂方法,其实就是在这一步调用的@Configuration类里面的@bean方法,来创建对象
//而且在第3步可以看到是将currentlyInvokedFactoryMethod的值设置成正在调用的,用来标记它是容器进行调用的
//方法,而非用户调用的代码,用户调用就是在@Bean方法内部你调用了其他@bean标注的方法,Spring会进行区分
Object result = factoryMethod.invoke(factoryBean, args);
if (result == null) {
result = new NullBean();
}
return result;
}
finally {
//5. 将原来的给设置进行,因为之前的那个@bean还没有被创建完的
if (priorInvokedFactoryMethod != null) {
currentlyInvokedFactoryMethod.set(priorInvokedFactoryMethod);
}
else {
currentlyInvokedFactoryMethod.remove();
}
}
}
catch (InvocationTargetException ex) {
throw new BeanInstantiationException(factoryMethod, msg, ex.getTargetException());
}
}
//省略其他代码
}
ThreadLocal是什么就不说了,大家如果想了解可以查看:深入理解ThreadLocal的原理及内存泄漏问题,这里面会详细的介绍ThreadLocal。
看到这里可能有点蒙,没关系,使用一个例子进行描述:
@Configuration
@ComponentScan("com.luban.configuration")
public class Config {
@Bean
public School school() {
School school = new School();
school.setStudent(student());
return school;
}
@Bean
public Student student() {
return new Student();
}
}
首先明白一点什么是容器调用的方法,什么是用户自己代码内部调用的方法:容器调用的方法指的就是在容器实例化Bean的时候,会自动调用调用加了@Bean的方法,将它变成一个Bean,就是Spring会在创建名称为school的Bean是,会调用school方法,这就是容器调用的,用户代码内部调用的方法,指的是在@Bean注解内部,你手动的调用了其他标注了@Bean的注解,就是你在school方法内部调用了student方法,这个方法就是用户自己调用的,Spring在进行处理@Configuration标注的类时是不同的。
标注了@Bean注解的方法,也会变成一个beanDefinition,不过在beanDefinition内部是没有BeanClass的,只有FactoryMethod属性,指向它是使用哪个方法创建对象,在进行bean创建的时候,先判断FactoryMethod是否为空(如果是@Bean这样的类型就不为空),那么就会使用工厂方法创建对象,假设我们在创建名称为school的bean,那么先会执行代码块11的instantiate方法,将currentlyInvokedFactoryMethod置为school方法,进行标记school方法是容器调用的方法,然后就会进行方法拦截代码块9 BeanMethodInterceptor类的intercept方法,此时在其第4步的判断中isCurrentlyInvokedFactoryMethod(beanMethod)中为true,然后就会执行Config类的school方法,在执行到school.setStudent(student()),就会进入student()方法里面,在进行之前也会进入方法拦截器,此时又会执行代码块9 BeanMethodInterceptor类的intercept方法,此时在其第4步的判断中isCurrentlyInvokedFactoryMethod(beanMethod)中为false了,currentlyInvokedFactoryMethod是school方法,用于标记容器调用的方法为school方法,而我们在school内部调用了student方法,导致就不一样,所以为flase,然后就执行容器的getBean方法,去获取student的bean,发现没有就去创建,然后就会进行执行到代码块11的instantiate方法,先取出之前设置的,那就是school,并将currentlyInvokedFactoryMethod置为student方法,等到student的bean创建好后,又把currentlyInvokedFactoryMethod置为school方法。
到这里关于@Configuration源码就看完了,更深层的细节我还没整懂,上面如果说的哪个地方有错误的可以指出来。
另外,我们来可以来看一下使用cglib增强的类长什么样,可以帮助我们更好的理解cglib的原理:
首先加上System.setProperty(DebuggingClassWriter.DEBUG_LOCATION_PROPERTY, "C:\\class")的代码,然后运行这个mian方法就可以了,然后就可以去C盘中查看cglib生成的类。
public class Test01 {
public static void main(String[] args) {
System.setProperty(DebuggingClassWriter.DEBUG_LOCATION_PROPERTY, "C:\\class");
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(Config.class);
}
}
这里我先贴出来没有增强之前的代码:
@Configuration
@ComponentScan("com.luban.configuration")
public class Config {
@Bean
public School school() {
return new School();
}
}
再贴出来增强后的代码:
//继承了需要增强的Config类,并实现了EnhancedConfiguration接口
public class Config$$EnhancerBySpringCGLIB$$308299b4 extends Config implements ConfigurationClassEnhancer.EnhancedConfiguration {
private boolean CGLIB$BOUND;
public static Object CGLIB$FACTORY_DATA;
private static final ThreadLocal CGLIB$THREAD_CALLBACKS;
private static final Callback[] CGLIB$STATIC_CALLBACKS;
private MethodInterceptor CGLIB$CALLBACK_0;
private MethodInterceptor CGLIB$CALLBACK_1;
private NoOp CGLIB$CALLBACK_2;
private static Object CGLIB$CALLBACK_FILTER;
private static final Method CGLIB$school$0$Method;
private static final MethodProxy CGLIB$school$0$Proxy;
private static final Object[] CGLIB$emptyArgs;
private static final Method CGLIB$setBeanFactory$5$Method;
private static final MethodProxy CGLIB$setBeanFactory$5$Proxy;
//正如我们所说的,会有一个BeanFactory类型,名称为$$beanFactory的属性
public BeanFactory $$beanFactory;
static void CGLIB$STATICHOOK1() {
CGLIB$THREAD_CALLBACKS = new ThreadLocal();
CGLIB$emptyArgs = new Object[0];
Class clazz1 = Class.forName("com.luban.configuration.Config$$EnhancerBySpringCGLIB$$308299b4");
Class clazz2;
CGLIB$setBeanFactory$5$Method = ReflectUtils.findMethods(new String[] { "setBeanFactory", "(Lorg/springframework/beans/factory/BeanFactory;)V" }, (clazz2 = Class.forName("org.springframework.beans.factory.BeanFactoryAware")).getDeclaredMethods())[0];
CGLIB$setBeanFactory$5$Proxy = MethodProxy.create(clazz2, clazz1, "(Lorg/springframework/beans/factory/BeanFactory;)V", "setBeanFactory", "CGLIB$setBeanFactory$5");
ReflectUtils.findMethods(new String[] { "setBeanFactory", "(Lorg/springframework/beans/factory/BeanFactory;)V" }, (clazz2 = Class.forName("org.springframework.beans.factory.BeanFactoryAware")).getDeclaredMethods());
CGLIB$school$0$Method = ReflectUtils.findMethods(new String[] { "school", "()Lcom/luban/School;" }, (clazz2 = Class.forName("com.luban.configuration.Config")).getDeclaredMethods())[0];
CGLIB$school$0$Proxy = MethodProxy.create(clazz2, clazz1, "()Lcom/luban/School;", "school", "CGLIB$school$0");
ReflectUtils.findMethods(new String[] { "school", "()Lcom/luban/School;" }, (clazz2 = Class.forName("com.luban.configuration.Config")).getDeclaredMethods());
}
final School CGLIB$school$0() {
return super.school();
}
//这个方法是被增强的方法
public final School school() {
if (this.CGLIB$CALLBACK_0 == null)
CGLIB$BIND_CALLBACKS(this);
//进行方法的拦截
return (this.CGLIB$CALLBACK_0 != null) ?
(School)this.CGLIB$CALLBACK_0.intercept(this, CGLIB$school$0$Method, CGLIB$emptyArgs, CGLIB$school$0$Proxy) : super.school();
}
final void CGLIB$setBeanFactory$5(BeanFactory paramBeanFactory) throws BeansException {
super.setBeanFactory(paramBeanFactory);
}
public final void setBeanFactory(BeanFactory paramBeanFactory) throws BeansException {
if (this.CGLIB$CALLBACK_1 == null)
CGLIB$BIND_CALLBACKS(this);
if (this.CGLIB$CALLBACK_1 != null) {
(new Object[1])[0] = paramBeanFactory;
return;
}
super.setBeanFactory(paramBeanFactory);
}
public Config$$EnhancerBySpringCGLIB$$308299b4() {
CGLIB$BIND_CALLBACKS(this);
}
public static void CGLIB$SET_THREAD_CALLBACKS(Callback[] paramArrayOfCallback) {
CGLIB$THREAD_CALLBACKS.set(paramArrayOfCallback);
}
public static void CGLIB$SET_STATIC_CALLBACKS(Callback[] paramArrayOfCallback) {
CGLIB$STATIC_CALLBACKS = paramArrayOfCallback;
}
private static final void CGLIB$BIND_CALLBACKS(Object paramObject) {
Config$$EnhancerBySpringCGLIB$$308299b4 config$$EnhancerBySpringCGLIB$$308299b4 = (Config$$EnhancerBySpringCGLIB$$308299b4)paramObject;
if (!config$$EnhancerBySpringCGLIB$$308299b4.CGLIB$BOUND) {
config$$EnhancerBySpringCGLIB$$308299b4.CGLIB$BOUND = true;
if (CGLIB$THREAD_CALLBACKS.get() == null) {
CGLIB$THREAD_CALLBACKS.get();
if (CGLIB$STATIC_CALLBACKS == null)
return;
}
config$$EnhancerBySpringCGLIB$$308299b4.CGLIB$CALLBACK_2 = (NoOp)((Callback[])CGLIB$THREAD_CALLBACKS.get())[2];
config$$EnhancerBySpringCGLIB$$308299b4.CGLIB$CALLBACK_1 = (MethodInterceptor)((Callback[])CGLIB$THREAD_CALLBACKS.get())[1];
config$$EnhancerBySpringCGLIB$$308299b4.CGLIB$CALLBACK_0 = (MethodInterceptor)((Callback[])CGLIB$THREAD_CALLBACKS.get())[0];
}
}
static {
CGLIB$STATICHOOK2();
CGLIB$STATICHOOK1();
}
static void CGLIB$STATICHOOK2() {}
}
@Configuration总结:
在Spring的生命周期中,其中会beanFactory的后置处理器,执行时,先执行beanFactory的子接口BeanDefinitionRegistryPostProcessor,在这一步完成会包的扫描和类上面注解信息的解析,然后将普通类转换成beanDefinition对象,其中标注了@Configuration注解的类,会在beanDefinition中标记为full。然后再执行BeanFactoryPostProcessor的postProcessBeanFactory方法,在这一步会对beanDefinition中标记为full的进行cglib代理增强,使用cglib代理增强就意味着需要增强类不能使用final关键字修饰,在这个cglib代理增强类中是间接的实现BeanFactoryAware接口,这样就可以拿到BeanFactory,并且会创建一个public、BeanFactory类型名称为$$beanFactory进行接收BeanFactory, 并且cglib代理类会对方法进行拦截,这样就不用了每次都去new一个对象,所以使用@Configuration可以保证bean的单一性,并且,如果标注了@Bean注解的方法返回的对象是FactoryBean类型的,Spring会进行二次拦截判断,确保是获取的bean是单一的。