Spring?refresh()源碼解析
目錄
正文
public void refresh() throws BeansException, IllegalStateException {
synchronized(this.startupShutdownMonitor) {
// 1. 初始化前的預(yù)處理
this.prepareRefresh();
// 2. 刷新Bean工廠
ConfigurableListableBeanFactory beanFactory = this.obtainFreshBeanFactory();
// 3. BeanFactory的預(yù)處理配置
this.prepareBeanFactory(beanFactory);
try {
// 4. BeanFactory的后置處理
this.postProcessBeanFactory(beanFactory);
// 5. 執(zhí)行BeanFactory后置處理器
this.invokeBeanFactoryPostProcessors(beanFactory);
// 6. 注冊(cè)Bean的后置處理器
this.registerBeanPostProcessors(beanFactory);
// 7. 初始化MessageSource
this.initMessageSource();
// 8. 初始化事件派發(fā)器
this.initApplicationEventMulticaster();
// 9. 子類的多態(tài)onRefresh
this.onRefresh();
// 10. 注冊(cè)監(jiān)聽(tīng)器
this.registerListeners();
// 11. 初始化所有剩下的單例Bean
this.finishBeanFactoryInitialization(beanFactory);
// 12. 完成容器的創(chuàng)建工作
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 {
// 13. 清除緩存
this.resetCommonCaches();
}
}
}
一、prepareRefresh:初始化前的預(yù)處理
protected void prepareRefresh() {
//設(shè)置容器啟動(dòng)時(shí)間
this.startupDate = System.currentTimeMillis();
//設(shè)置容器關(guān)閉狀態(tài)為false
this.closed.set(false);
//設(shè)置容器激活狀態(tài)為true
this.active.set(true);
if (this.logger.isDebugEnabled()) {
if (this.logger.isTraceEnabled()) {
this.logger.trace("Refreshing " + this);
} else {
this.logger.debug("Refreshing " + this.getDisplayName());
}
}
//1.1初始化屬性資源
this.initPropertySources();
//1.2校驗(yàn)
this.getEnvironment().validateRequiredProperties();
this.earlyApplicationEvents = new LinkedHashSet();
}
1.1初始化屬性值
初始化方法是個(gè)模壓方法,由子類重寫
protected void initPropertySources() {
}
Web容器GenericWebApplicationContext重寫了此方法
protected void initPropertySources() {
//獲取環(huán)境信息
ConfigurableEnvironment env = getEnvironment();
//判斷是否是web配置環(huán)境
if (env instanceof ConfigurableWebEnvironment) {
((ConfigurableWebEnvironment) env).initPropertySources(this.servletContext, null);
}
}
最終由StandardServletEnvironment進(jìn)行初始化
public void initPropertySources(@Nullable ServletContext servletContext, @Nullable ServletConfig servletConfig) {
//使用web容器工具初始化
WebApplicationContextUtils.initServletPropertySources(getPropertySources(), servletContext, servletConfig);
}
把 Servlet 的一些初始化參數(shù)放入IOC容器中
public static void initServletPropertySources(MutablePropertySources sources, @Nullable ServletContext servletContext, @Nullable ServletConfig servletConfig) {
Assert.notNull(sources, "'propertySources' must not be null");
String name = "servletContextInitParams";
if (servletContext != null && sources.contains(name) && sources.get(name) instanceof StubPropertySource) {
sources.replace(name, new ServletContextPropertySource(name, servletContext));
}
name = "servletConfigInitParams";
if (servletConfig != null && sources.contains(name) && sources.get(name) instanceof StubPropertySource) {
sources.replace(name, new ServletConfigPropertySource(name, servletConfig));
}
}
1.2屬性校驗(yàn)
通過(guò)占位符解析器校驗(yàn)資源集合
public void validateRequiredProperties() throws MissingRequiredPropertiesException {
this.propertyResolver.validateRequiredProperties();
}
這里的解析器作為常量在環(huán)境被實(shí)例化時(shí)就被創(chuàng)建出來(lái)的,PropertySourcesPropertyResolver是占位符解析器,將數(shù)據(jù)源中占位符替換成目標(biāo)值

校驗(yàn)是否有需要被占位符修飾的屬性,如果有但是資源中找不到對(duì)應(yīng)屬性的key就會(huì)拋出異常
public void validateRequiredProperties() {
MissingRequiredPropertiesException ex = new MissingRequiredPropertiesException();
for (String key : this.requiredProperties) {
if (this.getProperty(key) == null) {
ex.addMissingRequiredProperty(key);
}
}
if (!ex.getMissingRequiredProperties().isEmpty()) {
throw ex;
}
}
案例: 資源文件
name=zhansan
age=${name},10
encoding=utf-8
name2=${name}
測(cè)試代碼
@Test
public void test1() throws Exception {
//省略propertySources
PropertyResolver propertyResolver = new PropertySourcesPropertyResolver(getPropertySources());
System.out.println(propertyResolver.getProperty("age"));
System.out.println(propertyResolver.getProperty("encoding"));
System.out.println(propertyResolver.resolvePlaceholders("must be encoding ${encoding}")); //輸出must be encoding gbk
}
輸出結(jié)果
10,zhansan
utf-8
must be encoding utf-8
二、obtainFreshBeanFactory:刷新Bean工廠
protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
//2.1刷新Bean工廠
refreshBeanFactory();
return getBeanFactory();
}
將容器刷新標(biāo)識(shí)改為true,并且設(shè)置了工廠序列化id
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");
}
this.beanFactory.setSerializationId(getId());
}
三、prepareBeanFactory:Bean工廠預(yù)處理
protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory) {
// 設(shè)置BeanFactory的類加載器、表達(dá)式解析器等
beanFactory.setBeanClassLoader(getClassLoader());
beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver(beanFactory.getBeanClassLoader()));
beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this, getEnvironment()));
// 3.1 添加Aware執(zhí)行器
beanFactory.addBeanPostProcessor(new ApplicationContextDProcessor(this));
beanFactory.ignoreDependencyInterface(EnvironmentAware.class);
beanFactory.ignoreDependencyInterface(EmbeddedValueResolverAware.class);
beanFactory.ignoreDependencyInterface(ResourceLoaderAware.class);
beanFactory.ignoreDependencyInterface(ApplicationEventPublisherAware.class);
beanFactory.ignoreDependencyInterface(MessageSourceAware.class);
beanFactory.ignoreDependencyInterface(ApplicationContextAware.class);
// 3.2 自動(dòng)注入的支持
beanFactory.registerResolvableDependency(BeanFactory.class, beanFactory);
beanFactory.registerResolvableDependency(ResourceLoader.class, this);
beanFactory.registerResolvableDependency(ApplicationEventPublisher.class, this);
beanFactory.registerResolvableDependency(ApplicationContext.class, this);
// 3.3 添加監(jiān)聽(tīng)器執(zhí)行器
beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(this));
// Detect a LoadTimeWeaver and prepare for weaving, if found.
if (beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {
beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));
// Set a temporary ClassLoader for type matching.
beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));
}
// Register default environment beans.
if (!beanFactory.containsLocalBean(ENVIRONMENT_BEAN_NAME)) {
beanFactory.registerSingleton(ENVIRONMENT_BEAN_NAME, getEnvironment());
}
if (!beanFactory.containsLocalBean(SYSTEM_PROPERTIES_BEAN_NAME)) {
beanFactory.registerSingleton(SYSTEM_PROPERTIES_BEAN_NAME, getEnvironment().getSystemProperties());
}
if (!beanFactory.containsLocalBean(SYSTEM_ENVIRONMENT_BEAN_NAME)) {
beanFactory.registerSingleton(SYSTEM_ENVIRONMENT_BEAN_NAME, getEnvironment().getSystemEnvironment());
}
}
3.1 ApplicationContextDProcessor:Aware執(zhí)行器
ApplicationContextDProcessor實(shí)現(xiàn)了BeanPostProcessor的postProcessBeforeInitialization接口,在所有Bean初始化前會(huì)執(zhí)行當(dāng)前方法
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
//判斷Bean是Aware的子類
if (!(bean instanceof EnvironmentAware || bean instanceof EmbeddedValueResolverAware ||
bean instanceof ResourceLoaderAware || bean instanceof ApplicationEventPublisherAware ||
bean instanceof MessageSourceAware || bean instanceof ApplicationContextAware)){
return bean;
}
AccessControlContext acc = null;
if (System.getSecurityManager() != null) {
acc = this.applicationContext.getBeanFactory().getAccessControlContext();
}
if (acc != null) {
AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
invokeAwareInterfaces(bean);
return null;
}, acc);
}
else {
//回調(diào)執(zhí)行Aware接口
invokeAwareInterfaces(bean);
}
return bean;
}
如果當(dāng)前Bean是Aware的子類,那么將Bean強(qiáng)轉(zhuǎn)成Aware類型,通過(guò)回調(diào)將信息設(shè)置到Bean中
private void invokeAwareInterfaces(Object bean) {
if (bean instanceof EnvironmentAware) {
((EnvironmentAware) bean).setEnvironment(this.applicationContext.getEnvironment());
}
if (bean instanceof EmbeddedValueResolverAware) {
((EmbeddedValueResolverAware) bean).setEmbeddedValueResolver(this.embeddedValueResolver);
}
if (bean instanceof ResourceLoaderAware) {
((ResourceLoaderAware) bean).setResourceLoader(this.applicationContext);
}
if (bean instanceof ApplicationEventPublisherAware) {
((ApplicationEventPublisherAware) bean).setApplicationEventPublisher(this.applicationContext);
}
if (bean instanceof MessageSourceAware) {
((MessageSourceAware) bean).setMessageSource(this.applicationContext);
}
if (bean instanceof ApplicationContextAware) {
((ApplicationContextAware) bean).setApplicationContext(this.applicationContext);
}
}
3.2 registerResolvableDependency:自動(dòng)注入的支持
如果過(guò)容器中有多個(gè)相同接口的實(shí)現(xiàn)類,那么在自動(dòng)注入的時(shí)候會(huì)注入注冊(cè)的實(shí)現(xiàn)類
beanFactory.registerResolvableDependency(BeanFactory.class, beanFactory); beanFactory.registerResolvableDependency(ResourceLoader.class, this); beanFactory.registerResolvableDependency(ApplicationEventPublisher.class, this); beanFactory.registerResolvableDependency(ApplicationContext.class, this);
3.3 添加監(jiān)聽(tīng)器執(zhí)行器
ApplicationListenerDetector主要作用是添加和銷毀監(jiān)聽(tīng)器,實(shí)現(xiàn)了BeanPostProcessor的postProcessAfterInitialization(Bean實(shí)例化之后)方法和DestructionAwareBeanPostProcessor的postProcessBeforeDestruction(Bean銷毀之前)方法
詳情:http://www.dhdzp.com/article/277948.htm
四、BeanFactory的后置處理
這是個(gè)模壓方法,由子類AnnotationConfigServletWebServerApplicationContext實(shí)現(xiàn)
protected void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) {
}
AnnotationConfigServletWebServerApplicationContext首先調(diào)了父類 ServletWebServerApplicationContext 的 postProcessBeanFactory 方法
protected void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) {
//4.1后置處理Bean工廠
super.postProcessBeanFactory(beanFactory);
if (this.basePackages != null && this.basePackages.length > 0) {
//basePackages為空不會(huì)執(zhí)行
this.scanner.scan(this.basePackages);
}
if (!this.annotatedClasses.isEmpty()) {
this.reader.register(ClassUtils.toClassArray(this.annotatedClasses));
}
}
4.1 后置處理bean工廠
父類ServletWebServerApplicationContext首先向Bean工廠中注入了一個(gè)執(zhí)行器
protected void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) {
//4.1.1注入執(zhí)行器
beanFactory.addBeanPostProcessor(new WebApplicationContextServletContextAwareProcessor(this));
beanFactory.ignoreDependencyInterface(ServletContextAware.class);
//4.1.2注冊(cè)作用域
registerWebApplicationScopes();
}
4.1.1 WebApplicationContextServletContextAwareProcessor
WebApplicationContextServletContextAwareProcessor繼承了ServletContextAwareProcessor
ServletContextAwareProcessor繼承了BeanPostProcessor實(shí)現(xiàn)了postProcessBeforeInitialization(Bean初始化前執(zhí)行)
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
//注入ServletContext
if (getServletContext() != null && bean instanceof ServletContextAware) {
((ServletContextAware) bean).setServletContext(getServletContext());
}
//注入ServletConfig
if (getServletConfig() != null && bean instanceof ServletConfigAware) {
((ServletConfigAware) bean).setServletConfig(getServletConfig());
}
return bean;
}
4.1.2 registerWebApplicationScopes 注冊(cè)web的應(yīng)用域
// 所在類及方法:ServletWebServerApplicationContext#registerWebApplicationScopes
private void registerWebApplicationScopes() {
ExistingWebApplicationScopes existingScopes = new ExistingWebApplicationScopes(getBeanFactory());
WebApplicationContextUtils.registerWebApplicationScopes(getBeanFactory());
existingScopes.restore();
}
ExistingWebApplicationScopes是ServletWebServerApplicationContext類中的一個(gè)靜態(tài)類
源碼如下:
public static class ExistingWebApplicationScopes {
static {
Set<String> scopes = new LinkedHashSet<>();
scopes.add(WebApplicationContext.SCOPE_REQUEST);
scopes.add(WebApplicationContext.SCOPE_SESSION);
SCOPES = Collections.unmodifiableSet(scopes);
}
// 這是構(gòu)造方法,大概就是根據(jù)SCOPES獲取beanFactory中已經(jīng)注冊(cè)的scope,然后放入scopes
// 需要注意的是,在上面的方法中,第二行才在向beanFactory中注冊(cè),也就是這時(shí)的beanFactory里面沒(méi)有request和session這兩個(gè)scop
// 所以這里就完成了beanFactory的賦值。建議打斷點(diǎn)進(jìn)去看看
public ExistingWebApplicationScopes(ConfigurableListableBeanFactory beanFactory) {
this.beanFactory = beanFactory;
for (String scopeName : SCOPES) {
Scope scope = beanFactory.getRegisteredScope(scopeName);
if (scope != null) {
this.scopes.put(scopeName, scope);
}
}
}
// 由于上面的方法并沒(méi)有值存入scopes,所以這里也就沒(méi)執(zhí)行里面的內(nèi)容
public void restore() {
this.scopes.forEach((key, value) -> {
if (logger.isInfoEnabled()) {
logger.info("Restoring user defined scope " + key);
}
this.beanFactory.registerScope(key, value);
});
}
}
WebApplicationContextUtils.registerWebApplicationScopes(),這個(gè)方法就是向beanFactory注冊(cè)web的scope了,源碼如下
public static void registerWebApplicationScopes(ConfigurableListableBeanFactory beanFactory) {
registerWebApplicationScopes(beanFactory, null);
}
public static void registerWebApplicationScopes(ConfigurableListableBeanFactory beanFactory,
@Nullable ServletContext sc) {
// 注冊(cè)作用域
beanFactory.registerScope(WebApplicationContext.SCOPE_REQUEST, new RequestScope());// 注冊(cè)request SCOP
beanFactory.registerScope(WebApplicationContext.SCOPE_SESSION, new SessionScope());// 注冊(cè)session SCOP
if (sc != null) {
ServletContextScope appScope = new ServletContextScope(sc);
beanFactory.registerScope(WebApplicationContext.SCOPE_APPLICATION, appScope); // 注冊(cè)application SCOP
// Register as ServletContext attribute, for ContextCleanupListener to detect it.
sc.setAttribute(ServletContextScope.class.getName(), appScope);
}
// 添加依賴項(xiàng)
beanFactory.registerResolvableDependency(ServletRequest.class, new RequestObjectFactory());
beanFactory.registerResolvableDependency(ServletResponse.class, new ResponseObjectFactory());
beanFactory.registerResolvableDependency(HttpSession.class, new SessionObjectFactory());
beanFactory.registerResolvableDependency(WebRequest.class, new WebRequestObjectFactory());
if (jsfPresent) {
FacesDependencyRegistrar.registerFacesDependencies(beanFactory);
}
}以上就是Spring refresh()源碼解析的詳細(xì)內(nèi)容,更多關(guān)于Spring refresh()的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
非常適合新手學(xué)生的Java線程池超詳細(xì)分析
作者是一個(gè)來(lái)自河源的大三在校生,以下筆記都是作者自學(xué)之路的一些淺薄經(jīng)驗(yàn),如有錯(cuò)誤請(qǐng)指正,將來(lái)會(huì)不斷的完善筆記,幫助更多的Java愛(ài)好者入門2022-03-03
java 實(shí)現(xiàn)音樂(lè)播放器的簡(jiǎn)單實(shí)例
這篇文章主要介紹了java 實(shí)現(xiàn)音樂(lè)播放器的簡(jiǎn)單實(shí)例的相關(guān)資料,希望通過(guò)本文能幫助到大家,實(shí)現(xiàn)這樣的功能,需要的朋友可以參考下2017-09-09
詳解在IDEA中使用MyBatis Generator逆向工程生成代碼
這篇文章主要介紹了詳解在IDEA中使用MyBatis Generator逆向工程生成代碼,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2018-06-06
MybatisX-Generator不生成domain文件夾的問(wèn)題及解決
在使用MybatisX-Generator生成數(shù)據(jù)庫(kù)表實(shí)體時(shí),如果發(fā)現(xiàn)沒(méi)有生成domain文件夾以及User.java文件,是因?yàn)镸ybatisX版本更新,最新版需要在options里額外勾選model才能生成domain,勾選model并點(diǎn)擊finish后,成功生成domain文件夾及User.java文件2025-01-01
JavaMail實(shí)現(xiàn)發(fā)送超文本(html)格式郵件的方法
這篇文章主要介紹了JavaMail實(shí)現(xiàn)發(fā)送超文本(html)格式郵件的方法,實(shí)例分析了java發(fā)送超文本文件的相關(guān)技巧,需要的朋友可以參考下2015-05-05
示例解析java面向?qū)ο缶幊谭庋b與訪問(wèn)控制
這篇文章主要為大家介紹了java封裝與訪問(wèn)控制的示例解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-05-05

