Springboot原始碼分析
1、SpringApplication初始化
從run()方法進入,可以看到Springboot首先建立了SpringApplication,然後呼叫SpringApplication的run()方法。
public static ConfigurableApplicationContext run(Class<?>[] primarySources, String[] args) {
return (new SpringApplication(primarySources)).run(args);
}
建立SpringApplication,首先要執行它的構造方法。
//SpringApplication.class
public SpringApplication(ResourceLoader resourceLoader, Class<?>... primarySources) {
this.sources = new LinkedHashSet();
this.bannerMode = Mode.CONSOLE;
this.logStartupInfo = true;
this.addCommandLineProperties = true;
this.addConversionService = true;
this.headless = true;
this.registerShutdownHook = true;
this.additionalProfiles = new HashSet();
this.isCustomEnvironment = false;
this.lazyInitialization = false;
this.resourceLoader = resourceLoader;
Assert.notNull(primarySources, "PrimarySources must not be null");
this.primarySources = new LinkedHashSet(Arrays.asList(primarySources));
//webApplication型別一般是servlet
this.webApplicationType = WebApplicationType.deduceFromClasspath();
//設定初始化器,載入spring.factories檔案中的ApplicationContextInitializer
this.setInitializers(this.getSpringFactoriesInstances(ApplicationContextInitializer.class));
//設定監聽器,載入spring.factories檔案中的ApplicationListener
this.setListeners(this.getSpringFactoriesInstances(ApplicationListener.class));
//啟動類的型別,我們的是com.example.demo.DemoApplication
this.mainApplicationClass = this.deduceMainApplicationClass();
}
1.1 & 1.2 設定初始化器和監聽器
上面的setInitializers和setListeners去初始化spring.factories檔案中對應的類,然後放入ArrayList中。比如這些:
org.springframework.context.ApplicationContextInitializer=\
org.springframework.boot.autoconfigure.SharedMetadataReaderFactoryContextInitializer,\
org.springframework.boot.autoconfigure.logging.ConditionEvaluationReportLoggingListener
# Application Listeners
org.springframework.context.ApplicationListener=\
org.springframework.boot.autoconfigure.BackgroundPreinitializer
1.2.1 getSpringFactoriesInstances
在getSpringFactoriesInstances()方法中,springboot首先去所有spring.factories找到對應的類,然後透過反射建立類的例項。
//SpringApplication.class
private <T> Collection<T> getSpringFactoriesInstances(Class<T> type) {
return this.getSpringFactoriesInstances(type, new Class[0]);
}
private <T> Collection<T> getSpringFactoriesInstances(Class<T> type, Class<?>[] parameterTypes, Object... args) {
ClassLoader classLoader = this.getClassLoader();
//獲取spring.factories中對應類的類名,以ApplicationListenser為例,springboot會去檔案中找到所有ApplicationListener對應的類,放入Set中。
Set<String> names = new LinkedHashSet(SpringFactoriesLoader.loadFactoryNames(type, classLoader));
//反射建立類的例項物件,放到List中返回
List<T> instances = this.createSpringFactoriesInstances(type, parameterTypes, classLoader, args, names);
AnnotationAwareOrderComparator.sort(instances);
return instances;
}
private <T> List<T> createSpringFactoriesInstances(Class<T> type, Class<?>[] parameterTypes, ClassLoader classLoader, Object[] args, Set<String> names) {
List<T> instances = new ArrayList(names.size());
Iterator var7 = names.iterator();
while(var7.hasNext()) {
String name = (String)var7.next();
try {
//獲取類資訊
Class<?> instanceClass = ClassUtils.forName(name, classLoader);
Assert.isAssignable(type, instanceClass);
//獲取構造器
Constructor<?> constructor = instanceClass.getDeclaredConstructor(parameterTypes);
//建立例項
T instance = BeanUtils.instantiateClass(constructor, args);
instances.add(instance);
} catch (Throwable var12) {
throw new IllegalArgumentException("Cannot instantiate " + type + " : " + name, var12);
}
}
return instances;
}
1.2.2 loadFactoryNames()
進入SpringFactoriesLoader.loadFactoryNames(type, classLoader)看一下,這裡還是以ApplicationListener為例,這時的type是org.springframework.context.ApplicationListener,classLoader是AppClassLoader。
//SpringFactoriesLoader.class
public static List<String> loadFactoryNames(Class<?> factoryType, @Nullable ClassLoader classLoader) {
String factoryTypeName = factoryType.getName();
return (List)loadSpringFactories(classLoader).getOrDefault(factoryTypeName, Collections.emptyList());
}
private static Map<String, List<String>> loadSpringFactories(@Nullable ClassLoader classLoader) {
MultiValueMap<String, String> result = (MultiValueMap)cache.get(classLoader);
if (result != null) {
return result;
} else {
try {
Enumeration<URL> urls = classLoader != null ? classLoader.getResources("META-INF/spring.factories") : ClassLoader.getSystemResources("META-INF/spring.factories");
MultiValueMap<String, String> result = new LinkedMultiValueMap();
while(urls.hasMoreElements()) {
URL url = (URL)urls.nextElement();
UrlResource resource = new UrlResource(url);
Properties properties = PropertiesLoaderUtils.loadProperties(resource);
Iterator var6 = properties.entrySet().iterator();
while(var6.hasNext()) {
Map.Entry<?, ?> entry = (Map.Entry)var6.next();
String factoryTypeName = ((String)entry.getKey()).trim();
String[] var9 = StringUtils.commaDelimitedListToStringArray((String)entry.getValue());
int var10 = var9.length;
for(int var11 = 0; var11 < var10; ++var11) {
String factoryImplementationName = var9[var11];
result.add(factoryTypeName, factoryImplementationName.trim());
}
}
}
cache.put(classLoader, result);
return result;
} catch (IOException var13) {
throw new IllegalArgumentException("Unable to load factories from location [META-INF/spring.factories]", var13);
}
}
}
loadSpringFactories()方法會遍歷所有的spring.factories檔案,把所有的類的名字儲存到map中,然後呼叫getOrDefault()方法就可以獲取到所有的ApplicationListner對應的類名了。
SpringApplication初始化完了,接下來該執行run()方法了
2、SpringApplication執行run()方法
//SpringApplication.class
public ConfigurableApplicationContext run(String... args) {
StopWatch stopWatch = new StopWatch();
stopWatch.start();
//這裡是Spring的上下文
ConfigurableApplicationContext context = null;
Collection<SpringBootExceptionReporter> exceptionReporters = new ArrayList();
this.configureHeadlessProperty();
//獲取執行監聽器,獲取到的是EventPublishingRunListener,這是springboot的啟動監聽器
SpringApplicationRunListeners listeners = this.getRunListeners(args);
//啟動監聽器
listeners.starting();
Collection exceptionReporters;
try {
ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);
//2.1 準備環境
ConfigurableEnvironment environment = this.prepareEnvironment(listeners, applicationArguments);
this.configureIgnoreBeanInfo(environment);
//Banner列印類
Banner printedBanner = this.printBanner(environment);
//2.2 建立應用上下文
context = this.createApplicationContext();
exceptionReporters = this.getSpringFactoriesInstances(SpringBootExceptionReporter.class, new Class[]{ConfigurableApplicationContext.class}, context);
//2.3 準備上下文
this.prepareContext(context, environment, listeners, applicationArguments, printedBanner);
//2.4 重新整理上下文
this.refreshContext(context);
//重新整理上下文後置處理
this.afterRefresh(context, applicationArguments);
stopWatch.stop();
if (this.logStartupInfo) {
(new StartupInfoLogger(this.mainApplicationClass)).logStarted(this.getApplicationLog(), stopWatch);
}
//釋出上下文啟動完成事件
listeners.started(context);
this.callRunners(context, applicationArguments);
} catch (Throwable var10) {
this.handleRunFailure(context, var10, exceptionReporters, listeners);
throw new IllegalStateException(var10);
}
try {
listeners.running(context);
return context;
} catch (Throwable var9) {
this.handleRunFailure(context, var9, exceptionReporters, (SpringApplicationRunListeners)null);
throw new IllegalStateException(var9);
}
}
2.1 prepareEnvironment()準備環境
//SpringApplication.class
private ConfigurableEnvironment prepareEnvironment(SpringApplicationRunListeners listeners, ApplicationArguments applicationArguments) {
//根據前面推斷的webApplicationType建立對應的環境,servlet對應的是StandardServletEnvironment()
ConfigurableEnvironment environment = this.getOrCreateEnvironment();
//根據引數配置環境,包括命令列引數,啟動類傳入的引數
this.configureEnvironment((ConfigurableEnvironment)environment, applicationArguments.getSourceArgs());
ConfigurationPropertySources.attach((Environment)environment);
//執行完這個,配置檔案中的配置進行就被載入到環境中了
listeners.environmentPrepared((ConfigurableEnvironment)environment);
//環境和SpringApplication繫結起來
this.bindToSpringApplication((ConfigurableEnvironment)environment);
if (!this.isCustomEnvironment) {
environment = (new EnvironmentConverter(this.getClassLoader())).convertEnvironmentIfNecessary((ConfigurableEnvironment)environment, this.deduceEnvironmentClass());
}
ConfigurationPropertySources.attach((Environment)environment);
return (ConfigurableEnvironment)environment;
}
2.1.1 根據引數配置環境configureEnvironment()
//SpringApplication.class
protected void configureEnvironment(ConfigurableEnvironment environment, String[] args) {
if (this.addConversionService) {
ConversionService conversionService = ApplicationConversionService.getSharedInstance();
environment.setConversionService((ConfigurableConversionService)conversionService);
}
//配置命令列中的引數
this.configurePropertySources(environment, args);
//啟用相應的配置檔案,例如application.propertires或者application-dev.properties等
this.configureProfiles(environment, args);
}
如果我啟動的dev環境,執行完上面的程式碼後環境中是這樣的
2.1.2 listeners.environmentPrepared()
執行完這句程式碼後,配置檔案中的資訊就被載入到環境中了,如下圖。具體怎麼做到的還沒看懂
2.2 建立應用上下文createApplicationContext()
//SpringApplication.class
protected ConfigurableApplicationContext createApplicationContext() {
Class<?> contextClass = this.applicationContextClass;
if (contextClass == null) {
try {
switch (this.webApplicationType) {
case SERVLET:
contextClass = Class.forName("org.springframework.boot.web.servlet.context.AnnotationConfigServletWebServerApplicationContext");
break;
case REACTIVE:
contextClass = Class.forName("org.springframework.boot.web.reactive.context.AnnotationConfigReactiveWebServerApplicationContext");
break;
default:
contextClass = Class.forName("org.springframework.context.annotation.AnnotationConfigApplicationContext");
}
} catch (ClassNotFoundException var3) {
throw new IllegalStateException("Unable create a default ApplicationContext, please specify an ApplicationContextClass", var3);
}
}
return (ConfigurableApplicationContext)BeanUtils.instantiateClass(contextClass);
}
這個函式也是根據前面的webApplicationType建立應用上下文,servlet對應的是AnnotationConfigServletWebServerApplicationContext,當初始化完這個類時,其實也會建立一個IOC容器beanFactory,如下圖所示。這是因為AnnotationConfigServletWebServerApplicationContext會繼承GenericApplicationContext,當執行完這個類的建構函式,會建立一個DefaultListableBeanFactory()的beanFactory,這個就是IOC容器。
2.3 準備上下文prepareContext()
//SpringApplication.class
private void prepareContext(ConfigurableApplicationContext context, ConfigurableEnvironment environment, SpringApplicationRunListeners listeners, ApplicationArguments applicationArguments, Banner printedBanner) {
//設定上下文環境
context.setEnvironment(environment);
this.postProcessApplicationContext(context);
//初始化所有的ApplicationContextInitializer
this.applyInitializers(context);
//釋出上下文準備完成事件
listeners.contextPrepared(context);
if (this.logStartupInfo) {
this.logStartupInfo(context.getParent() == null);
this.logStartupProfileInfo(context);
}
//獲取IOC容器beanFactory
ConfigurableListableBeanFactory beanFactory = context.getBeanFactory();
//將springApplicationArguments和springBootBanner註冊成單例
beanFactory.registerSingleton("springApplicationArguments", applicationArguments);
if (printedBanner != null) {
beanFactory.registerSingleton("springBootBanner", printedBanner);
}
if (beanFactory instanceof DefaultListableBeanFactory) {
((DefaultListableBeanFactory)beanFactory).setAllowBeanDefinitionOverriding(this.allowBeanDefinitionOverriding);
}
if (this.lazyInitialization) {
context.addBeanFactoryPostProcessor(new LazyInitializationBeanFactoryPostProcessor());
}
//2.3.1 獲取資源,其中primarySources就是我們定義的啟動類DemoApplication
Set<Object> sources = this.getAllSources();
Assert.notEmpty(sources, "Sources must not be empty");
//2.3.2 載入啟動類,注入IOC容器
this.load(context, sources.toArray(new Object[0]));
//釋出完成載入事件
listeners.contextLoaded(context);
}
2.3.1 & 2.3.2 獲取啟動類,注入IOC容器
當執行完getAllSources(),可以獲取到啟動類DemoApplication
重點看load()方法,進入load()。
//SpringApplication.class
protected void load(ApplicationContext context, Object[] sources) {
if (logger.isDebugEnabled()) {
logger.debug("Loading source " + StringUtils.arrayToCommaDelimitedString(sources));
}
//建立BeanDefinitionLoader
BeanDefinitionLoader loader = this.createBeanDefinitionLoader(this.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();
}
其中getBeanDefinitionRegistry(context)方法會將之前的上下文context強轉成BeanDefinitionRegistry,他們之間的繼承關係很複雜,可以轉換成不同的類完成不同的方法。createBeanDefinitionLoader()方法建立了一個BeanDefinitionLoader(),點進去看看。
//BeanDefinitionLoader.class
BeanDefinitionLoader(BeanDefinitionRegistry registry, Object... sources) {
Assert.notNull(registry, "Registry must not be null");
Assert.notEmpty(sources, "Sources must not be empty");
this.sources = sources;
//註解形式的Bean閱讀器
this.annotatedReader = new AnnotatedBeanDefinitionReader(registry);
//xml形式的Bean閱讀器
this.xmlReader = new XmlBeanDefinitionReader(registry);
if (this.isGroovyPresent()) {
this.groovyReader = new GroovyBeanDefinitionReader(registry);
}
//類路徑掃描器
this.scanner = new ClassPathBeanDefinitionScanner(registry);
this.scanner.addExcludeFilter(new ClassExcludeFilter(sources));
}
一直跟進load()。
//BeanDefinitionLoader.class
private int load(Class<?> source) {
if (this.isGroovyPresent() && GroovyBeanDefinitionSource.class.isAssignableFrom(source)) {
GroovyBeanDefinitionSource loader = (GroovyBeanDefinitionSource)BeanUtils.instantiateClass(source, GroovyBeanDefinitionSource.class);
this.load(loader);
}
//啟動類會走進這裡
if (this.isEligible(source)) {
//將啟動類註冊進beanDefinitionMap
this.annotatedReader.register(new Class[]{source});
return 1;
} else {
return 0;
}
}
進入register()方法。
//AnnotatedBeanDefinitionReader.class
public void register(Class<?>... componentClasses) {
Class[] var2 = componentClasses;
int var3 = componentClasses.length;
for(int var4 = 0; var4 < var3; ++var4) {
Class<?> componentClass = var2[var4];
this.registerBean(componentClass);
}
}
public void registerBean(Class<?> beanClass) {
this.doRegisterBean(beanClass, (String)null, (Class[])null, (Supplier)null, (BeanDefinitionCustomizer[])null);
}
private <T> void doRegisterBean(Class<T> beanClass, @Nullable String name, @Nullable Class<? extends Annotation>[] qualifiers, @Nullable Supplier<T> supplier, @Nullable BeanDefinitionCustomizer[] customizers) {
//將beanClass(這裡是啟動類DemoApplication)封裝成AnnotatedGenericBeanDefinition
AnnotatedGenericBeanDefinition abd = new AnnotatedGenericBeanDefinition(beanClass);
if (!this.conditionEvaluator.shouldSkip(abd.getMetadata())) {
abd.setInstanceSupplier(supplier);
ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(abd);
abd.setScope(scopeMetadata.getScopeName());
String beanName = name != null ? name : this.beanNameGenerator.generateBeanName(abd, this.registry);
AnnotationConfigUtils.processCommonDefinitionAnnotations(abd);
int var10;
int var11;
if (qualifiers != null) {
Class[] var9 = qualifiers;
var10 = qualifiers.length;
for(var11 = 0; var11 < var10; ++var11) {
Class<? extends Annotation> qualifier = var9[var11];
if (Primary.class == qualifier) {
abd.setPrimary(true);
} else if (Lazy.class == qualifier) {
abd.setLazyInit(true);
} else {
abd.addQualifier(new AutowireCandidateQualifier(qualifier));
}
}
}
if (customizers != null) {
BeanDefinitionCustomizer[] var13 = customizers;
var10 = customizers.length;
for(var11 = 0; var11 < var10; ++var11) {
BeanDefinitionCustomizer customizer = var13[var11];
customizer.customize(abd);
}
}
//建立BeanDefinitionHolder,就是把BeanDefinition包裝了一下,新增了一些屬性和方法。
BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(abd, beanName);
definitionHolder = AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);
//將啟動類BeanDefinition註冊到IOC容器的map中。
BeanDefinitionReaderUtils.registerBeanDefinition(definitionHolder, this.registry);
}
}
registerBeanDefinition()方法實際會呼叫BeanDefinitionRegistry的registerBeanDefinition()方法,它在DefaultListableBeanFactory實現類裡實現的,之前說過這個就是IOC容器。
//DefaultListableBeanFactory.class
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 var8) {
throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName, "Validation of bean definition failed", var8);
}
}
//IOC容器beanFactory的beanDefinitionMap
BeanDefinition existingDefinition = (BeanDefinition)this.beanDefinitionMap.get(beanName);
if (existingDefinition != null) {
if (!this.isAllowBeanDefinitionOverriding()) {
throw new BeanDefinitionOverrideException(beanName, beanDefinition, existingDefinition);
}
if (existingDefinition.getRole() < beanDefinition.getRole()) {
if (this.logger.isInfoEnabled()) {
this.logger.info("Overriding user-defined bean definition for bean '" + beanName + "' with a framework-generated bean definition: replacing [" + existingDefinition + "] with [" + beanDefinition + "]");
}
} else if (!beanDefinition.equals(existingDefinition)) {
if (this.logger.isDebugEnabled()) {
this.logger.debug("Overriding bean definition for bean '" + beanName + "' with a different definition: replacing [" + existingDefinition + "] with [" + beanDefinition + "]");
}
} else if (this.logger.isTraceEnabled()) {
this.logger.trace("Overriding bean definition for bean '" + beanName + "' with an equivalent definition: replacing [" + existingDefinition + "] with [" + beanDefinition + "]");
}
this.beanDefinitionMap.put(beanName, beanDefinition);
} else {
if (this.hasBeanCreationStarted()) {
synchronized(this.beanDefinitionMap) {
this.beanDefinitionMap.put(beanName, beanDefinition);
List<String> updatedDefinitions = new ArrayList(this.beanDefinitionNames.size() + 1);
updatedDefinitions.addAll(this.beanDefinitionNames);
updatedDefinitions.add(beanName);
this.beanDefinitionNames = updatedDefinitions;
this.removeManualSingletonName(beanName);
}
} else {
//啟動階段會走到這裡,以beanName為key,beanDefinition為value存入beanDefinitionMap中
this.beanDefinitionMap.put(beanName, beanDefinition);
this.beanDefinitionNames.add(beanName);
this.removeManualSingletonName(beanName);
}
this.frozenBeanDefinitionNames = null;
}
if (existingDefinition == null && !this.containsSingleton(beanName)) {
if (this.isConfigurationFrozen()) {
this.clearByTypeCache();
}
} else {
this.resetBeanDefinition(beanName);
}
}
註冊完之後可以看到demoApplication已經被新增到beanFactory的beanDefinitionMap中了。
2.4、重新整理上下文refreshContext()
Springboot最終在這裡呼叫Spring的refresh()方法,從refreshContext()一直跟進去會到AbstractApplicationContext的refresh()方法。
//AbstractApplicationContext.class
public void refresh() throws BeansException, IllegalStateException {
synchronized(this.startupShutdownMonitor) {
this.prepareRefresh();
//2.4.1 獲取容器
ConfigurableListableBeanFactory beanFactory = this.obtainFreshBeanFactory();
//準備beanFactory,這個方法就是為beanFactory新增一些元件和配置,比如後置處理器、類載入器、依賴處理器等等
this.prepareBeanFactory(beanFactory);
try {
//在上下文新增一些BeanFactory後置處理器,處理器在beanDefinition載入完後,bean例項化之前執行
this.postProcessBeanFactory(beanFactory);
//2.4.2 呼叫BeanFactory後置處理器,這一步會進行IOC容器的初始化
this.invokeBeanFactoryPostProcessors(beanFactory);
//註冊bean的後置處理器,上面是BeanFactory後置處理器
this.registerBeanPostProcessors(beanFactory);
this.initMessageSource();
this.initApplicationEventMulticaster();
this.onRefresh();
this.registerListeners();
//上面這些不看了,直接從這開始
//2.4.3 完成所有單例bean的初始化
this.finishBeanFactoryInitialization(beanFactory);
//廣播重新整理完成事件
this.finishRefresh();
} catch (BeansException var9) {
if (this.logger.isWarnEnabled()) {
this.logger.warn("Exception encountered during context initialization - cancelling refresh attempt: " + var9);
}
this.destroyBeans();
this.cancelRefresh(var9);
throw var9;
} finally {
this.resetCommonCaches();
}
}
}
2.4.1 obtainFreshBeanFactory()獲取容器
之前說過Springboot在建立應用上下文時,觸發了GenericApplicationContext的建構函式,建立了beanFactory,這個方法就是獲取之前建立的beanFactory。
//AbstractApplicationContext.class
protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
this.refreshBeanFactory();
return this.getBeanFactory();
}
這兩個方法都是模板方法,由子類GenericApplicationContext實現
//GenericApplicationContext.class
protected final void refreshBeanFactory() throws IllegalStateException {
if (!this.refreshed.compareAndSet(false, true)) {
throw new IllegalStateException("GenericApplicationContext does not support multiple refresh attempts: just call 'refresh' once");
} else {
this.beanFactory.setSerializationId(this.getId());
}
}
public final ConfigurableListableBeanFactory getBeanFactory() {
return this.beanFactory;
}
2.4.2 invokeBeanFactoryPostProcessors()
public static void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory, List<BeanFactoryPostProcessor> beanFactoryPostProcessors) {
...
//預設的beanFactoryPostProcessors有三個,SharedMetadataReaferFactoryContextInitializer、ConfigurationWArningsApplicationContextInitializer、ConfigFileApplicationListener
Iterator var6 = beanFactoryPostProcessors.iterator();
//迴圈將它們註冊到beanDefinitionMap中
while(var6.hasNext()) {
BeanFactoryPostProcessor postProcessor = (BeanFactoryPostProcessor)var6.next();
if (postProcessor instanceof BeanDefinitionRegistryPostProcessor) {
BeanDefinitionRegistryPostProcessor registryProcessor = (BeanDefinitionRegistryPostProcessor)postProcessor;
registryProcessor.postProcessBeanDefinitionRegistry(registry);
registryProcessors.add(registryProcessor);
} else {
regularPostProcessors.add(postProcessor);
}
}
currentRegistryProcessors = new ArrayList();
//這裡postProcessorNames是org.springframework.context.annotation.internalConfigurationAnnotationProcessor,internalConfigurationAnnotationProcessor是專門用來處理Configuration註解的類。
postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
String[] var16 = postProcessorNames;
var9 = postProcessorNames.length;
int var10;
String ppName;
for(var10 = 0; var10 < var9; ++var10) {
ppName = var16[var10];
if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
//透過getBean,從例項化了ConfigurationClassPostProcessor到容器中
currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
processedBeans.add(ppName);
}
}
sortPostProcessors(currentRegistryProcessors, beanFactory);
registryProcessors.addAll(currentRegistryProcessors);
//對於使用基於@Configuration註解和@bean注入的物件, 此時的processor型別為ConfigurationClassPostprocessor, 且在此處執行
//如果是@Autowired和@Value註解注入的物件,processor型別應該是AutowiredAnnotationBeanPostProcessor,這些東西是在AnnotationConfigUtils類下定義的
//2.4.2.1 進去重點看看此時的processor型別為ConfigurationClassPostprocessor的postProcessBeanDefinitionRegistry()做了什麼
invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
...
}
2.4.2.1 invokeBeanDefinitionRegistryPostProcessors()
一直跟進這個方法,知道ConfigurationClassPostProcessor.class中的parser.parse(candidates)方法,看下面這張圖,這時候的只有這個啟動類,接下來繼續跟進這個方法。
//ConfigurationClassParser.class
public void parse(Set<BeanDefinitionHolder> configCandidates) {
Iterator var2 = configCandidates.iterator();
while(var2.hasNext()) {
BeanDefinitionHolder holder = (BeanDefinitionHolder)var2.next();
BeanDefinition bd = holder.getBeanDefinition();
try {
//會走這裡,之前看到過啟動類是被封裝成AnnotatedBeanDefinition的
if (bd instanceof AnnotatedBeanDefinition) {
this.parse(((AnnotatedBeanDefinition)bd).getMetadata(), holder.getBeanName());
} else if (bd instanceof AbstractBeanDefinition && ((AbstractBeanDefinition)bd).hasBeanClass()) {
this.parse(((AbstractBeanDefinition)bd).getBeanClass(), holder.getBeanName());
} else {
this.parse(bd.getBeanClassName(), holder.getBeanName());
}
} catch (BeanDefinitionStoreException var6) {
throw var6;
} catch (Throwable var7) {
throw new BeanDefinitionStoreException("Failed to parse configuration class [" + bd.getBeanClassName() + "]", var7);
}
}
//springboot自動裝配的入口
this.deferredImportSelectorHandler.process();
}
繼續跟進parse()方法直到ConfigurationClassParser.class的doProcessConfigurationClass()方法。
//ConfigurationClassParser.class
protected void processConfigurationClass(ConfigurationClass configClass, Predicate<String> filter) throws IOException {
...
do {
//主要就是這個方法進行處理
sourceClass = this.doProcessConfigurationClass(configClass, sourceClass, filter);
} while(sourceClass != null);
this.configurationClasses.put(configClass, configClass);
}
}
protected final SourceClass doProcessConfigurationClass(ConfigurationClass configClass, SourceClass sourceClass, Predicate<String> filter) throws IOException {
//遞迴處理內部類,啟動類是沒有內部類的,如果是啟動類這裡進去什麼都不做
if (configClass.getMetadata().isAnnotated(Component.class.getName())) {
this.processMemberClasses(configClass, sourceClass, filter);
}
//處理@PropertySource註解配置的屬性,對於啟動類來說,這裡也沒有
Iterator var4 = AnnotationConfigUtils.attributesForRepeatable(sourceClass.getMetadata(), PropertySources.class, PropertySource.class).iterator();
AnnotationAttributes importResource;
while(var4.hasNext()) {
importResource = (AnnotationAttributes)var4.next();
if (this.environment instanceof ConfigurableEnvironment) {
this.processPropertySource(importResource);
} else {
this.logger.info("Ignoring @PropertySource annotation on [" + sourceClass.getMetadata().getClassName() + "]. Reason: Environment must implement ConfigurableEnvironment");
}
}
//處理@ComponentScan註解,掃描專案中的bean,啟動類上包含這個註解
Set<AnnotationAttributes> componentScans = AnnotationConfigUtils.attributesForRepeatable(sourceClass.getMetadata(), ComponentScans.class, ComponentScan.class);
if (!componentScans.isEmpty() && !this.conditionEvaluator.shouldSkip(sourceClass.getMetadata(), ConfigurationPhase.REGISTER_BEAN)) {
Iterator var14 = componentScans.iterator();
while(var14.hasNext()) {
AnnotationAttributes componentScan = (AnnotationAttributes)var14.next();
//2.4.2.2 掃描專案中的bean
Set<BeanDefinitionHolder> scannedBeanDefinitions = this.componentScanParser.parse(componentScan, sourceClass.getMetadata().getClassName());
Iterator var8 = scannedBeanDefinitions.iterator();
while(var8.hasNext()) {
BeanDefinitionHolder holder = (BeanDefinitionHolder)var8.next();
BeanDefinition bdCand = holder.getBeanDefinition().getOriginatingBeanDefinition();
if (bdCand == null) {
bdCand = holder.getBeanDefinition();
}
if (ConfigurationClassUtils.checkConfigurationClassCandidate(bdCand, this.metadataReaderFactory)) {
//todo:解析掃描到的bean,這裡又迴圈會去了,可能是再從它們所在的包繼續向下掃描?
this.parse(bdCand.getBeanClassName(), holder.getBeanName());
}
}
}
}
//2.4.2.3 遞迴處理@Import註解,SpringBoot中經常用的各種@Enable***註解基本都是封裝的@Import
this.processImports(configClass, sourceClass, this.getImports(sourceClass), filter, true);
...
return null;
}
2.4.2.2 掃描bean
主要看看怎麼從掃描bean的,這裡會呼叫doScan()方法掃描bean,然後將beanDefinition註冊到beanDefinitionMap中。
protected Set<BeanDefinitionHolder> doScan(String... basePackages) {
...
for(int var5 = 0; var5 < var4; ++var5) {
String basePackage = var3[var5];
//從basePackage下找bean
Set<BeanDefinition> candidates = this.findCandidateComponents(basePackage);
Iterator var8 = candidates.iterator();
while(var8.hasNext()) {
BeanDefinition candidate = (BeanDefinition)var8.next();
...
if (this.checkCandidate(beanName, candidate)) {
BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(candidate, beanName);
definitionHolder = AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);
beanDefinitions.add(definitionHolder);
//註冊beanDefinition
this.registerBeanDefinition(definitionHolder, this.registry);
}
}
}
return beanDefinitions;
}
執行完上面程式碼,看看掃描到了那些bean,這兩個bean是我們提前寫好的。
@Configuration
public class Config {
@Bean
public MyService getMyService(MyService myService){
return myService;
}
}
回到2.4.2.1的doProcessConfigurationClass(),此時程式碼執行到processImports()方法了,這個方法是處理@Import註解的。
2.4.2.3 processImports()
這個方法會處理@Import註解,這裡主要從SpringBoot自動配置的角度看看這個方法,因為springboot開啟自動配置的註解@EnableAutoConfiguration封裝了@Import註解。進入processImports()程式碼。
private void processImports(ConfigurationClass configClass, SourceClass currentSourceClass, Collection<SourceClass> importCandidates, Predicate<String> exclusionFilter, boolean checkForCircularImports) {
//先看下面那段話
if (!importCandidates.isEmpty()) {
if (checkForCircularImports && this.isChainedImportOnStack(configClass)) {
this.problemReporter.error(new CircularImportProblem(configClass, this.importStack));
} else {
this.importStack.push(configClass);
try {
Iterator var6 = importCandidates.iterator();
while(var6.hasNext()) {
SourceClass candidate = (SourceClass)var6.next();
Class candidateClass;
if (candidate.isAssignable(ImportSelector.class)) {
candidateClass = candidate.loadClass();
ImportSelector selector = (ImportSelector)ParserStrategyUtils.instantiateClass(candidateClass, ImportSelector.class, this.environment, this.resourceLoader, this.registry);
Predicate<String> selectorFilter = selector.getExclusionFilter();
if (selectorFilter != null) {
exclusionFilter = exclusionFilter.or(selectorFilter);
}
//AutoConfigurationImportSelector會走這裡
if (selector instanceof DeferredImportSelector) {
this.deferredImportSelectorHandler.handle(configClass, (DeferredImportSelector)selector);
} else {
String[] importClassNames = selector.selectImports(currentSourceClass.getMetadata());
Collection<SourceClass> importSourceClasses = this.asSourceClasses(importClassNames, exclusionFilter);
this.processImports(configClass, currentSourceClass, importSourceClasses, exclusionFilter, false);
}
} else if (candidate.isAssignable(ImportBeanDefinitionRegistrar.class)) {
//ImportBeanDefinitionRegistrar會
candidateClass = candidate.loadClass();
ImportBeanDefinitionRegistrar registrar = (ImportBeanDefinitionRegistrar)ParserStrategyUtils.instantiateClass(candidateClass, ImportBeanDefinitionRegistrar.class, this.environment, this.resourceLoader, this.registry);
configClass.addImportBeanDefinitionRegistrar(registrar, currentSourceClass.getMetadata());
} else {
//當真正需要註冊需要自動配置的類時會走這裡,不過要走到這裡的入口是在2.4.2.1中提到的 this.deferredImportSelectorHandler.process()這個方法
this.importStack.registerImport(currentSourceClass.getMetadata(), candidate.getMetadata().getClassName());
//又回到了這個方法,在2.4.2.1介紹啟動類註冊的時候說過了,就是註冊到把beanDefinition註冊到Map中,那這裡就是去註冊那些自動配置類了。
this.processConfigurationClass(candidate.asConfigClass(configClass), exclusionFilter);
}
}
} catch (BeanDefinitionStoreException var17) {
throw var17;
} catch (Throwable var18) {
throw new BeanDefinitionStoreException("Failed to process import candidates for configuration class [" + configClass.getMetadata().getClassName() + "]", var18);
} finally {
this.importStack.pop();
}
}
}
}
看這張圖,傳入的兩個importCandidates一個是ImportBeanDefinitionRegistrar類,一個是ImportSelector類,對於AutoConfigurationImportSelector,更準確的說他是一個DeferredImportSelector。從名字也能看出他是延遲執行的,所以這時並不會將自動配置的類注入近來,在2.4.2.1中說過,springboot自動配置的入口是在 this.deferredImportSelectorHandler.process()這個方法下。在看上面的程式碼,兩個不同的類會走不同的if或else。
一直跟進程式碼,直到走到this.deferredImportSelectorHandler.process()。這個方法在ConfigurationClassParser.class的parse()方法下。
//ConfigurationClassParser.class
public void process() {
List<DeferredImportSelectorHolder> deferredImports = this.deferredImportSelectors;
this.deferredImportSelectors = null;
try {
if (deferredImports != null) {
DeferredImportSelectorGroupingHandler handler = ConfigurationClassParser.this.new DeferredImportSelectorGroupingHandler();
deferredImports.sort(ConfigurationClassParser.DEFERRED_IMPORT_COMPARATOR);
deferredImports.forEach(handler::register);
//重點是這個
handler.processGroupImports();
}
} finally {
this.deferredImportSelectors = new ArrayList();
}
}
在跟進processGroupImports()方法。
//ConfigurationClassParser.class
public void processGroupImports() {
Iterator var1 = this.groupings.values().iterator();
while(var1.hasNext()) {
...
//呼叫getImport()方法去找spring.factories檔案中的自動配置類
grouping.getImports().forEach((entry) -> {
ConfigurationClass configurationClass = (ConfigurationClass)this.configurationClasses.get(entry.getMetadata());
try {
//又到了這個方法了,之前也提過,會走processImports()的最後一個else
ConfigurationClassParser.this.processImports(configurationClass, ConfigurationClassParser.this.asSourceClass(configurationClass, exclusionFilter), Collections.singleton(ConfigurationClassParser.this.asSourceClass(entry.getImportClassName(), exclusionFilter)), exclusionFilter, false);
}
...
});
}
}
進入getImport()方法:
////ConfigurationClassParser.class
public Iterable<DeferredImportSelector.Group.Entry> getImports() {
Iterator var1 = this.deferredImports.iterator();
while(var1.hasNext()) {
DeferredImportSelectorHolder deferredImport = (DeferredImportSelectorHolder)var1.next();
//這裡會呼叫Group介面的實現類AutoConfigurationImportSelector,執行process()方法將需要自動配置的類放到一個map中
this.group.process(deferredImport.getConfigurationClass().getMetadata(), deferredImport.getImportSelector());
}
//呼叫AutoConfigurationImportSelector的selectImports()封裝map然後返回需要自動配置的類
return this.group.selectImports();
}
DeferredImportSelector下定義了一個Group介面,AutoConfigurationImportSelector實現了這個介面,當程式執行到this.group.process(),會去呼叫AutoConfigurationImportSelector實現的process()。
public void process(AnnotationMetadata annotationMetadata, DeferredImportSelector deferredImportSelector) {
Assert.state(deferredImportSelector instanceof AutoConfigurationImportSelector, () -> {
return String.format("Only %s implementations are supported, got %s", AutoConfigurationImportSelector.class.getSimpleName(), deferredImportSelector.getClass().getName());
});
//getAutoConfigurationEntry()最終會呼叫SpringFactoriesLoader.loadFactoryNames()方法去載入spring.factories檔案中的類
AutoConfigurationEntry autoConfigurationEntry = ((AutoConfigurationImportSelector)deferredImportSelector).getAutoConfigurationEntry(annotationMetadata);
this.autoConfigurationEntries.add(autoConfigurationEntry);
Iterator var4 = autoConfigurationEntry.getConfigurations().iterator();
while(var4.hasNext()) {
String importClassName = (String)var4.next();
//將這些需要自動配置的類放到一個名為entries的map中
this.entries.putIfAbsent(importClassName, annotationMetadata);
}
}
然後呼叫AutoConfigurationImportSelector的selectImports()封裝map然後返回需要自動配置的類
之後再回到ConfigurationClassParser的processGroupImports()方法執行後面的processImports()方法,這時才真正開始註冊自動配置類的beanDefinition,這時的processImports()會進入processImports()的最後一個else,processConfigurationClass()這個方法前面說過了,將beanDefinition註冊到Map中。
//ConfigurationClassParser.class
private void processImports(ConfigurationClass configClass, SourceClass currentSourceClass, Collection<SourceClass> importCandidates, Predicate<String> exclusionFilter, boolean checkForCircularImports) {
...
try {
Iterator var6 = importCandidates.iterator();
while(var6.hasNext()) {
...
} else {
this.importStack.registerImport(currentSourceClass.getMetadata(), candidate.getMetadata().getClassName());
this.processConfigurationClass(candidate.asConfigClass(configClass), exclusionFilter);
}
}
}
...
}
這部分就到這裡了,回到2.4。
2.4.3 finishBeanFactoryInitialization()初始化bean
之前只是將bean的beanDefinition註冊到IOC容器中,但是還沒有初始化,bean的完整生命週期是在這個方法中完成的。我們以自定義的bean為例來看看bean的初始化。跟進程式碼,到AbstractBeanFactory.class的doGetBean時在斷點上新增條件,這個條件就是beanName=myController時才會進去。
//AbstractBeanFactory.class
protected <T> T doGetBean(String name, @Nullable Class<T> requiredType, @Nullable Object[] args, boolean typeCheckOnly) throws BeansException {
String beanName = this.transformedBeanName(name);
Object sharedInstance = this.getSingleton(beanName);
Object bean;
if (sharedInstance != null && args == null) {
//...
} else {
//...
try {
//獲取bean的beanDefinition
RootBeanDefinition mbd = this.getMergedLocalBeanDefinition(beanName);
this.checkMergedBeanDefinition(mbd, beanName, args);
//...
//如果是單例bean
if (mbd.isSingleton()) {
//獲取bean,這裡是從緩衝池裡拿,在初始化bean的過程中會把他們放到緩衝池
sharedInstance = this.getSingleton(beanName, () -> {
try {
//bean的初始化過程是在這裡完成的
return this.createBean(beanName, mbd, args);
} catch (BeansException var5) {
this.destroySingleton(beanName);
throw var5;
}
});
bean = this.getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
} else if (mbd.isPrototype()) {
//...
} else {
//...
}
} catch (BeansException var26) {
this.cleanupAfterBeanCreationFailure(beanName);
throw var26;
}
}
//...
}
然後一直跟進程式碼createBean()方法,直到AbstractAutowireCapableBeanFactory.class的doCreateBean()方法,這裡完成了bean的初始化,主要包括三個步驟:1、建立bean例項。2、為bean例項進行屬性注入。3、呼叫bean的初始化方法。
//AbstractAutowireCapableBeanFactory.class
protected Object doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) throws BeanCreationException {
BeanWrapper instanceWrapper = null;
if (mbd.isSingleton()) {
instanceWrapper = (BeanWrapper)this.factoryBeanInstanceCache.remove(beanName);
}
if (instanceWrapper == null) {
//2.4.3.1 建立bean例項
instanceWrapper = this.createBeanInstance(beanName, mbd, args);
}
Object bean = instanceWrapper.getWrappedInstance();
//...
//如果bean是單例且允許迴圈引用且正在建立,暴露一個bean的早期物件工廠,放到三級快取
boolean earlySingletonExposure = mbd.isSingleton() && this.allowCircularReferences && this.isSingletonCurrentlyInCreation(beanName);
if (earlySingletonExposure) {
//...
this.addSingletonFactory(beanName, () -> {
return this.getEarlyBeanReference(beanName, mbd, bean);
});
}
Object exposedObject = bean;
try {
//2.4.3.2 屬性注入
this.populateBean(beanName, mbd, instanceWrapper);
//2.4.3.3 呼叫初始化方法
exposedObject = this.initializeBean(beanName, exposedObject, mbd);
} catch (Throwable var18) {
if (var18 instanceof BeanCreationException && beanName.equals(((BeanCreationException)var18).getBeanName())) {
throw (BeanCreationException)var18;
}
throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Initialization of bean failed", var18);
}
if (earlySingletonExposure) {
Object earlySingletonReference = this.getSingleton(beanName, false);
if (earlySingletonReference != null) {
if (exposedObject == bean) {
exposedObject = earlySingletonReference;
} else if (!this.allowRawInjectionDespiteWrapping && this.hasDependentBean(beanName)) {
String[] dependentBeans = this.getDependentBeans(beanName);
Set<String> actualDependentBeans = new LinkedHashSet(dependentBeans.length);
String[] var12 = dependentBeans;
int var13 = dependentBeans.length;
for(int var14 = 0; var14 < var13; ++var14) {
String dependentBean = var12[var14];
if (!this.removeSingletonIfCreatedForTypeCheckOnly(dependentBean)) {
actualDependentBeans.add(dependentBean);
}
}
//...
}
}
}
try {
this.registerDisposableBeanIfNecessary(beanName, bean, mbd);
return exposedObject;
} catch (BeanDefinitionValidationException var16) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Invalid destruction signature", var16);
}
}
2.4.3.1 createBeanInstance()建立bean例項
protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) {
Class<?> beanClass = this.resolveBeanClass(mbd, beanName, new Class[0]);
if (beanClass != null && !Modifier.isPublic(beanClass.getModifiers()) &&
//...
} else {
Supplier<?> instanceSupplier = mbd.getInstanceSupplier();
if (instanceSupplier != null) {
return this.obtainFromSupplier(instanceSupplier, beanName);
} else if (mbd.getFactoryMethodName() != null) {
return this.instantiateUsingFactoryMethod(beanName, mbd, args);
} else {
//...
if (resolved) {
//...
} else {
Constructor<?>[] ctors = this.determineConstructorsFromBeanPostProcessors(beanClass, beanName);
if (ctors == null && mbd.getResolvedAutowireMode() != 3 && !mbd.hasConstructorArgumentValues() && ObjectUtils.isEmpty(args)) {
ctors = mbd.getPreferredConstructors();
//對於myController這個我們自定義的bean,會進入instantiateBean()方法,透過BeanUtils建立bean例項
return ctors != null ? this.autowireConstructor(beanName, mbd, ctors, (Object[])null) : this.instantiateBean(beanName, mbd);
} else {
return this.autowireConstructor(beanName, mbd, ctors, args);
}
}
}
}
}
2.4.3.2 populateBean()屬性注入
protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) {
if (bw == null) {
//...
} else {
//...
boolean hasInstAwareBpps = this.hasInstantiationAwareBeanPostProcessors();
//...
if (hasInstAwareBpps) {
if (pvs == null) {
pvs = mbd.getPropertyValues();
}
Iterator var9 = this.getBeanPostProcessors().iterator();
//使用後置處理器進行屬性注入,對於透過@Autowired注入的屬性,使用ImportAwareBeanPostProcessor這個處理器,用它完成屬性注入,它是InstantiationAwareBeanPostProcessor的一個實現類。
while(var9.hasNext()) {
BeanPostProcessor bp = (BeanPostProcessor)var9.next();
if (bp instanceof InstantiationAwareBeanPostProcessor) {
InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor)bp;
//假如MyController中注入了MyService,在這裡會先去初始化MyService,流程和MyController一樣,之後再回到MyController的生命週期進行屬性注入。
PropertyValues pvsToUse = ibp.postProcessProperties((PropertyValues)pvs, bw.getWrappedInstance(), beanName);
//...
}
}
}
//...
}
}
進入postProcessProperties()看看注入邏輯。
//AutowriedAnnotationBeanPostProcessor.class
public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) {
//尋找要注入的屬性
InjectionMetadata metadata = this.findAutowiringMetadata(beanName, bean.getClass(), pvs);
try {
//注入
metadata.inject(bean, beanName, pvs);
return pvs;
} catch (BeanCreationException var6) {
throw var6;
} catch (Throwable var7) {
throw new BeanCreationException(beanName, "Injection of autowired dependencies failed", var7);
}
}
findAutowiringMetadata()可以找到要注入的屬性,看下面的圖,找到了要注入到MyController中的MyService。
然後執行inject()方法進行注入,注入MyService時會先去初始化MyService,流程是一樣的。
2.4.3.3 initializeBean()呼叫初始化方法
protected Object initializeBean(String beanName, Object bean, @Nullable RootBeanDefinition mbd) {
if (System.getSecurityManager() != null) {
AccessController.doPrivileged(() -> {
this.invokeAwareMethods(beanName, bean);
return null;
}, this.getAccessControlContext());
} else {
//呼叫Aware介面的實現,設定相關的beanName、beanClassLoader、BeanFactory等,自己定義的bean好像不會走這。
this.invokeAwareMethods(beanName, bean);
}
Object wrappedBean = bean;
if (mbd == null || !mbd.isSynthetic()) {
//在初始化之前呼叫BeanPostProcessor,為了方便擴充套件吧
wrappedBean = this.applyBeanPostProcessorsBeforeInitialization(bean, beanName);
}
try {
//呼叫初始化方法
this.invokeInitMethods(beanName, wrappedBean, mbd);
} catch (Throwable var6) {
throw new BeanCreationException(mbd != null ? mbd.getResourceDescription() : null, beanName, "Invocation of init method failed", var6);
}
if (mbd == null || !mbd.isSynthetic()) {
//初始化之後呼叫BeanPostProcessor
wrappedBean = this.applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
}
return wrappedBean;
}
接下來看一下invokeInitMethods()方法,有兩個初始化方法,第一個是實現InitializingBean介面並重寫afterPropertiesSet()方法,第二種方法是設定init-method方法。springboot會判斷我們有沒有定義這些方法,如果有就按順序執行就好了。
protected void invokeInitMethods(String beanName, Object bean, @Nullable RootBeanDefinition mbd) throws Throwable {
//判斷bean有沒有實現InitializingBean介面並重寫afterPropertiesSet()方法,如果判斷為ture,那就呼叫afterPropertiesSet()方法進行初始化。
boolean isInitializingBean = bean instanceof InitializingBean;
if (isInitializingBean && (mbd == null || !mbd.isExternallyManagedInitMethod("afterPropertiesSet"))) {
if (this.logger.isTraceEnabled()) {
this.logger.trace("Invoking afterPropertiesSet() on bean with name '" + beanName + "'");
}
if (System.getSecurityManager() != null) {
try {
AccessController.doPrivileged(() -> {
((InitializingBean)bean).afterPropertiesSet();
return null;
}, this.getAccessControlContext());
} catch (PrivilegedActionException var6) {
throw var6.getException();
}
} else {
//呼叫afterPropertiesSet()進行初始化
((InitializingBean)bean).afterPropertiesSet();
}
}
//判斷bean是否配置了init-method方法,如果判斷為true,透過反射得到method物件,然後呼叫init-method,完成最後的初始化。
if (mbd != null && bean.getClass() != NullBean.class) {
String initMethodName = mbd.getInitMethodName();
if (StringUtils.hasLength(initMethodName) && (!isInitializingBean || !"afterPropertiesSet".equals(initMethodName)) && !mbd.isExternallyManagedInitMethod(initMethodName)) {
this.invokeCustomInitMethod(beanName, bean, mbd);
}
}
}
自定義這兩種方法也很簡單,如下:
//實現InitializingBean介面並重寫afterPropertiesSet()方法
@Controller
public class MyController implements InitializingBean {
@Autowired
private MyService myService;
public void testController(){
return;
}
@Override
public void afterPropertiesSet() throws Exception {
System.out.println("method 1");
}
}
//配置了init-method方法
@Configuration
public class Config {
@Bean(initMethod = "test")
public MyService getMyService(MyService myService){
return myService;
}
}
@Service
public class MyService {
public void test(){
System.out.println("haha");
}
}
到這裡單例bean就初始化完了,結束。
3、補充:迴圈依賴
Spring解決迴圈依賴的流程如下圖所示。
沒有AOP的情況下:
Spring透過三級快取解決迴圈依賴問題,假設A和B發生了迴圈依賴,在A的生命週期中,在A建立了例項之後,會生成一個A的物件工廠並將其放入三級快取,在A進行屬性注入時,發生A依賴了B,這時Spring會先去建立B,和A的流程一樣,當B進行屬性注入時發現依賴了A,這時Spring又會呼叫doGetBean()想去建立A,但是在建立A之前,會先呼叫getSingleton()方法從快取中取,這時Spring從三級快取中呼叫A的物件工廠來生成一個A的早期物件,然後把它放到二級快取。將A注入B之後,B會走完剩下的生命週期,然後透過getSingleton()方法將B放入一級快取。接下來,A會走完剩下的生命週期,並且會把A放入一級快取。就這樣,A和B就都初始化完了。
有AOP的情況下:
AOP動態代理的處理一般是發生在bean初始化之後的,也就是initializeBean()方法中的最後執行applyBeanPostProcessorsAfterInitialization()時生成代理物件,但是當出現迴圈依賴時,可以發現bean的AOP代理提前發生了。我覺得將AOP代理提前才是為什麼需要第三級快取的原因把。
還是看上面這個例子,當A經過例項化createInstance之後,會生成一個早期bean工廠放入三級快取,程式碼是這樣的,可以看到它傳入了一個lambda表達時,當三級快取中的早期bean工廠執行getObject()時會觸發這個lambda表示式呼叫getEarlyBeanReference(),也就是當B需要注入A時,需要走到這一步。如果A被AOP代理了,這個這個方法會去調wrapIfNecessary()方法生成A的代理物件。如果沒有三級快取,那麼就無法提前生成bean的代理物件,那麼B中就會注入A的原始物件,但是當A經過初始化之後再去生成AOP代理物件,就會出現多個A,這不符合單例模式。
this.addSingletonFactory(beanName, () -> {
return this.getEarlyBeanReference(beanName, mbd, bean);
});