spring學習(三)ConfigurableApplicationContext的refresh方法
spring在載入bean的時候,執行的主要方法就是ConfigurableApplicationContext的refresh方法。這個方法在實現類AbstractApplicationContext裡做了處理,這裡就簡單說明一下這個處理方法,下圖是我簡單畫的類關係圖
這個是類AbstractApplicationContext實現的程式碼,以下對每個執行進行說明
public void refresh() throws BeansException, IllegalStateException { synchronized (this.startupShutdownMonitor) { // Prepare this context for refreshing. prepareRefresh(); // Tell the subclass to refresh the internal bean factory. ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory(); // Prepare the bean factory for use in this context. prepareBeanFactory(beanFactory); try { // Allows post-processing of the bean factory in context subclasses. postProcessBeanFactory(beanFactory); // Invoke factory processors registered as beans in the context. invokeBeanFactoryPostProcessors(beanFactory); // Register bean processors that intercept bean creation. registerBeanPostProcessors(beanFactory); // Initialize message source for this context. initMessageSource(); // Initialize event multicaster for this context. initApplicationEventMulticaster(); // Initialize other special beans in specific context subclasses. onRefresh(); // Check for listener beans and register them. registerListeners(); // Instantiate all remaining (non-lazy-init) singletons. finishBeanFactoryInitialization(beanFactory); // Last step: publish corresponding event. finishRefresh(); } catch (BeansException ex) { // Destroy already created singletons to avoid dangling resources. destroyBeans(); // Reset 'active' flag. cancelRefresh(ex); // Propagate exception to caller. throw ex; } } }
一、prepareRefresh
此方法主要記錄一下開始初始化的時候或active的標記,並對一些properties進行初始化
initPropertySources();//子類實現
getEnvironment().validateRequiredProperties();//如果沒有設定Environment取預設的實現StandardEnvironment
二、ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory()
protected ConfigurableListableBeanFactory obtainFreshBeanFactory() { refreshBeanFactory(); ConfigurableListableBeanFactory beanFactory = getBeanFactory(); if (logger.isDebugEnabled()) { logger.debug("Bean factory for " + getDisplayName() + ": " + beanFactory); } return beanFactory; }
此方法全部由子類實現,
在AbstractRefreshApplicationContext實現了refreshBeanFactory方法,此方法最主要的就是loadBeanDefinitions(beanFactory),由子類去實現load所有的beanDefinition,下一次將具體說明這個方法
//建立一個預設的BeanFactory。使用了DefaultListableBeanFactory@Override protected final void refreshBeanFactory() throws BeansException { if (hasBeanFactory()) { destroyBeans(); closeBeanFactory(); } try { DefaultListableBeanFactory beanFactory = createBeanFactory(); beanFactory.setSerializationId(getId()); customizeBeanFactory(beanFactory); loadBeanDefinitions(beanFactory); synchronized (this.beanFactoryMonitor) { this.beanFactory = beanFactory; } } catch (IOException ex) { throw new ApplicationContextException("I/O error parsing bean definition source for " + getDisplayName(), ex); } }
protected DefaultListableBeanFactory createBeanFactory() {
return new DefaultListableBeanFactory(getInternalParentBeanFactory());
}
@Override
public final ConfigurableListableBeanFactory getBeanFactory() {
synchronized (this.beanFactoryMonitor) {
if (this.beanFactory == null) {
throw new IllegalStateException("BeanFactory not initialized or already closed - " +
"call 'refresh' before accessing beans via the ApplicationContext");
}
return this.beanFactory;
}
}
三、prepareBeanFactory(beanFactory);
預處理beanFactory容器,配置一些beanFactory的classLoader和post-processor等
protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory) {
// Tell the internal bean factory to use the context's class loader etc.
beanFactory.setBeanClassLoader(getClassLoader());
beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver());
beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this, getEnvironment()));
// Configure the bean factory with context callbacks.
beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));
beanFactory.ignoreDependencyInterface(ResourceLoaderAware.class);
beanFactory.ignoreDependencyInterface(ApplicationEventPublisherAware.class);
beanFactory.ignoreDependencyInterface(MessageSourceAware.class);
beanFactory.ignoreDependencyInterface(ApplicationContextAware.class);
beanFactory.ignoreDependencyInterface(EnvironmentAware.class);
// BeanFactory interface not registered as resolvable type in a plain factory.
// MessageSource registered (and found for autowiring) as a bean.
beanFactory.registerResolvableDependency(BeanFactory.class, beanFactory);
beanFactory.registerResolvableDependency(ResourceLoader.class, this);
beanFactory.registerResolvableDependency(ApplicationEventPublisher.class, this);
beanFactory.registerResolvableDependency(ApplicationContext.class, 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());
}
}
四、postProcessBeanFactory(beanFactory);
此方法由子類執行beanFactory 之前的操作
五、invokeBeanFactoryPostProcessors(beanFactory);
用於執行BeanFactoryPostProcessors中的postProcessBeanFactory,beanFactoryPostProcessor是優先於BeanPostProcessor執行
先執行BeanDefinitionRegistryPostProcessor的postProcessBeanDefinitionRegistry。再執行BeanFactoryPostProcessor.postProcessBeanFactory小例子,此時在載入spring容器時,會打印出當前的Singlecount,注。此時還沒有載入指定的業務bean.除非呼叫getBean(beanName),否則要等到後一步才載入執行
public class TestBeanFactoryPostProcessor implements BeanFactoryPostProcessor {
@Override
public void postProcessBeanFactory(
ConfigurableListableBeanFactory beanFactory) throws BeansException {
System.out.println(" signleton count :" + beanFactory.getSingletonCount());
}
}
mybatis與spring整合時,就是配置了一個BeanDefinitionRegistryPostProcessor。並在postProcessBeanDefinitionRegistry這個方法裡進行查詢mybatis所有配置的mapper
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<property name="basePackage" value="com.dld.app.shop"/>
<property name="sqlSessionFactory" ref="sqlSessionFactoryShop"></property>
</bean>
public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
if (this.processPropertyPlaceHolders) {
processPropertyPlaceHolders();
}
ClassPathMapperScanner scanner = new ClassPathMapperScanner(registry);
scanner.setAddToConfig(this.addToConfig);
scanner.setAnnotationClass(this.annotationClass);
scanner.setMarkerInterface(this.markerInterface);
scanner.setSqlSessionFactory(this.sqlSessionFactory);
scanner.setSqlSessionTemplate(this.sqlSessionTemplate);
scanner.setSqlSessionFactoryBeanName(this.sqlSessionFactoryBeanName);
scanner.setSqlSessionTemplateBeanName(this.sqlSessionTemplateBeanName);
scanner.setResourceLoader(this.applicationContext);
scanner.setBeanNameGenerator(this.nameGenerator);
scanner.registerFilters();
scanner.scan(StringUtils.tokenizeToStringArray(this.basePackage, ConfigurableApplicationContext.CONFIG_LOCATION_DELIMITERS));
}
六、registerBeanPostProcessors(beanFactory);
註冊beanPostProcessor,注意要和beanFactoryPostProcessor區分開,beanFactoryPostProcessor是執行。此時的這裡只是註冊beanPostProcessor,beanFactoryPostProcessor優先於beanPostProcessor執行
beanPostProcessor的流程與beanFactoryPostProcessor執行流程類似。
1、先查詢所有BeanPostProcessor型別的bean
2、註冊屬於PriorityOrdered的beanPostProcessor
3、註冊屬於Ordered型別的beanPostProcessor
4、註冊剩餘的beanPostProcessor
5、增加一個繼承了ApplicationListener的beanPostProcessor檢查ApplicationListenerDetector
public class TestBeanPostProcessor implements BeanPostProcessor {
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName)
throws BeansException {
System.out.println("before beanName [" + beanName + "] bean class [" + bean.getClass() + "]");
return bean;
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName)
throws BeansException {
System.out.println("after beanName [" + beanName + "] bean class [" + bean.getClass() + "]");
return bean;
}
}
七、initMessageSource();
初始化一個messageSource類
1、判斷beanFactory是否有name=messageSource的MessageSource
2、生成一個預設的MessageSource DelegatingMessageSource並註冊到beanFactory中
八、initApplicationEventMulticaster();
初始化ApplicationEvent類
1、判斷beanFactory是否有name =applicationEventMulticaster的ApplicationEventMulticaster
2、生成預設的SimpleApplicationEventMulticaster 並註冊到beanFactory中
九、onRefresh();
此方法由子類實現
十、registerListeners();
載入所以ApplicationListener並註冊到ApplicationEventMulticaster中
十一、finishBeanFactoryInitialization(beanFactory);
處理beanFactory初始化結束的操作
其中
beanFactory.preInstantiateSingletons();
開始例項化所有未例項化的bean
十二、finishRefresh()
protected void finishRefresh() {
// Initialize lifecycle processor for this context.
initLifecycleProcessor();
// Propagate refresh to lifecycle processor first.
getLifecycleProcessor().onRefresh();
// Publish the final event.
publishEvent(new ContextRefreshedEvent(this));
// Participate in LiveBeansView MBean, if active.
LiveBeansView.registerApplicationContext(this);
}
1、生成一個LifecycleProcessor.預設為DefaultLifecycleProcessor
2、執行LiftcycleProcessor的onfresh方法,執行所有屬於Lifecycle的bean
3、推送ApplicationEvent
相關推薦
spring學習(三)ConfigurableApplicationContext的refresh方法
spring在載入bean的時候,執行的主要方法就是ConfigurableApplicationContext的refresh方法。這個方法在實現類AbstractApplicationContext裡做了處理,這裡就簡單說明一下這個處理方法,下圖是我簡單畫的類關係圖
Spring學習(三)| Spring AOP
文章目錄 1. 什麼是 AOP ? 2. 為什麼需要使用 AOP ? 3. AOP 術語 4. 在 Spring 中使用 Aspect 註解方式進行切面程式設計 4.1 在 Spring 中啟用 AspectJ 註解支援 4.2
Spring 學習(三)——Spring 中的 Bean 配置
配置形式:基於 XML 檔案的方式;基於註解的方式 Bean 的配置方式:通過全類名(反射)、通過工廠方法(靜態工廠方法 & 例項工廠方法)、FactoryBean IOC 容器 BeanFactory & ApplicationContext 概述 依賴注入
Spring學習(三)
(一)Spring基於AspectJ的註解的AOP開發 (1)建立專案 引入jar包 編寫目標類,切面類,在Spring中進行bean配置 (2)在配置檔案中開啟註解的AOP開發 (3)切面類AOP配置 注意要在類上打Aspect註解 前置通知 後置通知
Spring學習(三)IOC控制反轉與DI依賴注入
IOC(Inversion of Control,控制反轉)是spring的核心,貫穿始終。 所謂IOC,對於spring框架來說,就是由spring來負責控制物件的生命週期和物件間的關係: 傳統開發
Spring極簡學習(三)例項化Bean的方法有兩種
其實例項化一個Bean並沒有那麼複雜,不就是將new Bean()的過程放到Spring這裡來實現了嗎? 其實的確如此,當然了,之前的設計模式中的例項化Bean的方式Spring也得支援支援吧。 一、最直觀例項化(反射模式) xml配置 <bean id="car1
Spring Boot學習(三)
src pack art tin pre size -s script jar Spring boot實戰 —— Hello Word 1、創建maven項目 2、pom.xml文件 <?xml version="1.0" encoding="UTF-8"?>
Spring MVC學習(三)
新建一個web project專案 嚴重: Context initialization failed org.springframework.beans.factory.BeanDefinitionStoreException: IOException parsing XML docum
SpringBoot學習(三)--構建RESTFUL API並用spring-data-jpa進行儲存&&使用IDEA反向生成帶註釋的例項
構造User物件(/domain),如果有資料庫的表可以直接使用IDEA反向生成例項的類。過程如下: 開啟IDEA:View-ToolWindows-Database。新增資料來源,選擇資料庫型別,輸入資料庫的ip。如果不是預設Windows登陸資料庫,則取消勾選然後填入使用者名稱,密碼。
SSH框架學習(三)——struts整合spring
SSH框架學習(三)——struts整合spring 建立包結構 struts整合spring 建立提交頁面 編寫domain 編寫dao 編寫service 編寫action 配置applicationCo
Spring的學習(三):面向切面的Spring
介紹 如果要重用功能的話,最常見的面向物件技術是繼承或者委託。但是,如果在整個應用中都使用相同的基類,繼承往往會導致一個脆弱的物件體系;而使用委託可能需要對委託物件進行復雜的呼叫。 切面提供了取代繼承和委託的另一種可選方案,而且在很多場景下更清晰簡潔。在使用切面
Spring Cloud學習(三)Feign簡單使用
前面瞭解瞭如何通過RestTemplate+Ribbon去消費服務,這裡講述如何通過Feign去消費服務。 Feign是一個宣告式的偽Http客戶端,它使得寫Http客戶端變得更簡單。使用Feign,只需要建立一個介面並註解。它具有可插拔的註解特性,可
Spring 學習(十)——通過工廠方法(靜態工廠方法 & 例項工廠方法)配置 bean
通過呼叫靜態工廠方法建立 Bean •呼叫靜態工廠方法建立 Bean是將物件建立的過程封裝到靜態方法中. 當客戶端需要物件時, 只需要簡單地呼叫靜態方法, 而不同關心建立物件的細節. •要宣告通過靜態方法建立的 Bean, 需要在 Bean 的 class 屬性裡指定擁有該
spring深入學習(三)IOC 之 載入 Bean
先看一段熟悉的程式碼: ClassPathResource resource = new ClassPathResource("bean.xml"); DefaultListableBeanFactory factory = new DefaultListableBeanF
SpringBoot學習(三),兩種啟動方式-以main方法啟動和在tomcat裡啟動
sprigboot既可以直接通過main方法啟動,也可以在tomcat裡啟動,在main方法裡啟動很簡單,直接run啟動類的main方法就可以了。 在tomcat裡啟動
laravel框架學習(三)win下php artisan tinker 測試資料時,無法執行報錯的解決方法
問題描述: 複製該路徑,在資源管理器的位址列中開啟,會看到 如下: Temp 往往是系統或者其他軟體生成的快取檔案或目錄 需要返回到上一級目錄Temp中,全選資料夾,刪除,提示不允許刪除的話,
Spring Boot 構建企業級部落格學習(三)
ide外掛的安裝配置、專案執行 安裝、配置ide 常用外掛安裝、配置 匯入專案到ide 啟動gradle的方式 eclipse環境配置 jdk配置 在eslipse中window-preferences-java裡配置jdk 安裝gradle
Spring Cloud微學習(三)Eureka應用——服務間通訊
微服務可以在“自己的程式”中執行,並通過“輕量級裝置與HTTP型API進行溝通”。這裡的溝通就是本節要說的服務間通訊。即各個微服務註冊到Eureka服務註冊中心,這些微服務之間的通訊 建立服務提供者 啟動上一節 Eureka入門——叢集的服務內容
小菜學習設計模式(三)—工廠方法(Factory Method)模式
前言 設計模式目錄: 本篇目錄: 其實大家都知道,在工廠方法(Factory Method)模式之前有個簡單工廠模式,也就是靜態工廠方法(Static Factory Method)模式,在簡單工廠模式之前有個我們都熟悉的三層架構模式,那我們就上到下一層一層的來了解下。 三層架構 三
Spring Boot學習(三):定時任務
一、簡介 專案中經常會遇到使用定時任務的情況,那麼SpringBoot如何實現這種需求呢,還是簡潔到要命。 二、環境準備 eclipse + maven + Spring Boot 三、程式碼示例 pom.xml檔案不用特殊引入依賴包,保持一般初始化就可以,如下