一、@Configuration
1.1 未加@Configuration
<!--logback-test.xml,配置不打印日志-->
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<include resource="org/springframework/boot/logging/logback/base.xml" />
<logger name="org.springframework" level="OFF"/>
</configuration>
1.2 加上@Configuration
1.3 Cglib動態(tài)代理
二、源碼跟蹤
2.1 AnnotationConfigApplicationContext
2.2 AnnotationConfigApplicationContext#AnnotationConfigApplicationContext(Class<?>... annotatedClasses)
2.3 AbstractApplicationContext#refresh()
@Override
public void refresh() throws BeansException, IllegalStateException {
// 同步,線程安全; 防止 fresh還沒結束 就又進入改方法 導致容器初始化錯亂
synchronized (this.startupShutdownMonitor) {
// 準備刷新 記錄開始時間 設置幾個標志位 驗證環(huán)境屬性
prepareRefresh();
// 告訴子類刷新內(nèi)部bean工廠 創(chuàng)建BeanFactory 并且獲取BeanDefinition的定義信息
/**
* obtainFreshBeanFactory();方法
* 解析為一個個beanDefinition 放在我們beanDefinitionMap中管理起來
* 1. refreshBeanFactory(); 核心方法
* AbstractRefreshableApplicationContext#refreshBeanFactory()
* 創(chuàng)建DefaultListableBeanFactory 并設置屬性
* 加載BeanFactory; 根據(jù)不同的類型,調(diào)用不同的方法
* org.springframework.context.support.AbstractXmlApplicationContext#loadBeanDefinitions(org.springframework.beans.factory.support.DefaultListableBeanFactory)
*/
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
// 準備在這種情況下使用的bean工廠 向beanFactory中設置一些屬性 。對BeanFactory 進行各種功能填充
prepareBeanFactory(beanFactory);
try {
// 允許在上下文 的子類中對bean工廠進行后處理 由子類去實現(xiàn); 主要是自定義去使用
postProcessBeanFactory(beanFactory);
// 第5步 【BeanFactoryPostProcessors ;bean工廠后置處理器】調(diào)用我們的bean工廠后置處理器 (所有實現(xiàn)接口BeanFactoryPostProcessor接口的)
// 主要是
// 會在此將class掃描成BeanDefinition 并注冊bean 到一個BeanDefinitionMap中 這個過程使用到代理
//BeanFactoryPostProcessor 可以 用于容器完成初始化()
// 此處可以 還沒有實例化Bean之前讀取Bean的信息,并作出一些修改。
// 例如修改Bean的屬性,修改Bean的scope等
invokeBeanFactoryPostProcessors(beanFactory);
//https://blog.csdn.net/caihaijiang/article/details/35552859
// 【BeanPostProcessors ;bean后置處理器】 注冊BeanPostProcessor
// BeanPostProcessor是Bean的后置處理器,
// 在Bean的初始化方法[InitializingBean 以及init-method]前,后執(zhí)行。
registerBeanPostProcessors(beanFactory);
// 為上下文初始化Message 源, 即不同語言的消息體, 國際化處理 i18n
initMessageSource();
// 初始化事件傳播器
//初始化應用消息廣播器, 并放入"applicationEventMulticaster" bean 中
initApplicationEventMulticaster();
// 擴展的一個實現(xiàn) ,留給子類來初始化其它的Bean。如springboot內(nèi)嵌的tomcat在這個階段完成
onRefresh();
// 注冊監(jiān)聽器
// 在所有注冊的bean 中查找Listener bean , 注冊到消息廣播報中
registerListeners();
/**第11步
對于非抽象類、非延遲初始化的單例bean,
在spring容器啟動的時候調(diào)用getBean方法來實例化bean, 并進行相關初始化工作,
getBean方法最終調(diào)用AbstractAutowireCapableBeanFactory.doCreateBean方法
*/
// 在創(chuàng)建BeanFactory的過程中,BeanDefinition注冊到了BeanFactory中的一個ConCurretHashMap對象中
// 以BeanName為key,BeanDefinition為value ; 實例化所有剩余的(非延遲初始化)單例。
finishBeanFactoryInitialization(beanFactory);
// 第12步 最后一步:發(fā)布相應的事件。
//完成刷新過程, 通知生命周期處現(xiàn)器lifecycleProcessor 刷新過程, 同時發(fā)出ContextRefreshEvent 通知別人
finishRefresh();
}
catch (BeansException ex) {
if (logger.isWarnEnabled()) {
logger.warn("Exception encountered during context initialization - " +
"cancelling refresh attempt: " + ex);
}
// 第13步 銷毀以創(chuàng)建的Bean
destroyBeans();
//取消refresh操作,重置容器的同步標識
cancelRefresh(ex);
// Propagate exception to caller.
throw ex;
}
finally {
resetCommonCaches();
}
}
}
2.4 AbstractApplicationContext#invokeBeanFactoryPostProcessors
2.5 PostProcessorRegistrationDelegate#invokeBeanFactoryPostProcessors
public static void invokeBeanFactoryPostProcessors(
ConfigurableListableBeanFactory beanFactory, List<BeanFactoryPostProcessor> beanFactoryPostProcessors) {
Set<String> processedBeans = new HashSet<>();
// 對BeanDefinitionRegistry 類型的處理
if (beanFactory instanceof BeanDefinitionRegistry) {
BeanDefinitionRegistry registry = (BeanDefinitionRegistry) beanFactory;
List<BeanFactoryPostProcessor> regularPostProcessors = new ArrayList<>();
// 用于存放BeanDefinitionRegistryPostProcessor
List<BeanDefinitionRegistryPostProcessor> registryProcessors = new ArrayList<>();
// 遍歷所有的beanFactoryPostProcessors,將BeanDefinitionRegistryPostProcessor和普通BeanFactoryPostProcessor區(qū)分開
for (BeanFactoryPostProcessor postProcessor : beanFactoryPostProcessors) {
if (postProcessor instanceof BeanDefinitionRegistryPostProcessor) {
BeanDefinitionRegistryPostProcessor registryProcessor =
(BeanDefinitionRegistryPostProcessor) postProcessor;
/**
對于BeanDefinitionRegistryPostProcessor 類型, 在BeanFactoryPostProcessor 的
基礎上還有自己定義的方法,需要先調(diào)用
*/
registryProcessor.postProcessBeanDefinitionRegistry(registry);
registryProcessors.add(registryProcessor);
}
else {
// 記錄常規(guī)BeanFactoryPostProcessor
regularPostProcessors.add(postProcessor);
}
}
/**
不要在這里初始化FactoryBeans: 我們需要保留所有常規(guī)bean未初始化,讓bean工廠后處理器應用到它們!
BeanDefinitionRegistryPostProcessors之間的分離實現(xiàn)排好序,點好,等等。
獲取spring配置文件中定義的所有實現(xiàn)BeanFactoryPostProcessor接口的bean,然后根據(jù)優(yōu)先級進行排序
*/
List<BeanDefinitionRegistryPostProcessor> currentRegistryProcessors = new ArrayList<>();
// 首先,調(diào)用實現(xiàn)優(yōu)先排序的BeanDefinitionRegistryPostProcessors
String[] postProcessorNames =
beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
for (String ppName : postProcessorNames) {
// PriorityOrdered.class 優(yōu)先排序
if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
processedBeans.add(ppName);
}
}
sortPostProcessors(currentRegistryProcessors, beanFactory);
registryProcessors.addAll(currentRegistryProcessors);
invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
currentRegistryProcessors.clear();
// 接下來,調(diào)用實現(xiàn)Ordered的BeanDefinitionRegistryPostProcessors
postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
for (String ppName : postProcessorNames) {
// Ordered.class
if (!processedBeans.contains(ppName) && beanFactory.isTypeMatch(ppName, Ordered.class)) {
currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
processedBeans.add(ppName);
}
}
sortPostProcessors(currentRegistryProcessors, beanFactory);
registryProcessors.addAll(currentRegistryProcessors);
invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
currentRegistryProcessors.clear();
// Finally, invoke all other BeanDefinitionRegistryPostProcessors until no further ones appear.
boolean reiterate = true;
while (reiterate) {
reiterate = false;
postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
for (String ppName : postProcessorNames) {
if (!processedBeans.contains(ppName)) {
currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
processedBeans.add(ppName);
reiterate = true;
}
}
sortPostProcessors(currentRegistryProcessors, beanFactory);
registryProcessors.addAll(currentRegistryProcessors);
invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
currentRegistryProcessors.clear();
}
// Now, invoke the postProcessBeanFactory callback of all processors handled so far.
// 調(diào)用ConfigurationClassPostProcessor#postProcessBeanFactory增強配置類
// 通過cglib生成增強類
// 設置beanDefinition的beanClass為增強類,讓@Bean生成的bean是單例
invokeBeanFactoryPostProcessors(registryProcessors, beanFactory);
invokeBeanFactoryPostProcessors(regularPostProcessors, beanFactory);
}
else {
// Invoke factory processors registered with the context instance.
invokeBeanFactoryPostProcessors(beanFactoryPostProcessors, beanFactory);
}
// BeanFactoryPostProcessor.class類型
// Do not initialize FactoryBeans here: We need to leave all regular beans
// uninitialized to let the bean factory post-processors apply to them!
String[] postProcessorNames =
beanFactory.getBeanNamesForType(BeanFactoryPostProcessor.class, true, false);
// 篩選出bean工程中存在的所有實現(xiàn)BeanFactoryPostProcessor類的類名稱
// Separate between BeanFactoryPostProcessors that implement PriorityOrdered,
// Ordered, and the rest.
List<BeanFactoryPostProcessor> priorityOrderedPostProcessors = new ArrayList<>();
List<String> orderedPostProcessorNames = new ArrayList<>();
List<String> nonOrderedPostProcessorNames = new ArrayList<>();
for (String ppName : postProcessorNames) {
if (processedBeans.contains(ppName)) {
// skip - already processed in first phase above
// 已經(jīng)存在了,不再處理
}
else if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
// 為PriorityOrdered類型
priorityOrderedPostProcessors.add(beanFactory.getBean(ppName, BeanFactoryPostProcessor.class));
}
else if (beanFactory.isTypeMatch(ppName, Ordered.class)) {
// 為Ordered類型
orderedPostProcessorNames.add(ppName);
}
else {
// 這個就是我們當前需要關心的PostProcessors
//nonOrderedPostProcessors添加的不是bean實例,而是BeanDefinition
nonOrderedPostProcessorNames.add(ppName);
}
}
// First, invoke the BeanFactoryPostProcessors that implement PriorityOrdered.
sortPostProcessors(priorityOrderedPostProcessors, beanFactory);
invokeBeanFactoryPostProcessors(priorityOrderedPostProcessors, beanFactory);
// Next, invoke the BeanFactoryPostProcessors that implement Ordered.
List<BeanFactoryPostProcessor> orderedPostProcessors = new ArrayList<>();
for (String postProcessorName : orderedPostProcessorNames) {
orderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class));
}
sortPostProcessors(orderedPostProcessors, beanFactory);
invokeBeanFactoryPostProcessors(orderedPostProcessors, beanFactory);
// Finally, invoke all other BeanFactoryPostProcessors.
List<BeanFactoryPostProcessor> nonOrderedPostProcessors = new ArrayList<>();
for (String postProcessorName : nonOrderedPostProcessorNames) {
nonOrderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class));
}
invokeBeanFactoryPostProcessors(nonOrderedPostProcessors, beanFactory);
// Clear cached merged bean definitions since the post-processors might have
// modified the original metadata, e.g. replacing placeholders in values...
beanFactory.clearMetadataCache();
}
2.6 PostProcessorRegistrationDelegate#invokeBeanFactoryPostProcessors
2.7 ConfigurationClassPostProcessor#postProcessBeanFactory
2.8 ConfigurationClaassPostProcessor#enhanceConfigurationClasses
public void enhanceConfigurationClasses(ConfigurableListableBeanFactory beanFactory) {
Map<String, AbstractBeanDefinition> configBeanDefs = new LinkedHashMap<>();
for (String beanName : beanFactory.getBeanDefinitionNames()) {
BeanDefinition beanDef = beanFactory.getBeanDefinition(beanName);
// 判斷是否是一個全注解類
// 掃描是全注解類?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");
}
else if (logger.isInfoEnabled() && beanFactory.containsSingleton(beanName)) {
logger.info("Cannot enhance @Configuration bean definition '" + beanName +
"' since its singleton instance has been created too early. The typical cause " +
"is a non-static @Bean method with a BeanDefinitionRegistryPostProcessor " +
"return type: Consider declaring such methods as 'static'.");
}
// 是全注解,需要代理,添加到configBeanDefs中
configBeanDefs.put(beanName, (AbstractBeanDefinition) beanDef);
}
}
if (configBeanDefs.isEmpty()) {
// nothing to enhance -> return immediately
return;
}
ConfigurationClassEnhancer enhancer = new ConfigurationClassEnhancer();
// 遍歷這個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
Class<?> configClass = beanDef.resolveBeanClass(this.beanClassLoader);
if (configClass != null) {
// 進行cglib代理,為@Configuration注解的類生成增強類
Class<?> enhancedClass = enhancer.enhance(configClass, this.beanClassLoader);
if (configClass != enhancedClass) {
if (logger.isTraceEnabled()) {
logger.trace(String.format("Replacing bean definition '%s' existing class '%s' with " +
"enhanced class '%s'", entry.getKey(), configClass.getName(), enhancedClass.getName()));
}
// 再通過beanDef.setBeanClass(enhancedClass)修改beanDefinition的BeanClass屬性,
// 在bean實例化階段,會利用反射技術將beanClass屬性對應的類實例化出來
// 所以最終實例化出來的@Configuration bean是一個代理類的實例
beanDef.setBeanClass(enhancedClass);
}
}
}
catch (Throwable ex) {
throw new IllegalStateException("Cannot load configuration class: " + beanDef.getBeanClassName(), ex);
}
}
2.9 ConfigurationClassUtils#checkConfigurationClassCandidate
1.在ConfigurationClassUtils類中的checkConfigurationClassCandidate標記是Full @Configuration還是lite @Bean mode
2.通過"full".equals(configClassAttr)判斷是否是全類注解是全注解
3.則將beandefinition放入map中configBeanDefs.put
4.遍歷這個map
5.使用cglib技術為配置類生成一個enhancedClass
6.通過enhancer.enhance進行cglib代理,為@Configuration注解的類生成增強類
7.再通過beanDef.setBeanClass(enhancedClass)修改beanDefinition的BeanClass屬性,在bean實例化階段,會利用反射技術將beanClass屬性對應的類實例化出來,所以最終實例化出來的@Configuration bean是一個代理類的實例
使用了@Configuration注解的類,屬于Full @Configuration。@Con?guration類允許通過調(diào)用同一類中的其他@Bean方法來定義bean之間的依賴關系,保證@Bean的對象作用域受到控制,避免多例。
@Configuration類中的@Bean地方會被CGLIB進行代理。Spring會攔截該方法的執(zhí)行,在默認單例情況下,容器中只有一個Bean,所以我們多次調(diào)用user()方法,獲取的都是同一個對象。
對于@Configuration注解的類中@Bean標記的方法,返回的都是一個bean,在增強的方法中,Spring會先去容器中查看一下是否有這個bean的實例了,如果有了的話,就返回已有對象,沒有的話就創(chuàng)建一個,然后放到容器中。
2.10 ConfigurationClassEnhancer#enhance
2.11 ConfigurationClassEnhancer#newEnhancer
2.12 ConfigurationClassEnhancer#CallBacks
2.13 ConfigurationClassEnhancer#intercept
2.13.1 ConfigurationClassEnhancer#isCurrentlyInvokedFactoryMethod
2.14 ConfigurationClassEnhancer#resolveBeanReference
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.
// 判斷他是否正在創(chuàng)建
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;
}
}
}
Object beanInstance = (useArgs ? beanFactory.getBean(beanName, beanMethodArgs) :
beanFactory.getBean(beanName));
if (!ClassUtils.isAssignableValue(beanMethod.getReturnType(), beanInstance)) {
// Detect package-protected NullBean instance through equals(null) check
if (beanInstance.equals(null)) {
if (logger.isDebugEnabled()) {
logger.debug(String.format("@Bean method %s.%s called as bean reference " +
"for type [%s] returned null bean; resolving to null value.",
beanMethod.getDeclaringClass().getSimpleName(), beanMethod.getName(),
beanMethod.getReturnType().getName()));
}
beanInstance = null;
}
else {
String msg = String.format("@Bean method %s.%s called as bean reference " +
"for type [%s] but overridden by non-compatible bean instance of type [%s].",
beanMethod.getDeclaringClass().getSimpleName(), beanMethod.getName(),
beanMethod.getReturnType().getName(), beanInstance.getClass().getName());
try {
BeanDefinition beanDefinition = beanFactory.getMergedBeanDefinition(beanName);
msg += " Overriding bean of same name declared in: " + beanDefinition.getResourceDescription();
}
catch (NoSuchBeanDefinitionException ex) {
// Ignore - simply no detailed message then.
}
throw new IllegalStateException(msg);
}
}
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);
}
}
}
三、總結
- lite @Bean mode :當@Bean方法在沒有使用@Configuration注解的類中聲明時稱之為lite @Bean mode
- Full @Configuration:如果@Bean方法在使用@Configuration注解的類中聲明時稱之為Full @Configuration
Full @Configuration
中的@Bean
方法會被CGLIB所代理,而 lite @Bean mode
中的@Bean
方法不會被CGLIB代理
@Configuration注解作用
1.告訴spring這是一個配置類,相當于spring的xml配置文件
2.被@Configuration 注解的類,會被cglib代理進行增強
3.@Con?guration類允許通過調(diào)用同一類中的其他@Bean方法來定義bean之間的依賴關系,保證@Bean的對象作用域受到控制,避免多例
@Configuration注解底層是如何實現(xiàn)的,通過源碼咱們可以反推并總結為以下幾點:
1.Spring首先會獲取到所有的beanDefenition
2.ConfigurationClassUtils類中checkConfigurationClassCandidate方法判斷是Full @Configuration還是lite @Bean mode
3.通過ConfigurationClassPostProcessor后置處理器遍歷所有的beanDefenition
4.將標記了Full @Configuration模式的beanDefenition,會對這個類進行cglib代理,生成一個代理類,并把這個類設置到BeanDefenition的Class屬性中
5.配置類會被CGLIB增強(生成代理對象),放進IoC容器內(nèi)的是代理
6.對于內(nèi)部類是沒有限制的:可以是Full模式或者Lite模式
7.配置類內(nèi)部可以通過方法調(diào)用來處理依賴,并且能夠保證是同一個實例,都指向IoC內(nèi)的那個單例
8.需要用這個Bean實例的時候,從這個Class屬性中拿到的Class對象進行反射,最終反射出來的是代理增強后的類
9.通過@Configuration標注類的Bean,Spring會先去容器中查看是否有這個Bean實例,如果有就返回已有的對象,沒有就創(chuàng)建一個,然后放到容器中
本篇關于 Spring 中的 @Configuration 注解的詳細內(nèi)容就介紹到此結束了,想要了解更多相關 Spring 其他注解 以及 @Configuration 注解的其他詳細內(nèi)容請搜索W3Cschool以前的文章或繼續(xù)瀏覽下面的相關文章,也希望大家以后多多支持!