九江建設(shè)監(jiān)督網(wǎng)站國(guó)外友鏈買賣平臺(tái)
參考文章:SpringBoot啟動(dòng)流程系列講解
參考視頻:SpringBoot啟動(dòng)流程
吐血推薦視頻:史上最完整的Spring啟動(dòng)流程
超級(jí)好文:SpringBoot執(zhí)行原理
參考文章:SpringBoot資源接口ResourceLoader和Resource學(xué)習(xí)
參考文章:到底什么是上下文(Context)
參考文章:超級(jí)好文
參考文章:這個(gè)系列的文章,讓我自愧不如,痛刪了原來2W字的內(nèi)容
文章目錄
- Spring Boot啟動(dòng)流程
- 服務(wù)構(gòu)建
- 環(huán)境準(zhǔn)備
- 容器創(chuàng)建
- 填充容器
- 非常重要的函數(shù)
- getSpringFactoriesInstances()
- getClassLoader()
- deduceMainApplicationClass()
- getRunListeners(String[] args)
- SpringApplicationRunListeners.starting()
- prepareEnvironment(SpringApplicationRunListeners, applicationArguments)
- prepareContext()
- refreshContext()
- refreshContext().refresh().obtainFreshBeanFactory()
- refreshContext().refresh().finishBeanFactoryInitialization(beanFactory)
- 非常重要的類
- ResourceLoader
- 總結(jié)
- **4. 填充容器(就是容器創(chuàng)建的refreshContext)**
Spring Boot啟動(dòng)流程
服務(wù)構(gòu)建
//SpringApplication類
//只列出幾個(gè)重要的字段和方法
public class SpringApplication {//SpringApplication默認(rèn)web容器類public static final String DEFAULT_SERVLET_WEB_CONTEXT_CLASS = "org.springframework.boot."+ "web.servlet.context.AnnotationConfigServletWebServerApplicationContext";//banner名稱,默認(rèn)為banner.txtpublic static final String BANNER_LOCATION_PROPERTY_VALUE = SpringApplicationBannerPrinter.DEFAULT_BANNER_LOCATION;//banner位置key,默認(rèn)為spring.banner.locationpublic static final String BANNER_LOCATION_PROPERTY = SpringApplicationBannerPrinter.BANNER_LOCATION_PROPERTY;//調(diào)用main函數(shù)的類,也就是YanggxApplication.classprivate Class<?> mainApplicationClass;//bean名稱生成器,執(zhí)行結(jié)果為nullprivate BeanNameGenerator beanNameGenerator;//spring的環(huán)境,我們使用的是ServletWeb環(huán)境private ConfigurableEnvironment environment;//web類型,執(zhí)行結(jié)果為SERVLETprivate WebApplicationType webApplicationType;//Application初始化器,springboot啟動(dòng)過程中執(zhí)行其initialize方法private List<ApplicationContextInitializer<?>> initializers;//Application監(jiān)聽器,springboot啟動(dòng)過程執(zhí)行其onApplicationEvent方法private List<ApplicationListener<?>> listeners;/*** SpringApplication構(gòu)造函數(shù)* @param resourceLoader 資源加載器的策略接口,傳參null,* @param primarySources 傳參YanggxApplication.class*/public SpringApplication(ResourceLoader resourceLoader, Class<?>... primarySources) {//執(zhí)行結(jié)果:nullthis.resourceLoader = resourceLoader;Assert.notNull(primarySources, "PrimarySources must not be null");//Set去重:"primarySources":[com.yanggx.spring.YanggxApplication.class]this.primarySources = new LinkedHashSet<>(Arrays.asList(primarySources));// 判斷當(dāng)前模塊web類型:"webApplicationType":"SERVLET"this.webApplicationType = WebApplicationType.deduceFromClasspath();// 加載Application初始化器// 獲取所有"META-INF/spring.factories"文件中維護(hù)的ApplicationContextInitializer子類列表// org.springframework.boot.context.ConfigurationWarningsApplicationContextInitializer// org.springframework.boot.context.ContextIdApplicationContextInitializer // org.springframework.boot.context.config.DelegatingApplicationContextInitializer // org.springframework.boot.web.context.ServerPortInfoApplicationContextInitializer // org.springframework.boot.autoconfigure.logging.ConditionEvaluationReportLoggingListenersetInitializers((Collection) getSpringFactoriesInstances(ApplicationContextInitializer.class));// 3.3 加載Application監(jiān)聽器// 獲取所有"META-INF/spring.factories"文件中維護(hù)的ApplicationListener子類列表// org.springframework.boot.ClearCachesApplicationListener// org.springframework.boot.builder.ParentContextCloserApplicationListener// org.springframework.boot.context.FileEncodingApplicationListener// org.springframework.boot.context.config.AnsiOutputApplicationListener// org.springframework.boot.context.config.ConfigFileApplicationListener// org.springframework.boot.context.config.DelegatingApplicationListener// org.springframework.boot.context.logging.ClasspathLoggingApplicationListener// org.springframework.boot.context.logging.LoggingApplicationListener// org.springframework.boot.liquibase.LiquibaseServiceLocatorApplicationListener// org.springframework.boot.autoconfigure.BackgroundPreinitializer// 加載的這些類都是ApplicationListener的子類setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));// 3.4 找到啟動(dòng)類// 拋出一個(gè)RuntimeException,然后通過堆棧信息找到啟動(dòng)類//"mainApplicationClass": com.yanggx.spring.YanggxApplication.classthis.mainApplicationClass = deduceMainApplicationClass();}
}
環(huán)境準(zhǔn)備
public class SpringApplication {public ConfigurableApplicationContext run(String... args) {//實(shí)例化一個(gè)StopWatch實(shí)例, 監(jiān)控項(xiàng)目運(yùn)行時(shí)間StopWatch stopWatch = new StopWatch();stopWatch.start();//初始化Spring上下文ConfigurableApplicationContext context = null;//初始化錯(cuò)誤報(bào)告參數(shù)Collection<SpringBootExceptionReporter> exceptionReporters = new ArrayList<>();//配置headless,在沒有顯示器,鼠標(biāo),鍵盤的情況下,仍然可以調(diào)用顯示,輸入輸出的方法configureHeadlessProperty();//1. 發(fā)布Spring啟動(dòng)事件SpringApplicationRunListeners listeners = getRunListeners(args);listeners.starting();try {/*2. 這一步的主要作用是處理啟動(dòng)類main函數(shù)的參數(shù), 將其封裝為一個(gè) DefaultApplicationArguments對(duì)象, 為prepareEnvironment()提供參數(shù)*/ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);//3.這一步的主要作用按順序加載命令行參數(shù), 系統(tǒng)參數(shù)和外部配置文件, 創(chuàng)建并配置Web環(huán)境ConfigurableEnvironment environment = prepareEnvironment(listeners, applicationArguments); configureIgnoreBeanInfo(environment);//4. 打印Banner圖Banner printedBanner = printBanner(environment);//....}
容器創(chuàng)建
public ConfigurableApplicationContext run(String... args) {//步驟1: 根據(jù)switch創(chuàng)建context,分別有:SERVLET、REACTIVE、NONE,并且注冊(cè)了Bean后置處理器context = createApplicationContext();//步驟2: BeanFactory是在這里創(chuàng)建的context.setApplicationStartup(this.applicationStartup);//步驟2: prepareContext()準(zhǔn)備應(yīng)用上下文prepareContext(context, environment, listeners, applicationArguments, printedBanner);//步驟3: refreshContext()刷新應(yīng)用上下文,BeanDefinition和BeanFactory都是在這里創(chuàng)建的refreshContext(context);//步驟4: 刷新完成,該方法是拓展接口,用戶可以自定義操作邏輯afterRefresh(context, applicationArguments);//步驟6: 發(fā)布Application開始事件listeners.started(context);//步驟7: 執(zhí)行Runners,用于調(diào)用項(xiàng)目中自定義的執(zhí)行器xxxRunner類,//在項(xiàng)目啟動(dòng)完成后立即執(zhí)行,這些操作只在服務(wù)啟動(dòng)時(shí)執(zhí)行一次callRunners(context, applicationArguments);//步驟8: 發(fā)布Application準(zhǔn)備事件listeners.running(context);return context;
}
填充容器
/*** 抽象父類ApplicationContext*/
public abstract class AbstractApplicationContext extends DefaultResourceLoaderimplements ConfigurableApplicationContext {@Overridepublic void refresh() throws BeansException, IllegalStateException {synchronized (this.startupShutdownMonitor) {//刷新前操作,例如:清空緩存、初始化占位符prepareRefresh();//獲取并刷新beanFactory,創(chuàng)建BeanFactory和BeanDefinitionConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();//設(shè)置beanFactory,配置各種beanFactory.xxx屬性prepareBeanFactory(beanFactory);//beanFactory的后置處理器:注冊(cè)與Servlet相關(guān)的特殊Bean,注冊(cè)beanDefinitionpostProcessBeanFactory(beanFactory);/*BeanFactoryPostProcessor是一個(gè)接口, 處理beanFactory中所有的bean, 在所有的beanDefinition加載完成之后, BeanFactoryPostProcessor可以對(duì)beanDefinition進(jìn)行屬性的修改, 之后再進(jìn)行bean實(shí)例化*/invokeBeanFactoryPostProcessors(beanFactory);//beanFactory注冊(cè)后置處理器,對(duì)bean實(shí)例的增強(qiáng)registerBeanPostProcessors(beanFactory);//初始化messageSourceinitMessageSource();//初始化Application事件發(fā)布器initApplicationEventMulticaster();//初始化其他特殊的bean,例如實(shí)例化了TomcatWebServeronRefresh();//注冊(cè)監(jiān)聽器registerListeners();//完成beanFactory初始化finishBeanFactoryInitialization(beanFactory);//完成刷新,發(fā)布完成事件,實(shí)例化了所有beanfinishRefresh(); }
}
非常重要的函數(shù)
getSpringFactoriesInstances()
private <T> Collection<T> getSpringFactoriesInstances(Class<T> type, Class<?>[] parameterTypes, Object... args) {ClassLoader classLoader = this.getClassLoader();Set<String> names = new LinkedHashSet(SpringFactoriesLoader.loadFactoryNames(type, classLoader));List<T> instances = this.createSpringFactoriesInstances(type, parameterTypes, classLoader, args, names);AnnotationAwareOrderComparator.sort(instances);return instances;}
public static List<String> loadFactoryNames(Class<?> factoryType, @Nullable ClassLoader classLoader) {//主要獲取spring.factories中的key,key對(duì)應(yīng)接口全名String factoryTypeName = factoryType.getName();//篩選Map中key為factoryTypeName對(duì)應(yīng)放到list返回 return loadSpringFactories(classLoader).getOrDefault(factoryTypeName, Collections.emptyList());}
//會(huì)把Spring.factories文件中所有鍵值對(duì)放到Map中,其實(shí)就是緩存//classLoader參數(shù)就是"META-INF/spring.factories"加載器private static Map<String, List<String>> loadSpringFactories(@Nullable ClassLoader classLoader) {//如果緩存已經(jīng)有Spring.factories,那就從緩存中拿MultiValueMap<String, String> result = cache.get(classLoader);if (result != null) {return result;}//如果緩存中沒有Spring.factories,那就從重新加載到緩存Enumeration<URL> urls = (classLoader != null ?// FACTORIES_RESOURCE_LOCATION = "META-INF/spring.factories" classLoader.getResources(FACTORIES_RESOURCE_LOCATION) :ClassLoader.getSystemResources(FACTORIES_RESOURCE_LOCATION));result = new LinkedMultiValueMap<>();while (urls.hasMoreElements()) {URL url = urls.nextElement();UrlResource resource = new UrlResource(url);Properties properties = PropertiesLoaderUtils.loadProperties(resource);for (Map.Entry<?, ?> entry : properties.entrySet()) {String factoryTypeName = ((String) entry.getKey()).trim();for (String factoryImplementationName : StringUtils.commaDelimitedListToStringArray((String) entry.getValue())) {result.add(factoryTypeName, factoryImplementationName.trim());}}}cache.put(classLoader, result);return result;}
private <T> List<T> createSpringFactoriesInstances(Class<T> type, Class<?>[] parameterTypes,ClassLoader classLoader, Object[] args, Set<String> names) {List<T> instances = new ArrayList<>(names.size());for (String name : names) {try {//通過反射機(jī)制創(chuàng)建實(shí)例Class<?> instanceClass = ClassUtils.forName(name, classLoader);Assert.isAssignable(type, instanceClass);Constructor<?> constructor = instanceClass.getDeclaredConstructor(parameterTypes);T instance = (T) BeanUtils.instantiateClass(constructor, args);instances.add(instance);}catch (Throwable ex) {throw new IllegalArgumentException("Cannot instantiate " + type + " : " + name, ex);}}return instances;}
總結(jié):
- loadSpringFactories(@Nullable ClassLoader classLoader):判斷緩存是否有Spring.factories文件,如果有就提取整個(gè)spring.factories。如果沒有就加載到緩存再提取。
- loadFactoryNames(Class<?> factoryType, @Nullable ClassLoader classLoader):從spring.factories文件中獲取指定factoryType
- createSpringFactoriesInstances(Class type, Class<?>[] parameterTypes,
ClassLoader classLoader, Object[] args, Set names):將loadFactoryNames()返回的factoryType,通過反射機(jī)制實(shí)例化- getSpringFactoriesInstances(Class type, Class<?>[] parameterTypes, Object… args):獲取createSpringFactoriesInstances()返回的實(shí)例instances,返回實(shí)例
getClassLoader()
- 我們都知道java程序?qū)懞靡院笫且?java(文本文件)的文件存在磁盤上,然后,我們通過(bin/javac.exe)編譯命令把.java文件編譯成.class文件(字節(jié)碼文件),并存在磁盤上。
但是程序要運(yùn)行,首先一定要把.class文件加載到JVM內(nèi)存中才能使用的,我們所講的classLoader,就是負(fù)責(zé)把磁盤上的.class文件加載到JVM內(nèi)存中- 你可以認(rèn)為每一個(gè)Class對(duì)象擁有磁盤上的那個(gè).class字節(jié)碼內(nèi)容,每一個(gè)class對(duì)象都有一個(gè)getClassLoader()方法,得到是誰把我從.class文件加載到內(nèi)存中變成Class對(duì)象的
deduceMainApplicationClass()
private Class<?> deduceMainApplicationClass() {try {//通過一個(gè)RuntimeException,獲取器堆棧信息StackTraceElement[] stackTrace = new RuntimeException().getStackTrace();for (StackTraceElement stackTraceElement : stackTrace) {if ("main".equals(stackTraceElement.getMethodName())) {//堆棧中包含main方法,實(shí)例化一個(gè)該類的對(duì)象return Class.forName(stackTraceElement.getClassName());}}}catch (ClassNotFoundException ex) { }return null;
}
getRunListeners(String[] args)
//當(dāng)前只能獲取SpringApplicationRunListener子類列表EventPublishingRunListenerprivate SpringApplicationRunListeners getRunListeners(String[] args) {Class<?>[] types = new Class<?>[] { SpringApplication.class, String[].class };return new SpringApplicationRunListeners(logger, getSpringFactoriesInstances(SpringApplicationRunListener.class, types, this, args));}
SpringApplicationRunListeners.starting()
//該SpringApplicationRunListeners存在多個(gè)子類,在下面starting方法中,會(huì)調(diào)用對(duì)應(yīng)子類的starting方法
class SpringApplicationRunListeners {//發(fā)布啟動(dòng)事件public void starting() {for (SpringApplicationRunListener listener : this.listeners) {//目前調(diào)用EventPublishingRunListener的starting方法listener.starting();}}//其他事件都是相同的代碼
}
//不僅僅是ApplicationListeners存在很多子類,EventPublishingRunListener也有很多子類
public class EventPublishingRunListener implements SpringApplicationRunListener, Ordered {//SpringApplication對(duì)象private final SpringApplication application;//命令函參數(shù)private final String[] args;//事件廣播器private final SimpleApplicationEventMulticaster initialMulticaster;public EventPublishingRunListener(SpringApplication application, String[] args) {this.application = application;this.args = args;this.initialMulticaster = new SimpleApplicationEventMulticaster();// 通過application.getListeners(),獲取到Listener列表// ConfigFileApplicationListener// AnsiOutputApplicationListener// LoggingApplicationListener// ClasspathLoggingApplicationListener// BackgroundPreinitializer// DelegatingApplicationListener// ParentContextCloserApplicationListener// ClearCachesApplicationListener// FileEncodingApplicationListener// LiquibaseServiceLocatorApplicationListenerfor (ApplicationListener<?> listener : application.getListeners()) {//將listener添加到事件廣播器initialMulticasterthis.initialMulticaster.addApplicationListener(listener);}}@Overridepublic void starting() {// 廣播器廣播ApplicationStartingEvent事件this.initialMulticaster.multicastEvent(new ApplicationStartingEvent(this.application, this.args));}//其他事件發(fā)布都是相同的代碼//...
}
public class SimpleApplicationEventMulticaster extends AbstractApplicationEventMulticaster {public void multicastEvent(final ApplicationEvent event, @Nullable ResolvableType eventType) {ResolvableType type = (eventType != null ? eventType : resolveDefaultEventType(event));//調(diào)用父類getApplicationListeners方法//遍歷所有支持ApplicationStartingEvent事件的監(jiān)聽器//LoggingApplicationListener//BackgroundPreinitializer//DelegatingApplicationListener//LiquibaseServiceLocatorApplicationListenerfor (final ApplicationListener<?> listener : getApplicationListeners(event, type)) {//此時(shí)的executor為nullExecutor executor = getTaskExecutor();if (executor != null) {executor.execute(() -> invokeListener(listener, event));}else {//調(diào)用listenerinvokeListener(listener, event);}}}
}
protected void invokeListener(ApplicationListener<?> listener, ApplicationEvent event) {ErrorHandler errorHandler = this.getErrorHandler();if (errorHandler != null) {try {this.doInvokeListener(listener, event);} catch (Throwable var5) {errorHandler.handleError(var5);}} else {this.doInvokeListener(listener, event);}}
private void doInvokeListener(ApplicationListener listener, ApplicationEvent event) {//調(diào)用listener的onApplicationEvent方法listener.onApplicationEvent(event);}
onApplicationEvent(event){到這里就不再深究了,這個(gè)方法有三十個(gè)實(shí)現(xiàn)類,操作基本上就是綁定環(huán)境,設(shè)置參數(shù)等等
}
總結(jié):
- SpringApplicationRunListeners.starting()調(diào)用了EventPublishingRunListener.starting();
- EventPublishingRunListener.starting()調(diào)用了廣播器initialMulticaster.multicastEvent()發(fā)布SpringApplication啟動(dòng)事件
- initialMulticaster.multicastEvent()分別調(diào)用了LoggingApplicationListener、BackgroundPreinitializer、DelegatingApplicationListener、LiquibaseServiceLocatorApplicationListener的invokeListener()方法
invokeListener()——doInvokeListener()——onApplicationEvent()——設(shè)置參數(shù)、綁定環(huán)境等等
prepareEnvironment(SpringApplicationRunListeners, applicationArguments)
private ConfigurableEnvironment prepareEnvironment(SpringApplicationRunListeners listeners,ApplicationArguments applicationArguments) {//獲取或者創(chuàng)建環(huán)境,根據(jù)switch判斷,選擇SERVLET、REACTIVE、NONE類型ConfigurableEnvironment environment = getOrCreateEnvironment();//配置環(huán)境:為environment配置“共享的類型轉(zhuǎn)換服務(wù)”,即:A數(shù)據(jù)類型變成B數(shù)據(jù)類型 //然后將defaultProperties和args分別添加到environment的propertySources中configureEnvironment(environment, applicationArguments.getSourceArgs());//發(fā)布環(huán)境準(zhǔn)備事件listeners.environmentPrepared(environment);//如果指定了main函數(shù),那么會(huì)將當(dāng)前環(huán)境綁定到指定的SpringApplication中bindToSpringApplication(environment);if (!this.isCustomEnvironment) {//環(huán)境轉(zhuǎn)換:如果environment.class和模塊EnvironmentClass()不一致,就轉(zhuǎn)換成一樣的environment = new EnvironmentConverter(getClassLoader()).convertEnvironmentIfNecessary(environment, deduceEnvironmentClass());}//將環(huán)境依附到PropertySourcesConfigurationPropertySources.attach(environment);return environment;}
prepareContext()
private void prepareContext(ConfigurableApplicationContext context,ConfigurableEnvironment environment, SpringApplicationRunListeners listeners,ApplicationArguments applicationArguments, Banner printedBanner) {//設(shè)置context環(huán)境:統(tǒng)一ApplicationContext與Application.environment一致context.setEnvironment(environment);//設(shè)置ApplicationContext.beanNameGenerator、resourceLoader、classLoader、類型轉(zhuǎn)換服務(wù)postProcessApplicationContext(context);//獲取6個(gè)初始化器并執(zhí)行初始化方法,例如設(shè)置元數(shù)據(jù)、配置警告、獲取應(yīng)用名稱applyInitializers(context);//發(fā)布contextPrepared事件listeners.contextPrepared(context);if (this.logStartupInfo) {//配置了info日志//打印啟動(dòng)和profile日志logStartupInfo(context.getParent() == null);logStartupProfileInfo(context);}//獲取到DefaultListableBeanFactory實(shí)例ConfigurableListableBeanFactory beanFactory = context.getBeanFactory();//注冊(cè)名為springApplicationArguments,值為applicationArguments的單例beanbeanFactory.registerSingleton("springApplicationArguments", applicationArguments);//banner不為空,那么注冊(cè)名為springBootBanner,值為printedBanner的單例beanif (printedBanner != null) {beanFactory.registerSingleton("springBootBanner", printedBanner);}if (beanFactory instanceof DefaultListableBeanFactory) {//allowBeanDefinitionOverriding默認(rèn)為false((DefaultListableBeanFactory) beanFactory).setAllowBeanDefinitionOverriding(this.allowBeanDefinitionOverriding);}// 獲取sources列表,獲取到我們的YanggxApplication.classSet<Object> sources = getAllSources();Assert.notEmpty(sources, "Sources must not be empty");//初始化bean加載器,并加載bean到應(yīng)用上下文load(context, sources.toArray(new Object[0]));//發(fā)布contextLoaded事件listeners.contextLoaded(context);}
refreshContext()
//刷新應(yīng)用上下文,注冊(cè)關(guān)閉應(yīng)用鉤子private void refreshContext(ConfigurableApplicationContext context) {refresh(context);if (this.registerShutdownHook) context.registerShutdownHook();}
/*** 抽象父類ApplicationContext*/
public abstract class AbstractApplicationContext extends DefaultResourceLoaderimplements ConfigurableApplicationContext {@Overridepublic void refresh() throws BeansException, IllegalStateException {synchronized (this.startupShutdownMonitor) {//清空緩存、清空監(jiān)聽器、判斷必要屬性是否被忽略、打印日志、初始化占位符、設(shè)置earlyApplicationEventsprepareRefresh();//獲取并刷新beanFactoryConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();/*配置classLoader為當(dāng)前context的classLoader設(shè)置BeanExpressionResolver, 解析EL表達(dá)式設(shè)置屬性編輯器添加BeanPostProcessor配置自動(dòng)裝配手工注冊(cè)environment相關(guān)bean*/prepareBeanFactory(beanFactory);/*注冊(cè)basepackages注冊(cè)annotatedClasses注冊(cè)了request和session兩個(gè)scopes注冊(cè)幾個(gè)Autowired依賴類 */postProcessBeanFactory(beanFactory);/*BeanFactoryPostProcessor接口用于增強(qiáng)BeanFactory,Spring IoC 容器允許 BeanFactoryPostProcessor 在容器實(shí)例化任何 bean 之前讀取bean 的定義,并可以修改它。例如:public static void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory, List<BeanFactoryPostProcessor> beanFactoryPostProcessors) */invokeBeanFactoryPostProcessors(beanFactory);//beanFactory注冊(cè)后置處理器,對(duì)bean實(shí)例的增強(qiáng)registerBeanPostProcessors(beanFactory);//初始化messageSourceinitMessageSource();//初始化Application事件發(fā)布器initApplicationEventMulticaster();//初始化其他特殊的bean,例如實(shí)例化了TomcatWebServeronRefresh();//注冊(cè)監(jiān)聽器registerListeners();//完成beanFactory初始化finishBeanFactoryInitialization(beanFactory);//完成刷新,發(fā)布完成事件,實(shí)例化了所有beanfinishRefresh();} }
}
public abstract class AbstractApplicationContext extends DefaultResourceLoaderimplements ConfigurableApplicationContext {protected void prepareRefresh() {//記錄開始時(shí)間,調(diào)整active狀態(tài)this.startupDate = System.currentTimeMillis();this.closed.set(false);this.active.set(true);//初始化占位符,例如:$,#,{}initPropertySources();//如果屬性中缺少requiredProperties,那么拋出MissingRequiredPropertiesExceptiongetEnvironment().validateRequiredProperties();//清空監(jiān)聽器if (this.earlyApplicationListeners == null) {this.earlyApplicationListeners = new LinkedHashSet<>(this.applicationListeners);}else {this.applicationListeners.clear();this.applicationListeners.addAll(this.earlyApplicationListeners);}//初始化earlyApplicationEventsthis.earlyApplicationEvents = new LinkedHashSet<>();}
}
refreshContext().refresh().obtainFreshBeanFactory()
/*refreshBeanFactory():創(chuàng)建beanFactory、指定序列化Id、定制beanFactory、加載bean定義getBeanFactory():返回beanFactory實(shí)例
*/
protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {//1.初始化beanFactory,并執(zhí)行加載和解析配置操作refreshBeanFactory();//返回beanFactory實(shí)例ConfigurableListableBeanFactory beanFactory = getBeanFactory();if (logger.isDebugEnabled()) {logger.debug("Bean factory for " + getDisplayName() + ": " + beanFactory);}return beanFactory;}
public abstract class AbstractRefreshableApplicationContext extends AbstractApplicationContext {... @Overrideprotected final void refreshBeanFactory() throws BeansException {//判斷是否存在beanFactoryif (hasBeanFactory()) {// 注銷所有的單例destroyBeans();//重置beanFactorycloseBeanFactory();}try {//創(chuàng)建beanFactoryDefaultListableBeanFactory beanFactory = createBeanFactory();//指定序列化id,如果需要的話,讓這個(gè)BeanFactory從id反序列化到BeanFactory對(duì)象beanFactory.setSerializationId(getId());//定制BeanFactorycustomizeBeanFactory(beanFactory);//下載BeanDefinitions,放到BeanDefinitionsMaploadBeanDefinitions(beanFactory);synchronized (this.beanFactoryMonitor) {this.beanFactory = beanFactory;}}catch (IOException ex) {throw new ApplicationContextException("I/O error parsing bean definition source for " + getDisplayName(), ex);}}...
}
refreshContext().refresh().finishBeanFactoryInitialization(beanFactory)
/* 根據(jù)loadBeanDefinitions加載的BeanDinition到BeanDefinitionMap,再從BeanDefinitionMap拿出來BeanDefinitionMap創(chuàng)建Bean
*/
createBean(){//1. createBeanInstance通過反射機(jī)制獲取Bean的構(gòu)造方法,然后創(chuàng)建Bean。當(dāng)然,如果構(gòu)造方法需要參數(shù),就會(huì)到單例池中查找。//2. populateBean填充Bean屬性//3. 初始化1. 初始化容器信息,通過invokeAwareMethods(),喚醒各種Aware接口,獲取Bean在容器中的信息2. 初始化Bean成普通對(duì)象:通過invokeInitMethods(),執(zhí)行Bean的初始化方法,這個(gè)方法可以通過實(shí)現(xiàn)InitialzingBean接口實(shí)現(xiàn)的afterPropertiesSet方法。3. AOP操作Bean成:初始化之前和之后處理各種Bean的后置處理器,即在invokeInitMethods()之前和之后分別執(zhí)行applyBeanPostProcessorsBeforeInitialization()和applyBeanPostProcessorsAfterInitialization()//4. 注冊(cè)銷毀實(shí)現(xiàn)了銷毀接口DisposableBean,在registerDisposableBean方法注冊(cè)指定的Bean在銷毀時(shí)可以直接執(zhí)行destroy方法銷毀Bean
}addSingleton(){將上面create出來的Bean放入單例池就可以獲取和使用了
}
非常重要的類
ResourceLoader
//默認(rèn)的資源加載器
public class DefaultResourceLoader implements ResourceLoader {@Nullableprivate ClassLoader classLoader;//自定義ProtocolResolver, 用于獲取資源private final Set<ProtocolResolver> protocolResolvers = new LinkedHashSet<>(4);//private final Map<Class<?>, Map<Resource, ?>> resourceCaches = new ConcurrentHashMap<>(4);//實(shí)例化ClassLoaderpublic DefaultResourceLoader() {this.classLoader = ClassUtils.getDefaultClassLoader();}//加載資源@Overridepublic Resource getResource(String location) {Assert.notNull(location, "Location must not be null");//自定義資源加載方式for (ProtocolResolver protocolResolver : this.protocolResolvers) {//調(diào)用ProtocolResolver的resolve方法Resource resource = protocolResolver.resolve(location, this);if (resource != null) {//如果獲取到資源,立即返回return resource;}}if (location.startsWith("/")) {//先判斷是否是根目錄return getResourceByPath(location);}else if (location.startsWith(CLASSPATH_URL_PREFIX)) {//再判斷是否是classpath下的資源return new ClassPathResource(location.substring(CLASSPATH_URL_PREFIX.length()), getClassLoader());}else {try {//先當(dāng)做一個(gè)URL處理URL url = new URL(location);//先判斷是否是一個(gè)file//不是file的話,再從URL中獲取return (ResourceUtils.isFileURL(url) ? new FileUrlResource(url) : new UrlResource(url));}catch (MalformedURLException ex) {//獲取不到資源的話//當(dāng)做resource處理return getResourceByPath(location);}}}
}
總結(jié)
1. 服務(wù)構(gòu)建
- 設(shè)置primarySources:YanggxApplication.class
- 設(shè)置webType:SERVLET
- 從Spring.factories獲取初始化器
- 從Spring.factories獲取監(jiān)聽器ApplicationListener
- 設(shè)置啟動(dòng)類:YanggxApplication.class
2. 環(huán)境準(zhǔn)備
- 發(fā)布Spring啟動(dòng)事件listeners.starting()
- 封裝args參數(shù) new DefaultApplicationArguments(args);
- 配置環(huán)境并讓環(huán)境生效prepareEnvironment() & configureIgnoreBeanInfo()
- 打印Banner圖printBanner(environment)
3. 容器創(chuàng)建
- 創(chuàng)建容器createApplicationContext()
- 設(shè)置容器prepareContext()
- 刷新容器refreshContext(),這里也是填充容器,重點(diǎn)是 invokeBeanFactoryPostProcessors(beanFactory);和onRefresh()
- 執(zhí)行Runners
4. 填充容器(就是容器創(chuàng)建的refreshContext)