在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是單一的。