源碼分析@EnableAutoConfiguration在SpringBoot中的加載和實例化過程
萬里長征第一步,我們先理解下什麼是EnableAutoConfiguration?
什麼是EnableAutoConfiguration註解?
在哪?
org.springframework.boot.autoconfigure.EnableAutoConfiguration
EnableAutoConfiguration概述
我們先來看下源碼
package org.springframework.boot.autoconfigure;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Inherited;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.context.embedded.EmbeddedServletContainerFactory;
import org.springframework.boot.context.embedded.tomcat.TomcatEmbeddedServletContainerFactory;
import org.springframework.context.annotation.Conditional;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import org.springframework.core.io.support.SpringFactoriesLoader;
/**
* Enable auto-configuration of the Spring Application Context, attempting to guess and
* configure beans that you are likely to need. Auto-configuration classes are usually
* applied based on your classpath and what beans you have defined. For example, If you
* have {@code tomcat-embedded.jar} on your classpath you are likely to want a
* {@link TomcatEmbeddedServletContainerFactory} (unless you have defined your own
* {@link EmbeddedServletContainerFactory} bean).
* <p>
* When using {@link SpringBootApplication}, the auto-configuration of the context is
* automatically enabled and adding this annotation has therefore no additional effect.
* <p>
* Auto-configuration tries to be as intelligent as possible and will back-away as you
* define more of your own configuration. You can always manually {@link #exclude()} any
* configuration that you never want to apply (use {@link #excludeName()} if you don't
* have access to them). You can also exclude them via the
* {@code spring.autoconfigure.exclude} property. Auto-configuration is always applied
* after user-defined beans have been registered.
* <p>
* The package of the class that is annotated with {@code @EnableAutoConfiguration},
* usually via {@code @SpringBootApplication}, has specific significance and is often used
* as a 'default'. For example, it will be used when scanning for {@code @Entity} classes.
* It is generally recommended that you place {@code @EnableAutoConfiguration} (if you're
* not using {@code @SpringBootApplication}) in a root package so that all sub-packages
* and classes can be searched.
* <p>
* Auto-configuration classes are regular Spring {@link Configuration} beans. They are
* located using the {@link SpringFactoriesLoader} mechanism (keyed against this class).
* Generally auto-configuration beans are {@link Conditional @Conditional} beans (most
* often using {@link ConditionalOnClass @ConditionalOnClass} and
* {@link ConditionalOnMissingBean @ConditionalOnMissingBean} annotations).
*/
@SuppressWarnings("deprecation")
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@AutoConfigurationPackage
@Import(EnableAutoConfigurationImportSelector.class)
public @interface EnableAutoConfiguration {
String ENABLED_OVERRIDE_PROPERTY = "spring.boot.enableautoconfiguration";
/**
* Exclude specific auto-configuration classes such that they will never be applied.
* @return the classes to exclude
*/
Class<?>[] exclude() default {};
/**
* Exclude specific auto-configuration class names such that they will never be
* applied.
* @return the class names to exclude
* @since 1.3.0
*/
String[] excludeName() default {};
}
類圖
注意“@Import(EnableAutoConfigurationImportSelector.class)” 部分。後邊源碼分析中會使用到。
說明
EnableAutoConfiguration註解的功能大概如下。
- 開啓Spring應該上下文的自動配置,儘可能去加載需要的配置Beans。自動配置類,一般是根據你的classpath路徑來應用的。
- 當你使用了SpringBootApplication註解,在context中自動加載配置就已經開啓,不需要其他操作。
- 可以通過exclude()傳入Class類型;excludeName() 傳入名稱來排除其他類型的加載。自動加載的配置始終是在普通用戶定義的Bean加載之後執行。
- 默認EnableAutoConfiguration掃描的是當前啓用註解的Class對象的目錄作爲root目錄。所以這個目錄下的所有子目錄都會被掃描。
- 自動裝載的配置類,也是常規的SpringBean(被@Configuration修飾,@Configuration則被@Component修飾(如果你寫的@Configuration在啓動類的包名下,開啓註解掃描的情況下,也是會把@Configuration註冊爲Bean對象。))。當然也可以通過SpringFactoriesLoader的機制來定位到對應的org.springframework.boot.autoconfigure.EnableAutoConfiguration類(不在同用戶掃描包目錄中)。
- 一般配合Conditional、ConditionalOnClass、ConditionalOnMissingBean一起使用。
測試項目
│ pom.xml
└─src
└─main
├─java
│ └─com
│ └─baigt
│ ├─autoconfig
│ │ BaigtAutoConfig.java
│ │
│ └─sb
│ SBStarter.java
│
└─resources
└─META-INF
spring.factories
- pom
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.baigt</groupId>
<artifactId>SpringBootCodeAnalyze</artifactId>
<version>1.0-SNAPSHOT</version>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.5.14.RELEASE</version>
</parent>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
- BaigtAutoConfig
注意和啓動類不在一個目錄中
package com.baigt.autoconfig;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* 測試Autoconfig
*/
@Configuration
public class BaigtAutoConfig {
@Bean
public String env(){
return new String("Baigt Test");
}
}
- SBStarter
注意和config不在一個目錄 中
package com.baigt.sb;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ConfigurableApplicationContext;
/**
* 測試@EnableAutoConfig加載的流程(加載自定義的配置類,不在同一個目錄中)
*/
@SpringBootApplication
public class SBStarter{
public static void main(String[] args) {
SpringApplication sb=new SpringApplication(SBStarter.class);
ConfigurableApplicationContext run = sb.run(args);
System.out.println(run.getBean("baigt",String.class));
}
}
- spring.factories
# Auto Configure
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
com.baigt.autoconfig.BaigtAutoConfig
正題(源碼)
我們只分析和EnableAutoConfiguration相關的源碼。
new SpringApplication
初始化環境(是否是web),設置ApplicationContextInitializer、ApplicationListener,設置啓動類的class到mainApplicationClass上。我們的例子中不是web環境。
//初始化入口
public SpringApplication(Object... sources) {
initialize(sources);
}
private void initialize(Object[] sources) {
if (sources != null && sources.length > 0) {
this.sources.addAll(Arrays.asList(sources));
}
this.webEnvironment = deduceWebEnvironment();
setInitializers((Collection) getSpringFactoriesInstances(
ApplicationContextInitializer.class));
setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));
this.mainApplicationClass = deduceMainApplicationClass();
}
SpringApplication
啓動SpringBoot項目,我們這裏只關注Context創建和實例化AutoConfig相關的邏輯。注意我們的示例不是Web項目,只是個普通的java項目。
run
這裏主要有三處,一個是createApplicationContext,一個是prepareContext,一個是refreshContext。
public ConfigurableApplicationContext run(String... args) {
//...
ConfigurableApplicationContext context = null;
//。。。
listeners.starting();
try {
//....
//注意這部分 創建context
context = createApplicationContext();
analyzers = new FailureAnalyzers(context);
prepareContext(context, environment, listeners, applicationArguments,
printedBanner);
//刷新context(實例化各種post以及Bean)
refreshContext(context);
afterRefresh(context, applicationArguments);
// ...
return context;
}
catch (Throwable ex) {
}
}
後邊再講refreshContext。
createApplicationContext
創建Context,我們不是web項目哦。所以我們Context是AnnotationConfigApplicationContext類型。
public static final String DEFAULT_CONTEXT_CLASS = "org.springframework.context."
+ "annotation.AnnotationConfigApplicationContext";
protected ConfigurableApplicationContext createApplicationContext() {
Class<?> contextClass = this.applicationContextClass;
if (contextClass == null) {
try {
//前邊我們分析到,不是web 環境!! 所以我們Context是AnnotationConfigApplicationContext類型。
contextClass = Class.forName(this.webEnvironment
? DEFAULT_WEB_CONTEXT_CLASS : DEFAULT_CONTEXT_CLASS);
}
catch (ClassNotFoundException ex) {
//
}
}//這裏實例化的是 AnnotationConfigApplicationContext類(無參構造)
return (ConfigurableApplicationContext) BeanUtils.instantiate(contextClass);
}
AnnotationConfigApplicationContext
類圖
我們先看下類圖。
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-mnBCr3Vt-1593910393257)(https://gitee.com/bgt0314/vnoteimg/raw/master/1593835963_20200704121238961_5862.png =1066x)]
- 是BeanDefinitionRegistry
- 是BeanFactory
- 是Resource
AnnotationConfigApplicationContext()
從前邊我們瞭解到,我們的context是AnnotationConfigApplicationContext,無參構造會實例化AnnotatedBeanDefinitionReader和ClassPathBeanDefinitionScanner。因爲Autoconfig相關的都會被@Configuration修飾,所以我們只關注AnnotatedBeanDefinitionReader,它是註解BeanDefinition讀取器。我們主要分析說明的是這個。
public AnnotationConfigApplicationContext() {
this.reader = new AnnotatedBeanDefinitionReader(this);
this.scanner = new ClassPathBeanDefinitionScanner(this);
}
AnnotatedBeanDefinitionReader
AnnotatedBeanDefinitionReader(BeanDefinitionRegistry)
AnnotationConfigApplicationContext就是一個BeanDefinitionRegistry實例。將AnnotationConfigApplicationContext的實例傳遞到AnnotatedBeanDefinitionReader中使用。下邊我們分析這個AnnotatedBeanDefinitionReader類實例化過程中都做了什麼。
public AnnotatedBeanDefinitionReader(BeanDefinitionRegistry registry) {
this(registry, getOrCreateEnvironment(registry));
}
public AnnotatedBeanDefinitionReader(BeanDefinitionRegistry registry, Environment environment) {
Assert.notNull(registry, "BeanDefinitionRegistry must not be null");
Assert.notNull(environment, "Environment must not be null");
this.registry = registry;
this.conditionEvaluator = new ConditionEvaluator(registry, environment, null);
AnnotationConfigUtils.registerAnnotationConfigProcessors(this.registry);
}
AnnotationConfigUtils
registerAnnotationConfigProcessors
註冊註解相關的後置處理器,比如ConfigurationClassPostProcessor、AutowiredAnnotationBeanPostProcessor、RequiredAnnotationBeanPostProcessor、CommonAnnotationBeanPostProcessor、PersistenceAnnotationBeanPostProcessor、EventListenerMethodProcessor、DefaultEventListenerFactory等。我們這裏只關注配置類相關的源碼部分。
public static void registerAnnotationConfigProcessors(BeanDefinitionRegistry registry) {
registerAnnotationConfigProcessors(registry, null);
}
public static Set<BeanDefinitionHolder> registerAnnotationConfigProcessors(
BeanDefinitionRegistry registry, Object source) {
DefaultListableBeanFactory beanFactory = unwrapDefaultListableBeanFactory(registry);
Set<BeanDefinitionHolder> beanDefs = new LinkedHashSet<BeanDefinitionHolder>(4);
// 註冊ConfigurationClassPostProcessor處理器
if (!registry.containsBeanDefinition(CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME)) {
RootBeanDefinition def = new RootBeanDefinition(ConfigurationClassPostProcessor.class);
def.setSource(source);
beanDefs.add(registerPostProcessor(registry, def, CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME));
}
return beanDefs;
}
ConfigurationClassPostProcessor
類圖
- 是BeanDefinitionRegistryPostProcessor
- 是BeanFactoryPostProcessor
- 是PriorityOrdered
- 上邊兩個接口,是關鍵,後邊要用到!!!
registerPostProcessor
註冊ConfigurationClassPostProcessor處理器到BeanFactory中。
private static BeanDefinitionHolder registerPostProcessor(
BeanDefinitionRegistry registry, RootBeanDefinition definition, String beanName) {
definition.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
registry.registerBeanDefinition(beanName, definition);
return new BeanDefinitionHolder(definition, beanName);
}
BeanDefinitionRegistry
從入口處我們知道,registry是AnnotationConfigApplicationContext的實例,被傳遞過來。它的父類是GenericApplicationContext。在無參實例化時,GenericApplicationContext會持有一個DefaultListableBeanFactory對象。
-
結構圖
-
BeanFactory
GenericApplicationContext的實例化BeanFactory過程
private final DefaultListableBeanFactory beanFactory;
public GenericApplicationContext() {
this.beanFactory = new DefaultListableBeanFactory();
}
public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition)
throws BeanDefinitionStoreException {
this.beanFactory.registerBeanDefinition(beanName, beanDefinition);
}
DefaultListableBeanFactory
registerBeanDefinition
將BeanDefinition定義交給BeanFactory管理。主要在beanDefinitionMap、beanDefinitionNames這幾個map對象中存儲。
public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition)
throws BeanDefinitionStoreException {
Assert.hasText(beanName, "Bean name must not be empty");
Assert.notNull(beanDefinition, "BeanDefinition must not be null");
if (beanDefinition instanceof AbstractBeanDefinition) {
try {
((AbstractBeanDefinition) beanDefinition).validate();
}
catch (BeanDefinitionValidationException ex) {
throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName,
"Validation of bean definition failed", ex);
}
}
BeanDefinition oldBeanDefinition;
oldBeanDefinition = this.beanDefinitionMap.get(beanName);
if (oldBeanDefinition != null) {
if (!isAllowBeanDefinitionOverriding()) {
throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName,
"Cannot register bean definition [" + beanDefinition + "] for bean '" + beanName +
"': There is already [" + oldBeanDefinition + "] bound.");
}
else if (oldBeanDefinition.getRole() < beanDefinition.getRole()) {
// e.g. was ROLE_APPLICATION, now overriding with ROLE_SUPPORT or ROLE_INFRASTRUCTURE
if (this.logger.isWarnEnabled()) {
this.logger.warn("Overriding user-defined bean definition for bean '" + beanName +
"' with a framework-generated bean definition: replacing [" +
oldBeanDefinition + "] with [" + beanDefinition + "]");
}
}
else if (!beanDefinition.equals(oldBeanDefinition)) {
if (this.logger.isInfoEnabled()) {
this.logger.info("Overriding bean definition for bean '" + beanName +
"' with a different definition: replacing [" + oldBeanDefinition +
"] with [" + beanDefinition + "]");
}
}
else {
if (this.logger.isDebugEnabled()) {
this.logger.debug("Overriding bean definition for bean '" + beanName +
"' with an equivalent definition: replacing [" + oldBeanDefinition +
"] with [" + beanDefinition + "]");
}
}
this.beanDefinitionMap.put(beanName, beanDefinition);
}
else {
if (hasBeanCreationStarted()) {
// Cannot modify startup-time collection elements anymore (for stable iteration)
synchronized (this.beanDefinitionMap) {
this.beanDefinitionMap.put(beanName, beanDefinition);
List<String> updatedDefinitions = new ArrayList<String>(this.beanDefinitionNames.size() + 1);
updatedDefinitions.addAll(this.beanDefinitionNames);
updatedDefinitions.add(beanName);
this.beanDefinitionNames = updatedDefinitions;
if (this.manualSingletonNames.contains(beanName)) {
Set<String> updatedSingletons = new LinkedHashSet<String>(this.manualSingletonNames);
updatedSingletons.remove(beanName);
this.manualSingletonNames = updatedSingletons;
}
}
}
else {
// Still in startup registration phase
this.beanDefinitionMap.put(beanName, beanDefinition);
this.beanDefinitionNames.add(beanName);
this.manualSingletonNames.remove(beanName);
}
this.frozenBeanDefinitionNames = null;
}
if (oldBeanDefinition != null || containsSingleton(beanName)) {
resetBeanDefinition(beanName);
}
}
至此ConfigurationClassPostProcessor已經被BeanFactory管理起來。下邊我們再來分析後邊這個對象是怎麼使用。那麼我們再次回到SpringApplication的Run方法中prepareContext和**refreshContext(context);**部分。
SpringApplication
prepareContext
我們重點關注下load部分,傳入的是當前啓動類。source是new SpringApplication時傳入的Class對象,也就是SBStarter.class。
private void prepareContext(ConfigurableApplicationContext context,
ConfigurableEnvironment environment, SpringApplicationRunListeners listeners,
ApplicationArguments applicationArguments, Banner printedBanner) {
//。。。。。
// Load the sources
Set<Object> sources = getSources();
Assert.notEmpty(sources, "Sources must not be empty");
load(context, sources.toArray(new Object[sources.size()]));
// 。。。。
}
load
加載bean到ApplicationContext中.BeanDefinitionLoader是持有Context對象的。Context本身就是個registry.
protected void load(ApplicationContext context, Object[] sources) {
if (logger.isDebugEnabled()) {
logger.debug(
"Loading source " + StringUtils.arrayToCommaDelimitedString(sources));
}
BeanDefinitionLoader loader = createBeanDefinitionLoader(
getBeanDefinitionRegistry(context), sources);
if (this.beanNameGenerator != null) {
loader.setBeanNameGenerator(this.beanNameGenerator);
}
if (this.resourceLoader != null) {
loader.setResourceLoader(this.resourceLoader);
}
if (this.environment != null) {
loader.setEnvironment(this.environment);
}
loader.load();
}
BeanDefinitionLoader
load
我們的source就是SBStarter.class,也就是會執行load((Class<?>) source)。最後註冊成類型AnnotatedBeanDefinition的BeanDefinition。
public int load() {
int count = 0;
for (Object source : this.sources) {
count += load(source);
}
return count;
}
private int load(Object source) {
Assert.notNull(source, "Source must not be null");
if (source instanceof Class<?>) {
return load((Class<?>) source);
}
if (source instanceof Resource) {
return load((Resource) source);
}
if (source instanceof Package) {
return load((Package) source);
}
if (source instanceof CharSequence) {
return load((CharSequence) source);
}
throw new IllegalArgumentException("Invalid source type " + source.getClass());
}
private int load(Class<?> source) {
if (isGroovyPresent()) {
// Any GroovyLoaders added in beans{} DSL can contribute beans here
if (GroovyBeanDefinitionSource.class.isAssignableFrom(source)) {
GroovyBeanDefinitionSource loader = BeanUtils.instantiateClass(source,
GroovyBeanDefinitionSource.class);
load(loader);
}
}
//如果SBStarter是個組件的話,會註冊到beanDefinition上去。
if (isComponent(source)) {
//AnnotatedBeanDefinitionReader是前邊實例化時創建。目的是註冊一個類型AnnotatedBeanDefinition的BeanDefinition
this.annotatedReader.register(source);
return 1;
}
return 0;
}
isComponent
- @SpringBootApplication是SpringBootConfiguration類型的。
-
SpringBootConfiguration是Configuration類型的。
-
Configuration是Component類型的
-
最後SBStarter也就是個Component類型的
AnnotatedBeanDefinitionReader
register
//annotatedClasses=com.baigt.sb.SBStarter
public void register(Class<?>... annotatedClasses) {
for (Class<?> annotatedClass : annotatedClasses) {
registerBean(annotatedClass);
}
}
registerBean
這裏我們要注意的是我們是創建了一個AnnotatedGenericBeanDefinition類型的BeanDefinition對象通過BeanDefinitionReaderUtils工具進行註冊的。
public void registerBean(Class<?> annotatedClass) {
registerBean(annotatedClass, null, (Class<? extends Annotation>[]) null);
}
public void registerBean(Class<?> annotatedClass, Class<? extends Annotation>... qualifiers) {
registerBean(annotatedClass, null, qualifiers);
}
public void registerBean(Class<?> annotatedClass, String name, Class<? extends Annotation>... qualifiers) {
//注意這裏,我是一個AnnotatedGenericBeanDefinition類型的BeanDefinition實例
AnnotatedGenericBeanDefinition abd = new AnnotatedGenericBeanDefinition(annotatedClass);
if (this.conditionEvaluator.shouldSkip(abd.getMetadata())) {
return;
}
ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(abd);
abd.setScope(scopeMetadata.getScopeName());
String beanName = (name != null ? name : this.beanNameGenerator.generateBeanName(abd, this.registry));
AnnotationConfigUtils.processCommonDefinitionAnnotations(abd);
if (qualifiers != null) {
for (Class<? extends Annotation> qualifier : qualifiers) {
if (Primary.class == qualifier) {
abd.setPrimary(true);
}
else if (Lazy.class == qualifier) {
abd.setLazyInit(true);
}
else {
abd.addQualifier(new AutowireCandidateQualifier(qualifier));
}
}
}
BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(abd, beanName);
definitionHolder = AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);
//我是在這裏和context關聯上的
BeanDefinitionReaderUtils.registerBeanDefinition(definitionHolder, this.registry);
}
BeanDefinitionReaderUtils
registerBeanDefinition
注意傳入的registry,AnnotationConfigApplicationContext本身就是個BeanDefinitionRegistry。而這個部分最後調用的是AnnotationConfigApplicationContext在實例化中隱式實例化父類GenericApplicationContext時創建的一個DefaultListableBeanFactory對象的registerBeanDefinition方法。這就又回到了ConfiguationClassPostProcessor時registerBeanDefinition的過程。因此這裏就不再繼續深入分析。最終的結果是交給了BeanFactory統一管理BeanDefinition!!
public static void registerBeanDefinition(
BeanDefinitionHolder definitionHolder, BeanDefinitionRegistry registry)
throws BeanDefinitionStoreException {
// Register bean definition under primary name.
String beanName = definitionHolder.getBeanName();
registry.registerBeanDefinition(beanName, definitionHolder.getBeanDefinition());
// Register aliases for bean name, if any.
String[] aliases = definitionHolder.getAliases();
if (aliases != null) {
for (String alias : aliases) {
registry.registerAlias(beanName, alias);
}
}
}
SpringApplication
refreshContext
刷新Context和註冊關機鉤子;注意傳入的是一個AnnotationConfigApplicationContext實例。我們主要分析refresh
private void refreshContext(ConfigurableApplicationContext context) {
refresh(context);
if (this.registerShutdownHook) {
try {
context.registerShutdownHook();
}
catch (AccessControlException ex) {
// Not allowed in some environments.
}
}
}
protected void refresh(ApplicationContext applicationContext) {
Assert.isInstanceOf(AbstractApplicationContext.class, applicationContext);
((AbstractApplicationContext) applicationContext).refresh();
}
刷新用的是AbstractApplicationContext中的refresh方法。
AbstractApplicationContext
org.springframework.context.support.AbstractApplicationContext
refresh
在ConfigurationClassPostProcessor那一部分,我們知道它是一個BeanFactoryPostProcessor。所以我們一定要看的是invokeBeanFactoryPostProcessors部分的邏輯,其次因爲Configuration註解類中相關的如@Bean修飾的方法也是要實例化的,所以我們還要看的是finishBeanFactoryInitialization中的邏輯。
public void refresh() throws BeansException, IllegalStateException {
synchronized (this.startupShutdownMonitor) {
// refresh的前置準備,比如設置startTime,開啓激活狀態、關閉close狀態等等等
prepareRefresh();
//告訴子類去刷新內容Bean工廠(從類圖中可以明顯看出來入口類實例也是個bean工廠)
// 觀察和刷新BeanFactory
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
//提前設置一些在該context中使用的屬性,比如Classloader、Callback、environment等
prepareBeanFactory(beanFactory);
try {
// 通知context子類,後置處理beanFactory。比如用一系列的Webcontext子類
postProcessBeanFactory(beanFactory);
// 將BeanFactoryPostProcessor在當前Context中註冊爲Bean
invokeBeanFactoryPostProcessors(beanFactory);
// 註冊BeanPostProcessor來攔截Bean創建的後置處理。
registerBeanPostProcessors(beanFactory);
// 爲當前Context初始化MessageSource
initMessageSource();
// 爲當前context初始化應用事件廣播
initApplicationEventMulticaster();
// 初始化其他特殊的bean對象 比如webcontext
onRefresh();
// 檢查監聽Bean 併發布他們(ApplicationListener)
registerListeners();
// 實例化BeanFactory中所有的其他的單例對象集合(非延遲的)
finishBeanFactoryInitialization(beanFactory);
// 最後發佈LifecycleProcessor和ContextRefreshedEvent事件
finishRefresh();
}
catch (BeansException ex) {
if (logger.isWarnEnabled()) {
logger.warn("Exception encountered during context initialization - " +
"cancelling refresh attempt: " + ex);
}
// 失敗銷燬bean
destroyBeans();
// Reset 'active' flag.
cancelRefresh(ex);
// Propagate exception to caller.
throw ex;
}
finally {
// Reset common introspection caches in Spring's core, since we
// might not ever need metadata for singleton beans anymore...
resetCommonCaches();
}
}
}
invokeBeanFactoryPostProcessors
使用委託模式來執行BeanFactoryPostProcessors。注意委託類PostProcessorRegistrationDelegate接收的beanFactory是我們的Context實例(是個BeanFactory,同時它也持有ConfigurationClassPostProcessor的BeanDefinition信息)。getBeanFactoryPostProcessors部分中的BeanFactoryPostProcessors是其他步驟中注入的後置器,我們這裏不關注。直接進委託類中繼續 分析。
protected void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory) {
PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, getBeanFactoryPostProcessors());
// Detect a LoadTimeWeaver and prepare for weaving, if found in the meantime
// (e.g. through an @Bean method registered by ConfigurationClassPostProcessor)
if (beanFactory.getTempClassLoader() == null && beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {
beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));
beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));
}
}
PostProcessorRegistrationDelegate
org.springframework.context.support.PostProcessorRegistrationDelegate
invokeBeanFactoryPostProcessors
我們不關注beanFactoryPostProcessors部分傳入的參數,因爲ConfigurationClassPostProcessor不在此。前邊我們分析到ConfigurationClassPostProcessor同時是一個BeanDefinitionRegistryPostProcessor,invokeBeanFactoryPostProcessors中與此有關的邏輯我們重點看下!!!
- 首先執行實現PriorityOrdered接口的BeanDefinitionRegistryPostProcessor
- 其次執行實現Ordered接口的BeanDefinitionRegistryPostProcessor
- 最後執行其他所有的BeanDefinitionRegistryPostProcessor對象
public static void invokeBeanFactoryPostProcessors(
ConfigurableListableBeanFactory beanFactory, List<BeanFactoryPostProcessor> beanFactoryPostProcessors) {
// Invoke BeanDefinitionRegistryPostProcessors first, if any.
Set<String> processedBeans = new HashSet<String>();
if (beanFactory instanceof BeanDefinitionRegistry) {
BeanDefinitionRegistry registry = (BeanDefinitionRegistry) beanFactory;
List<BeanFactoryPostProcessor> regularPostProcessors = new LinkedList<BeanFactoryPostProcessor>();
List<BeanDefinitionRegistryPostProcessor> registryProcessors = new LinkedList<BeanDefinitionRegistryPostProcessor>();
for (BeanFactoryPostProcessor postProcessor : beanFactoryPostProcessors) {
//省略
}
List<BeanDefinitionRegistryPostProcessor> currentRegistryProcessors = new ArrayList<BeanDefinitionRegistryPostProcessor>();
// 首先執行一個實現PriorityOrdered接口的BeanDefinitionRegistryPostProcessors!!! 這不就是我們的ConfigurationClassPostProcessor嘛!!!
String[] postProcessorNames =
beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
for (String ppName : postProcessorNames) {
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();
// 其次執行一個實現Ordered接口的BeanDefinitionRegistryPostProcessors!!! 且沒有在processedBeans中
postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
for (String ppName : postProcessorNames) {
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();
// 最後執行其他 BeanDefinitionRegistryPostProcessor
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.
invokeBeanFactoryPostProcessors(registryProcessors, beanFactory);
invokeBeanFactoryPostProcessors(regularPostProcessors, beanFactory);
}
else {
// Invoke factory processors registered with the context instance.
invokeBeanFactoryPostProcessors(beanFactoryPostProcessors, beanFactory);
}
// 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);
// Separate between BeanFactoryPostProcessors that implement PriorityOrdered,
// Ordered, and the rest.
List<BeanFactoryPostProcessor> priorityOrderedPostProcessors = new ArrayList<BeanFactoryPostProcessor>();
List<String> orderedPostProcessorNames = new ArrayList<String>();
List<String> nonOrderedPostProcessorNames = new ArrayList<String>();
for (String ppName : postProcessorNames) {
if (processedBeans.contains(ppName)) {
// skip - already processed in first phase above
}
else if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
priorityOrderedPostProcessors.add(beanFactory.getBean(ppName, BeanFactoryPostProcessor.class));
}
else if (beanFactory.isTypeMatch(ppName, Ordered.class)) {
orderedPostProcessorNames.add(ppName);
}
else {
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<BeanFactoryPostProcessor>();
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<BeanFactoryPostProcessor>();
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();
}
- 我們只關注第一個,因爲ConfigurationClassPostProcessor實現了PriorityOrdered接口!!!
invokeBeanDefinitionRegistryPostProcessors
傳入的postProcessors是ConfigurationClassPostProcessor,傳入的registry則是我們的AnnotationConfigApplicationContext(前邊也提到了他也是個BeanDefinitionRegistry)。哇偶!終於到了我們ConfigurationClassPostProcessor的源碼部分了(postProcessBeanDefinitionRegistry)
private static void invokeBeanDefinitionRegistryPostProcessors(
Collection<? extends BeanDefinitionRegistryPostProcessor> postProcessors, BeanDefinitionRegistry registry) {
for (BeanDefinitionRegistryPostProcessor postProcessor : postProcessors) {
postProcessor.postProcessBeanDefinitionRegistry(registry);
}
}
ConfigurationClassPostProcessor
postProcessBeanDefinitionRegistry
這個方法比較簡單,有些檢查,核心方法是processConfigBeanDefinitions。我們跟進去看下。
public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) {
int registryId = System.identityHashCode(registry);
if (this.registriesPostProcessed.contains(registryId)) {
throw new IllegalStateException(
"postProcessBeanDefinitionRegistry already called on this post-processor against " + registry);
}
if (this.factoriesPostProcessed.contains(registryId)) {
throw new IllegalStateException(
"postProcessBeanFactory already called on this post-processor against " + registry);
}
this.registriesPostProcessed.add(registryId);
processConfigBeanDefinitions(registry);
}
processConfigBeanDefinitions
類的Doc說明是構建和驗證由Configuration註解修飾的Class對象。注意注入的BeanDefinitionRegistry是一個DefaultListableBeanFactory實例,因此也是一個SingletonBeanRegistry對象。具體可自行分析類圖的繼承關係。這裏會加載我們啓動類SBStarter這個配置類。
啓動類SBStarter是我們自定義的類,是在org.springframework.boot.SpringApplication#prepareContext步驟中注入的。
/**
* Build and validate a configuration model based on the registry of
* {@link Configuration} classes.
*/
public void processConfigBeanDefinitions(BeanDefinitionRegistry registry) {
List<BeanDefinitionHolder> configCandidates = new ArrayList<BeanDefinitionHolder>();
String[] candidateNames = registry.getBeanDefinitionNames();
for (String beanName : candidateNames) {
BeanDefinition beanDef = registry.getBeanDefinition(beanName);
//是否已經加載過
if (ConfigurationClassUtils.isFullConfigurationClass(beanDef) ||
ConfigurationClassUtils.isLiteConfigurationClass(beanDef)) {
}
//沒有加載過 就放入configCandidates集合中 這裏只有我們手寫的啓動類SBStarter是沒有被加載過的。具體加載過程上邊我們已經說過了 我們這裏看下SBStarter的後續操作。
else if (ConfigurationClassUtils.checkConfigurationClassCandidate(beanDef, this.metadataReaderFactory)) {
configCandidates.add(new BeanDefinitionHolder(beanDef, beanName));
}
}
// 沒有就快速返回
if (configCandidates.isEmpty()) {
return;
}
// 根據Order排序
Collections.sort(configCandidates, new Comparator<BeanDefinitionHolder>() {
@Override
public int compare(BeanDefinitionHolder bd1, BeanDefinitionHolder bd2) {
int i1 = ConfigurationClassUtils.getOrder(bd1.getBeanDefinition());
int i2 = ConfigurationClassUtils.getOrder(bd2.getBeanDefinition());
return (i1 < i2) ? -1 : (i1 > i2) ? 1 : 0;
}
});
// Detect any custom bean name generation strategy supplied through the enclosing application context
SingletonBeanRegistry sbr = null;
if (registry instanceof SingletonBeanRegistry) {
sbr = (SingletonBeanRegistry) registry;
if (!this.localBeanNameGeneratorSet && sbr.containsSingleton(CONFIGURATION_BEAN_NAME_GENERATOR)) {
BeanNameGenerator generator = (BeanNameGenerator) sbr.getSingleton(CONFIGURATION_BEAN_NAME_GENERATOR);
this.componentScanBeanNameGenerator = generator;
this.importBeanNameGenerator = generator;
}
}
// 解析每一個 @Configuration class 這裏只解析到我們開啓SpringBootApplication註解的SBStarter類是Configuration class,我們寫的那個不在掃描路徑中。
ConfigurationClassParser parser = new ConfigurationClassParser(
this.metadataReaderFactory, this.problemReporter, this.environment,
this.resourceLoader, this.componentScanBeanNameGenerator, registry);
Set<BeanDefinitionHolder> candidates = new LinkedHashSet<BeanDefinitionHolder>(configCandidates);
Set<ConfigurationClass> alreadyParsed = new HashSet<ConfigurationClass>(configCandidates.size());
do {
//從SBStarter爲入口解析Configuration相關Class
parser.parse(candidates);
parser.validate();
Set<ConfigurationClass> configClasses = new LinkedHashSet<ConfigurationClass>(parser.getConfigurationClasses());
configClasses.removeAll(alreadyParsed);
// Read the model and create bean definitions based on its content
if (this.reader == null) {
this.reader = new ConfigurationClassBeanDefinitionReader(
registry, this.sourceExtractor, this.resourceLoader, this.environment,
this.importBeanNameGenerator, parser.getImportRegistry());
}
// 在這裏加載成BeanDefinition 並交給BeanFactory管理。
this.reader.loadBeanDefinitions(configClasses);
alreadyParsed.addAll(configClasses);
candidates.clear();
if (registry.getBeanDefinitionCount() > candidateNames.length) {
String[] newCandidateNames = registry.getBeanDefinitionNames();
Set<String> oldCandidateNames = new HashSet<String>(Arrays.asList(candidateNames));
Set<String> alreadyParsedClasses = new HashSet<String>();
for (ConfigurationClass configurationClass : alreadyParsed) {
alreadyParsedClasses.add(configurationClass.getMetadata().getClassName());
}
for (String candidateName : newCandidateNames) {
if (!oldCandidateNames.contains(candidateName)) {
BeanDefinition bd = registry.getBeanDefinition(candidateName);
if (ConfigurationClassUtils.checkConfigurationClassCandidate(bd, this.metadataReaderFactory) &&
!alreadyParsedClasses.contains(bd.getBeanClassName())) {
candidates.add(new BeanDefinitionHolder(bd, candidateName));
}
}
}
candidateNames = newCandidateNames;
}
}
while (!candidates.isEmpty());
// Register the ImportRegistry as a bean in order to support ImportAware @Configuration classes
if (sbr != null) {
if (!sbr.containsSingleton(IMPORT_REGISTRY_BEAN_NAME)) {
sbr.registerSingleton(IMPORT_REGISTRY_BEAN_NAME, parser.getImportRegistry());
}
}
if (this.metadataReaderFactory instanceof CachingMetadataReaderFactory) {
((CachingMetadataReaderFactory) this.metadataReaderFactory).clearCache();
}
}
ConfigurationClassParser
parse(set)
這裏主要分析兩個部分,一個是再次Parse(不同入參),一個是完整流程(processDeferredImportSelectors())
- SBStarter注入的BeanDefiniton是個AnnotatedBeanDefinition
觸發parse(AnnotationMetadata metadata, String beanName)調用
public void parse(Set<BeanDefinitionHolder> configCandidates) {
this.deferredImportSelectors = new LinkedList<DeferredImportSelectorHolder>();
for (BeanDefinitionHolder holder : configCandidates) {
BeanDefinition bd = holder.getBeanDefinition();
try {
if (bd instanceof AnnotatedBeanDefinition) {
parse(((AnnotatedBeanDefinition) bd).getMetadata(), holder.getBeanName());
}
else if (bd instanceof AbstractBeanDefinition && ((AbstractBeanDefinition) bd).hasBeanClass()) {
parse(((AbstractBeanDefinition) bd).getBeanClass(), holder.getBeanName());
}
else {
parse(bd.getBeanClassName(), holder.getBeanName());
}
}
catch (BeanDefinitionStoreException ex) {
throw ex;
}
catch (Throwable ex) {
throw new BeanDefinitionStoreException(
"Failed to parse configuration class [" + bd.getBeanClassName() + "]", ex);
}
}
processDeferredImportSelectors();
}
parse(AnnotationMetadata, String)
protected final void parse(AnnotationMetadata metadata, String beanName) throws IOException {
processConfigurationClass(new ConfigurationClass(metadata, beanName));
}
processConfigurationClass
處理ConfigurationClass對象。主要是doProcessConfigurationClass部分。
protected void processConfigurationClass(ConfigurationClass configClass) throws IOException {
if (this.conditionEvaluator.shouldSkip(configClass.getMetadata(), ConfigurationPhase.PARSE_CONFIGURATION)) {
return;
}
ConfigurationClass existingClass = this.configurationClasses.get(configClass);
if (existingClass != null) {
if (configClass.isImported()) {
if (existingClass.isImported()) {
existingClass.mergeImportedBy(configClass);
}
// Otherwise ignore new imported config class; existing non-imported class overrides it.
return;
}
else {
// Explicit bean definition found, probably replacing an import.
// Let's remove the old one and go with the new one.
this.configurationClasses.remove(configClass);
for (Iterator<ConfigurationClass> it = this.knownSuperclasses.values().iterator(); it.hasNext();) {
if (configClass.equals(it.next())) {
it.remove();
}
}
}
}
// Recursively process the configuration class and its superclass hierarchy.
SourceClass sourceClass = asSourceClass(configClass);
do {
sourceClass = doProcessConfigurationClass(configClass, sourceClass);
}
while (sourceClass != null);
this.configurationClasses.put(configClass, configClass);
}
doProcessConfigurationClass
這裏很重要了,也是很複雜的一部分。不過也是SpringBoot可以不使用Xml就能掃描註解相關類的關鍵部分。下邊大概涉及到@PropertySources,@PropertySource,@ComponentScans.class, @ComponentScan.class,@Import,@ImportSource等等。我們主要關注的是@Import部分。爲什麼?因爲我們還是目的就是想看@EnableAutoConfiguration是怎麼加載不同目錄下的配置類,並實例化的!!! 而在@EnableAutoConfiguration中有使用了@Import,@Import(EnableAutoConfigurationImportSelector.class)
protected final SourceClass doProcessConfigurationClass(ConfigurationClass configClass, SourceClass sourceClass)
throws IOException {
// 處理成員class 比如內部class 靜態class
processMemberClasses(configClass, sourceClass);
// 處理 @PropertySource annotations
for (AnnotationAttributes propertySource : AnnotationConfigUtils.attributesForRepeatable(
sourceClass.getMetadata(), PropertySources.class,
org.springframework.context.annotation.PropertySource.class)) {
if (this.environment instanceof ConfigurableEnvironment) {
processPropertySource(propertySource);
}
else {
logger.warn("Ignoring @PropertySource annotation on [" + sourceClass.getMetadata().getClassName() +
"]. Reason: Environment must implement ConfigurableEnvironment");
}
}
// 處理 @ComponentScan annotations
Set<AnnotationAttributes> componentScans = AnnotationConfigUtils.attributesForRepeatable(
sourceClass.getMetadata(), ComponentScans.class, ComponentScan.class);
if (!componentScans.isEmpty() &&
!this.conditionEvaluator.shouldSkip(sourceClass.getMetadata(), ConfigurationPhase.REGISTER_BEAN)) {
for (AnnotationAttributes componentScan : componentScans) {
// The config class is annotated with @ComponentScan -> perform the scan immediately
Set<BeanDefinitionHolder> scannedBeanDefinitions =
this.componentScanParser.parse(componentScan, sourceClass.getMetadata().getClassName());
// Check the set of scanned definitions for any further config classes and parse recursively if needed
for (BeanDefinitionHolder holder : scannedBeanDefinitions) {
BeanDefinition bdCand = holder.getBeanDefinition().getOriginatingBeanDefinition();
if (bdCand == null) {
bdCand = holder.getBeanDefinition();
}
if (ConfigurationClassUtils.checkConfigurationClassCandidate(bdCand, this.metadataReaderFactory)) {
parse(bdCand.getBeanClassName(), holder.getBeanName());
}
}
}
}
// 處理 any @Import annotations 我們Spring.factories就是在這一部分 會解析出org.springframework.boot.autoconfigure.EnableAutoConfigurationImportSelector
processImports(configClass, sourceClass, getImports(sourceClass), true);
// 處理 any @ImportResource annotations 如果手動引入了xml配置文件 基本是這種的
if (sourceClass.getMetadata().isAnnotated(ImportResource.class.getName())) {
AnnotationAttributes importResource =
AnnotationConfigUtils.attributesFor(sourceClass.getMetadata(), ImportResource.class);
String[] resources = importResource.getStringArray("locations");
Class<? extends BeanDefinitionReader> readerClass = importResource.getClass("reader");
for (String resource : resources) {
String resolvedResource = this.environment.resolveRequiredPlaceholders(resource);
configClass.addImportedResource(resolvedResource, readerClass);
}
}
// Process individual @Bean methods
Set<MethodMetadata> beanMethods = retrieveBeanMethodMetadata(sourceClass);
for (MethodMetadata methodMetadata : beanMethods) {
configClass.addBeanMethod(new BeanMethod(methodMetadata, configClass));
}
// Process default methods on interfaces
processInterfaces(configClass, sourceClass);
// Process superclass, if any
if (sourceClass.getMetadata().hasSuperClass()) {
String superclass = sourceClass.getMetadata().getSuperClassName();
if (!superclass.startsWith("java") && !this.knownSuperclasses.containsKey(superclass)) {
this.knownSuperclasses.put(superclass, configClass);
// Superclass found, return its annotation metadata and recurse
return sourceClass.getSuperClass();
}
}
// No superclass -> processing is complete
return null;
}
processImports
從EnableAutoConfigurationImportSelector中獲取Spring.factories中key=org.springframework.boot.autoconfigure.EnableAutoConfiguration的需要自動化加載的配置類。最後存放在deferredImportSelectors集合中。
private void processImports(ConfigurationClass configClass, SourceClass currentSourceClass,
Collection<SourceClass> importCandidates, boolean checkForCircularImports) {
if (importCandidates.isEmpty()) {
return;
}
if (checkForCircularImports && isChainedImportOnStack(configClass)) {
this.problemReporter.error(new CircularImportProblem(configClass, this.importStack));
}
else {
this.importStack.push(configClass);
try {
for (SourceClass candidate : importCandidates) {
if (candidate.isAssignable(ImportSelector.class)) {
// Candidate class is an ImportSelector -> delegate to it to determine imports
Class<?> candidateClass = candidate.loadClass();
//實例化EnableAutoConfigurationImportSelector 存放在deferredImportSelectors中
ImportSelector selector = BeanUtils.instantiateClass(candidateClass, ImportSelector.class);
ParserStrategyUtils.invokeAwareMethods(
selector, this.environment, this.resourceLoader, this.registry);
if (this.deferredImportSelectors != null && selector instanceof DeferredImportSelector) {
this.deferredImportSelectors.add(
new DeferredImportSelectorHolder(configClass, (DeferredImportSelector) selector));
}
else {
String[] importClassNames = selector.selectImports(currentSourceClass.getMetadata());
Collection<SourceClass> importSourceClasses = asSourceClasses(importClassNames);
processImports(configClass, currentSourceClass, importSourceClasses, false);
}
}
else {
//省略代碼
}
}
}
catch (BeanDefinitionStoreException ex) {
//
}
finally {
this.importStack.pop();
}
}
}
parse(Set configCandidates)
返回到此處,執行 processDeferredImportSelectors方法。處理剛纔存放在deferredImportSelectors中的import對象。
public void parse(Set<BeanDefinitionHolder> configCandidates) {
this.deferredImportSelectors = new LinkedList<DeferredImportSelectorHolder>();
for (BeanDefinitionHolder holder : configCandidates) {
BeanDefinition bd = holder.getBeanDefinition();
try {
if (bd instanceof AnnotatedBeanDefinition) {
parse(((AnnotatedBeanDefinition) bd).getMetadata(), holder.getBeanName());
}
else if (bd instanceof AbstractBeanDefinition && ((AbstractBeanDefinition) bd).hasBeanClass()) {
parse(((AbstractBeanDefinition) bd).getBeanClass(), holder.getBeanName());
}
else {
parse(bd.getBeanClassName(), holder.getBeanName());
}
}
catch (BeanDefinitionStoreException ex) {
throw ex;
}
}
//處理我們剛纔存放在這裏的deferredImportSelectors
processDeferredImportSelectors();
}
processDeferredImportSelectors
調用ImportSelector類的selectImports方法,最後遞歸調用processImports來處理其他Configuration類。這裏我們來看下EnableAutoConfigurationImportSelector的selectImports方法。
private void processDeferredImportSelectors() {
List<DeferredImportSelectorHolder> deferredImports = this.deferredImportSelectors;
this.deferredImportSelectors = null;
Collections.sort(deferredImports, DEFERRED_IMPORT_COMPARATOR);
for (DeferredImportSelectorHolder deferredImport : deferredImports) {
ConfigurationClass configClass = deferredImport.getConfigurationClass();
try {
String[] imports = deferredImport.getImportSelector().selectImports(configClass.getMetadata());
processImports(configClass, asSourceClass(configClass), asSourceClasses(imports), false);
}
catch (BeanDefinitionStoreException ex) {
}
}
}
EnableAutoConfigurationImportSelector
@EnableAutoConfiguration 中@Import引入的ImportSelector。我們Ctrl+F12來看下selectImports方法在哪?
AutoConfigurationImportSelector
EnableAutoConfigurationImportSelector 的父類。selectImports方法所在的類。我們重點關注getCandidateConfigurations方法的源碼。通過SpringFactoriesLoader.loadFactoryNames來加載spring.factories中對應key爲EnableAutoConfiguration的ConfigClass集合。
public String[] selectImports(AnnotationMetadata annotationMetadata) {
//如果不是EnableAutoConfigurationImportSelector的時候 isEnabled==true 默認AutoConfigurationImportSelector的isEnable==true ,走後邊的邏輯
if (!isEnabled(annotationMetadata)) {
return NO_IMPORTS;
}
try {
AutoConfigurationMetadata autoConfigurationMetadata = AutoConfigurationMetadataLoader
.loadMetadata(this.beanClassLoader);
AnnotationAttributes attributes = getAttributes(annotationMetadata);
//獲取需要自動化加載配置類 這個是核心類。我們下邊分析
List<String> configurations = getCandidateConfigurations(annotationMetadata,
attributes);
//刪除重複的configClass
configurations = removeDuplicates(configurations);
//排序
configurations = sort(configurations, autoConfigurationMetadata);
Set<String> exclusions = getExclusions(annotationMetadata, attributes);
//刪除exclue掉的Class
checkExcludedClasses(configurations, exclusions);
configurations.removeAll(exclusions);
//處理AutoConfigurationImportFilter
configurations = filter(configurations, autoConfigurationMetadata);
//處理AutoConfigurationImportListener
fireAutoConfigurationImportEvents(configurations, exclusions);
return configurations.toArray(new String[configurations.size()]);
}
catch (IOException ex) {
throw new IllegalStateException(ex);
}
}
// 通過SpringFactoriesLoader加載EnableAutoConfiguration相關的配置類
protected List<String> getCandidateConfigurations(AnnotationMetadata metadata,
AnnotationAttributes attributes) {
List<String> configurations = SpringFactoriesLoader.loadFactoryNames(
getSpringFactoriesLoaderFactoryClass(), getBeanClassLoader());
Assert.notEmpty(configurations,
"No auto configuration classes found in META-INF/spring.factories. If you "
+ "are using a custom packaging, make sure that file is correct.");
return configurations;
}
// 要通過SpringFactories來加載的類
protected Class<?> getSpringFactoriesLoaderFactoryClass() {
return EnableAutoConfiguration.class;
}
SpringFactoriesLoader
loadFactoryNames
//從META-INF/spring.factories的文件中解析內容(所有的spring.factories。包括spring-boot-1.5.14.RELEASE.jar中的)。從中拿到org.springframework.boot.autoconfigure.EnableAutoConfiguration對應的配置類,比如我們自己定義的BaigtAutoConfig類。
public static final String FACTORIES_RESOURCE_LOCATION = "META-INF/spring.factories";
public static List<String> loadFactoryNames(Class<?> factoryClass, ClassLoader classLoader) {
//factoryClassName=org.springframework.boot.autoconfigure.EnableAutoConfiguration
String factoryClassName = factoryClass.getName();
try {
//從META-INF/spring.factories的文件中解析內容(所有的spring.factories。包括spring-boot-1.5.14.RELEASE.jar中的)
Enumeration<URL> urls = (classLoader != null ? classLoader.getResources(FACTORIES_RESOURCE_LOCATION) :
ClassLoader.getSystemResources(FACTORIES_RESOURCE_LOCATION));
List<String> result = new ArrayList<String>();
while (urls.hasMoreElements()) {
URL url = urls.nextElement();
//轉換爲Properties
Properties properties = PropertiesLoaderUtils.loadProperties(new UrlResource(url));
//從properties中獲取EnableAutoConfiguration對應的Value 比如我們的com.baigt.autoconfig.BaigtAutoConfig
String factoryClassNames = properties.getProperty(factoryClassName);
result.addAll(Arrays.asList(StringUtils.commaDelimitedListToStringArray(factoryClassNames)));
}
return result;
}
catch (IOException ex) {
}
}
接下來我們返回到ConfigurationClassPostProcessor的processConfigBeanDefinitions方法。
ConfigurationClassPostProcessor
processConfigBeanDefinitions
接下來我們來看下**this.reader.loadBeanDefinitions(configClasses);**加載我們配置類,交給beanFactory管理。
public void processConfigBeanDefinitions(BeanDefinitionRegistry registry) {
List<BeanDefinitionHolder> configCandidates = new ArrayList<BeanDefinitionHolder>();
String[] candidateNames = registry.getBeanDefinitionNames();
//。。。。
// Parse each @Configuration class
ConfigurationClassParser parser = new ConfigurationClassParser(
this.metadataReaderFactory, this.problemReporter, this.environment,
this.resourceLoader, this.componentScanBeanNameGenerator, registry);
Set<BeanDefinitionHolder> candidates = new LinkedHashSet<BeanDefinitionHolder>(configCandidates);
Set<ConfigurationClass> alreadyParsed = new HashSet<ConfigurationClass>(configCandidates.size());
do {
parser.parse(candidates);
parser.validate();
Set<ConfigurationClass> configClasses = new LinkedHashSet<ConfigurationClass>(parser.getConfigurationClasses());
configClasses.removeAll(alreadyParsed);
// Read the model and create bean definitions based on its content
if (this.reader == null) {
this.reader = new ConfigurationClassBeanDefinitionReader(
registry, this.sourceExtractor, this.resourceLoader, this.environment,
this.importBeanNameGenerator, parser.getImportRegistry());
}
this.reader.loadBeanDefinitions(configClasses);
alreadyParsed.addAll(configClasses);
}
ConfigurationClassBeanDefinitionReader
loadBeanDefinitions
我們只關注我們定義的配置類(BaigtAutoConfig)
public void loadBeanDefinitions(Set<ConfigurationClass> configurationModel) {
TrackedConditionEvaluator trackedConditionEvaluator = new TrackedConditionEvaluator();
for (ConfigurationClass configClass : configurationModel) {
loadBeanDefinitionsForConfigurationClass(configClass, trackedConditionEvaluator);
}
}
loadBeanDefinitionsForConfigurationClass
處理配置類中上的註解(比如Import),以及@Bean方法
private void loadBeanDefinitionsForConfigurationClass(
ConfigurationClass configClass, TrackedConditionEvaluator trackedConditionEvaluator) {
if (trackedConditionEvaluator.shouldSkip(configClass)) {
String beanName = configClass.getBeanName();
if (StringUtils.hasLength(beanName) && this.registry.containsBeanDefinition(beanName)) {
this.registry.removeBeanDefinition(beanName);
}
this.importRegistry.removeImportingClass(configClass.getMetadata().getClassName());
return;
}
// BaigtAutoConfig是通過Import(SelectImports)來創建的ConfigClass 所以這裏是true
if (configClass.isImported()) {
//將該配置類註冊爲BeanDefinition
registerBeanDefinitionForImportedConfigurationClass(configClass);
}
// BaigtAutoConfig中有個@Bean修飾的方法 也會執行這個方法
for (BeanMethod beanMethod : configClass.getBeanMethods()) {
loadBeanDefinitionsForBeanMethod(beanMethod);
}
//配置類中如果使用了ImportSource註解和ImportBeanDefinitionRegistrar。則去加載相關內容成BeanDefinition
loadBeanDefinitionsFromImportedResources(configClass.getImportedResources());
loadBeanDefinitionsFromRegistrars(configClass.getImportBeanDefinitionRegistrars());
}
registerBeanDefinitionForImportedConfigurationClass
將BaigtAutoConfig配置類註冊爲BeanDefinition
private void registerBeanDefinitionForImportedConfigurationClass(ConfigurationClass configClass) {
AnnotationMetadata metadata = configClass.getMetadata();
AnnotatedGenericBeanDefinition configBeanDef = new AnnotatedGenericBeanDefinition(metadata);
ScopeMetadata scopeMetadata = scopeMetadataResolver.resolveScopeMetadata(configBeanDef);
configBeanDef.setScope(scopeMetadata.getScopeName());
String configBeanName = this.importBeanNameGenerator.generateBeanName(configBeanDef, this.registry);
AnnotationConfigUtils.processCommonDefinitionAnnotations(configBeanDef, metadata);
BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(configBeanDef, configBeanName);
definitionHolder = AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);
// 註冊我們的BaigtAutoConfig
this.registry.registerBeanDefinition(definitionHolder.getBeanName(), definitionHolder.getBeanDefinition());
configClass.setBeanName(configBeanName);
}
loadBeanDefinitionsForBeanMethod
解析@Bean方法中相關的屬性,比如設置factoryMethod、InitMethod、DestroyMethod、beanName、alias等。也設置lazy、dependOn等等。最後this.registry.registerBeanDefinition(beanName, beanDefToRegister); 完成配置類中@Bean方法的註冊。this.registry又是我們前邊提到的DefaultListableBeanFactory。交給BeanFactory管理。
private void loadBeanDefinitionsForBeanMethod(BeanMethod beanMethod) {
ConfigurationClass configClass = beanMethod.getConfigurationClass();
MethodMetadata metadata = beanMethod.getMetadata();
String methodName = metadata.getMethodName();
// 這一步(shouldSkip)會設置mergedBeanDefinitions中該name的scope爲單例。即使沒有這個在最後判斷的時候scope=""時也等價於單例
if (this.conditionEvaluator.shouldSkip(metadata, ConfigurationPhase.REGISTER_BEAN)) {
configClass.skippedBeanMethods.add(methodName);
return;
}
if (configClass.skippedBeanMethods.contains(methodName)) {
return;
}
// Consider name and any aliases
AnnotationAttributes bean = AnnotationConfigUtils.attributesFor(metadata, Bean.class);
List<String> names = new ArrayList<String>(Arrays.asList(bean.getStringArray("name")));
String beanName = (!names.isEmpty() ? names.remove(0) : methodName);
// Register aliases even when overridden
for (String alias : names) {
this.registry.registerAlias(beanName, alias);
}
// Has this effectively been overridden before (e.g. via XML)?
if (isOverriddenByExistingDefinition(beanMethod, beanName)) {
if (beanName.equals(beanMethod.getConfigurationClass().getBeanName())) {
throw new BeanDefinitionStoreException(beanMethod.getConfigurationClass().getResource().getDescription(),
beanName, "Bean name derived from @Bean method '" + beanMethod.getMetadata().getMethodName() +
"' clashes with bean name for containing configuration class; please make those names unique!");
}
return;
}
ConfigurationClassBeanDefinition beanDef = new ConfigurationClassBeanDefinition(configClass, metadata);
beanDef.setResource(configClass.getResource());
beanDef.setSource(this.sourceExtractor.extractSource(metadata, configClass.getResource()));
if (metadata.isStatic()) {
// static @Bean method
beanDef.setBeanClassName(configClass.getMetadata().getClassName());
beanDef.setFactoryMethodName(methodName);
}
else {
// instance @Bean method
beanDef.setFactoryBeanName(configClass.getBeanName());
beanDef.setUniqueFactoryMethodName(methodName);
}
beanDef.setAutowireMode(RootBeanDefinition.AUTOWIRE_CONSTRUCTOR);
beanDef.setAttribute(RequiredAnnotationBeanPostProcessor.SKIP_REQUIRED_CHECK_ATTRIBUTE, Boolean.TRUE);
AnnotationConfigUtils.processCommonDefinitionAnnotations(beanDef, metadata);
Autowire autowire = bean.getEnum("autowire");
if (autowire.isAutowire()) {
beanDef.setAutowireMode(autowire.value());
}
String initMethodName = bean.getString("initMethod");
if (StringUtils.hasText(initMethodName)) {
beanDef.setInitMethodName(initMethodName);
}
String destroyMethodName = bean.getString("destroyMethod");
if (destroyMethodName != null) {
beanDef.setDestroyMethodName(destroyMethodName);
}
// Consider scoping
ScopedProxyMode proxyMode = ScopedProxyMode.NO;
AnnotationAttributes attributes = AnnotationConfigUtils.attributesFor(metadata, Scope.class);
if (attributes != null) {
beanDef.setScope(attributes.getString("value"));
proxyMode = attributes.getEnum("proxyMode");
if (proxyMode == ScopedProxyMode.DEFAULT) {
proxyMode = ScopedProxyMode.NO;
}
}
// Replace the original bean definition with the target one, if necessary
BeanDefinition beanDefToRegister = beanDef;
if (proxyMode != ScopedProxyMode.NO) {
BeanDefinitionHolder proxyDef = ScopedProxyCreator.createScopedProxy(
new BeanDefinitionHolder(beanDef, beanName), this.registry,
proxyMode == ScopedProxyMode.TARGET_CLASS);
beanDefToRegister = new ConfigurationClassBeanDefinition(
(RootBeanDefinition) proxyDef.getBeanDefinition(), configClass, metadata);
}
if (logger.isDebugEnabled()) {
logger.debug(String.format("Registering bean definition for @Bean method %s.%s()",
configClass.getMetadata().getClassName(), beanName));
}
this.registry.registerBeanDefinition(beanName, beanDefToRegister);
}
接下來,我們回到 AbstractApplicationContext#refresh
AbstractApplicationContext
refresh
finishBeanFactoryInitialization(beanFactory);
finishBeanFactoryInitialization
通過beanFactory來實例化我們之前交給它管理的BeanDefinition。
protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {
//省略一些代碼
// 實例化一些單例(non-lazyinit)
beanFactory.preInstantiateSingletons();
}
DefaultListableBeanFactory
preInstantiateSingletons
實例化beanDefinitionNames中定義BeanDefinition的單例。當然也包含我們的BaigtAutoConfig中對應的@Bean(name=“baigt”)方法的BeanDefinition
public void preInstantiateSingletons() throws BeansException {
// 從我們放入到beanDefinitionNames中來遍歷進行實例化。
List<String> beanNames = new ArrayList<String>(this.beanDefinitionNames);
// Trigger initialization of all non-lazy singleton beans...
for (String beanName : beanNames) {
RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
if (isFactoryBean(beanName)) {
final FactoryBean<?> factory = (FactoryBean<?>) getBean(FACTORY_BEAN_PREFIX + beanName);
boolean isEagerInit;
if (System.getSecurityManager() != null && factory instanceof SmartFactoryBean) {
isEagerInit = AccessController.doPrivileged(new PrivilegedAction<Boolean>() {
@Override
public Boolean run() {
return ((SmartFactoryBean<?>) factory).isEagerInit();
}
}, getAccessControlContext());
}
else {
isEagerInit = (factory instanceof SmartFactoryBean &&
((SmartFactoryBean<?>) factory).isEagerInit());
}
if (isEagerInit) {
getBean(beanName);
}
}
else {
// 最後執行這個方法進行實例化
getBean(beanName);
}
}
}
// SmartInitializingSingleton的處理
}
AbstractBeanFactory
getBean
public Object getBean(String name) throws BeansException {
return doGetBean(name, null, null, false);
}
doGetBean
這裏我們就是要創建單例的實例(有就從緩存中取)。創建的方式是通過ObjectFactory內部類實現中的createBean方法來完成。我們先看下getSingleton的邏輯。
// 首次進來爲空 最後會走下邊的邏輯
Object sharedInstance = getSingleton(beanName);
// 通過this.beanDefinitionMap得到的 具體可自行查看源碼。這裏不太花篇幅講述。
final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
//...
if (mbd.isSingleton()) {
sharedInstance = getSingleton(beanName, new ObjectFactory<Object>() {
@Override
public Object getObject() throws BeansException {
try {
//最終創建Bean的邏輯
return createBean(beanName, mbd, args);
}
catch (BeansException ex) {
destroySingleton(beanName);
throw ex;
}
}
});
bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
}
//....
// 注意這裏,會把單例cache起來,在後邊可以直接使用
if (newSingleton) {
addSingleton(beanName, singletonObject);
}
DefaultSingletonBeanRegistry
getSingleton
這裏我們要分析的核心邏輯(instance singleton)是調用的了ObjectFactory.getObject,即我們上邊的內部類,而內部類的實現則是通過createBean完成。我們再來看下createBean的邏輯。
try {
//回到了AbstractBeanFactory#doGetBean的ObjectFactory的getObject方法,執行其中的createBean方法
singletonObject = singletonFactory.getObject();
newSingleton = true;
}
AbstractAutowireCapableBeanFactory
createBean
AbstractBeanFactory的子類實現方法
AbstractAutowireCapableBeanFactory#createBean(java.lang.Class<T>)
public <T> T createBean(Class<T> beanClass) throws BeansException {
// Use prototype bean definition, to avoid registering bean as dependent bean.
RootBeanDefinition bd = new RootBeanDefinition(beanClass);
bd.setScope(SCOPE_PROTOTYPE);
bd.allowCaching = ClassUtils.isCacheSafe(beanClass, getBeanClassLoader());
return (T) createBean(beanClass.getName(), bd, null);
}
// 接上
protected Object createBean(String beanName, RootBeanDefinition mbd, Object[] args) throws BeanCreationException {
RootBeanDefinition mbdToUse = mbd;
Class<?> resolvedClass = resolveBeanClass(mbd, beanName);
if (resolvedClass != null && !mbd.hasBeanClass() && mbd.getBeanClassName() != null) {
mbdToUse = new RootBeanDefinition(mbd);
mbdToUse.setBeanClass(resolvedClass);
}
try {
mbdToUse.prepareMethodOverrides();
}
catch (BeanDefinitionValidationException ex) {
}
try {
// Give BeanPostProcessors a chance to return a proxy instead of the target bean instance.
Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
if (bean != null) {
return bean;
}
}
catch (Throwable ex) {
}
// 普通Bean的實例創建
Object beanInstance = doCreateBean(beanName, mbdToUse, args);
if (logger.isDebugEnabled()) {
logger.debug("Finished creating instance of bean '" + beanName + "'");
}
return beanInstance;
}
doCreateBean
核心關注instanceWrapper和exposedObject對象的處理過程
BeanWrapper instanceWrapper = null;
if (mbd.isSingleton()) {
instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
}
if (instanceWrapper == null) {
//創建bean實例的Wrapper對象
instanceWrapper = createBeanInstance(beanName, mbd, args);
}
// bean實例在wrapper中已經創建了(不完整)
final Object bean = (instanceWrapper != null ? instanceWrapper.getWrappedInstance() : null);
//省略一些代碼。。。
// Initialize the bean instance.
Object exposedObject = bean;
try {
// 注入property到Bean中
populateBean(beanName, mbd, instanceWrapper);
if (exposedObject != null) {
exposedObject = initializeBean(beanName, exposedObject, mbd);
}
}
//省略一些代碼。。。
return exposedObject;
createBeanInstance
instanceWrapper = createBeanInstance(beanName, mbd, args); 該方法是給指定的name的Class創建Bean對象,支持無參、factoryMethod、AutoWireConstructor三種策略。默認執行無參的"instantiateBean"。而我們的BaigtAutoConfig中的@Bean則設置的有FactoryMethodName(我們定義的@Bean的方法名=“env”)
protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, Object[] args) {
// Make sure bean class is actually resolved at this point.
Class<?> beanClass = resolveBeanClass(mbd, beanName);
if (beanClass != null && !Modifier.isPublic(beanClass.getModifiers()) && !mbd.isNonPublicAccessAllowed()) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"Bean class isn't public, and non-public access not allowed: " + beanClass.getName());
}
//配置類中的@Bean方法是通過下邊這種方式實例化的。
if (mbd.getFactoryMethodName() != null) {
return instantiateUsingFactoryMethod(beanName, mbd, args);
}
// Shortcut when re-creating the same bean...
boolean resolved = false;
boolean autowireNecessary = false;
if (args == null) {
synchronized (mbd.constructorArgumentLock) {
if (mbd.resolvedConstructorOrFactoryMethod != null) {
resolved = true;
autowireNecessary = mbd.constructorArgumentsResolved;
}
}
}
// 一般我們不是FactoryMethod和有參構造(也可以有哈)
if (resolved) {
if (autowireNecessary) {
return autowireConstructor(beanName, mbd, null, null);
}
else {
return instantiateBean(beanName, mbd);
}
}
// Need to determine the constructor...
Constructor<?>[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName);
if (ctors != null ||
mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_CONSTRUCTOR ||
mbd.hasConstructorArgumentValues() || !ObjectUtils.isEmpty(args)) {
return autowireConstructor(beanName, mbd, ctors, args);
}
//沒有特殊處理就使用無參構造實例
// No special handling: simply use no-arg constructor.
return instantiateBean(beanName, mbd);
}
instantiateUsingFactoryMethod
protected BeanWrapper instantiateUsingFactoryMethod(
String beanName, RootBeanDefinition mbd, Object[] explicitArgs) {
return new ConstructorResolver(this).instantiateUsingFactoryMethod(beanName, mbd, explicitArgs);
}
ConstructorResolver
instantiateUsingFactoryMethod
BeanWrapperImpl bw = new BeanWrapperImpl();
this.beanFactory.initBeanWrapper(bw);
//。。。。
Object beanInstance;
beanInstance = this.beanFactory.getInstantiationStrategy().instantiate(
mbd, beanName, this.beanFactory, factoryBean, factoryMethodToUse, argsToUse);
bw.setBeanInstance(beanInstance);
return bw;
SimpleInstantiationStrategy
instantiate
最後調用@Bean對應的方法的invoke方法。到此配置類中的@Bean已經實例化完成。
public Object instantiate(RootBeanDefinition bd, String beanName, BeanFactory owner,
Object factoryBean, final Method factoryMethod, Object... args) {
try {
if (System.getSecurityManager() != null) {
AccessController.doPrivileged(new PrivilegedAction<Object>() {
@Override
public Object run() {
ReflectionUtils.makeAccessible(factoryMethod);
return null;
}
});
}
else {
ReflectionUtils.makeAccessible(factoryMethod);
}
Method priorInvokedFactoryMethod = currentlyInvokedFactoryMethod.get();
try {
currentlyInvokedFactoryMethod.set(factoryMethod);
//執行方法
return factoryMethod.invoke(factoryBean, args);
}
finally {
if (priorInvokedFactoryMethod != null) {
currentlyInvokedFactoryMethod.set(priorInvokedFactoryMethod);
}
else {
currentlyInvokedFactoryMethod.remove();
}
}
}
catch (IllegalArgumentException ex) {
throws ex;
}
}
AbstractAutowireCapableBeanFactory
返回到doCreateBean方法
doCreateBean
我們繼續看exposedObject處理的內容。裝載Bean的Property屬性,initBean對象。我們着重看下initializeBean方法。
final Object bean = (instanceWrapper != null ? instanceWrapper.getWrappedInstance() : null);
Object exposedObject = bean;
try {
//裝載比如Property屬性 可以是其他Bean對象,也可能是String等基本屬性。 具體見populateBean中的applyPropertyValues方法
populateBean(beanName, mbd, instanceWrapper);
if (exposedObject != null) {
//初始化Bean對象
exposedObject = initializeBean(beanName, exposedObject, mbd);
}
}
initializeBean
- org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#initializeBean(java.lang.String, java.lang.Object, org.springframework.beans.factory.support.RootBeanDefinition)
初始化給定的Bean,(RootBeanDefinition爲空時,執行BeanPost)執行wired的相關方法((BeanNameAware、BeanClassLoaderAware、BeanFactoryAware))、執行initMethod。比如InitializingBean#afterPropertiesSet();或者是自定義的init方法。
protected Object initializeBean(final String beanName, final Object bean, RootBeanDefinition mbd) {
if (System.getSecurityManager() != null) {
AccessController.doPrivileged(new PrivilegedAction<Object>() {
@Override
public Object run() {
invokeAwareMethods(beanName, bean);
return null;
}
}, getAccessControlContext());
}
else {
//執行wire的method(BeanNameAware、BeanClassLoaderAware、BeanFactoryAware)
invokeAwareMethods(beanName, bean);
}
Object wrappedBean = bean;
if (mbd == null || !mbd.isSynthetic()) {
wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
}
try {
//執行init方法
invokeInitMethods(beanName, wrappedBean, mbd);
}
catch (Throwable ex) {
throw new BeanCreationException(
(mbd != null ? mbd.getResourceDescription() : null),
beanName, "Invocation of init method failed", ex);
}
if (mbd == null || !mbd.isSynthetic()) {
wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
}
return wrappedBean;
}
invokeInitMethods
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#invokeInitMethods。執行afterPropertiesSet方法。如果是自定義的init方法,就調用invokeCustomInitMethod。
protected void invokeInitMethods(String beanName, final Object bean, RootBeanDefinition mbd)
throws Throwable {
boolean isInitializingBean = (bean instanceof InitializingBean);
if (isInitializingBean && (mbd == null || !mbd.isExternallyManagedInitMethod("afterPropertiesSet"))) {
if (logger.isDebugEnabled()) {
logger.debug("Invoking afterPropertiesSet() on bean with name '" + beanName + "'");
}
if (System.getSecurityManager() != null) {
try {
AccessController.doPrivileged(new PrivilegedExceptionAction<Object>() {
@Override
public Object run() throws Exception {
((InitializingBean) bean).afterPropertiesSet();
return null;
}
}, getAccessControlContext());
}
catch (PrivilegedActionException pae) {
throw pae.getException();
}
}
else {
((InitializingBean) bean).afterPropertiesSet();
}
}
if (mbd != null) {
String initMethodName = mbd.getInitMethodName();
if (initMethodName != null && !(isInitializingBean && "afterPropertiesSet".equals(initMethodName)) &&
!mbd.isExternallyManagedInitMethod(initMethodName)) {
invokeCustomInitMethod(beanName, bean, mbd);
}
}
}
AbstractApplicationContext
返回到refresh方法
refresh
至此配置類相關的Bean實例化完成。
// Instantiate all remaining (non-lazy-init) singletons.
finishBeanFactoryInitialization(beanFactory);
其他Bean
我們這裏只關注的是配置類的加載,普通Bean的加載可以看我的另外一篇文章 徹底弄懂Spring中Bean的解析、創建和使用
結語
分析使用的Spring版本爲4.3.18。代碼上如有出入,請自行區分。最後如有不對,歡迎指正。 作者:ricky QQ交流羣:244930845。