Spring中@Configuration源碼深度解析(二)

      在Spring中@Configuration源碼深度解析(一)中已經說到了執行代碼塊4PostProcessorRegistrationDelegate#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是單一的。  

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章