Spring原始碼註解解析day04
今天主要是來記錄一下Spring的事務控制的原理、以及BeanPostProcessor、BeanFactoryPostProcessor、BeanDefinitionRegistryPostProcessor、ApplicationListener
一、Spring的宣告式事務: 環境搭建: 1、匯入相關依賴:資料來源、資料庫驅動、Spring-jdbc模組 2、配置資料來源、JdbcTemplate(Spring提供的簡化資料庫操作的工具)操作資料 3、給方法上標註 @Transactional 表示當前方法是一個事務方法; 4、 @EnableTransactionManagement 開啟基於註解的事務管理功能; 5、配置事務管理器來控制事務; @Bean public PlatformTransactionManager transactionManager()
根據底層所使用的不同的持久化 API 或框架,使用如下:
-
DataSourceTransactionManager:適用於使用JDBC和iBatis進行資料持久化操作的情況,在定義時需要提供底層的資料來源作為其屬性,也就是 DataSource。
-
HibernateTransactionManager:適用於使用Hibernate進行資料持久化操作的情況,與 HibernateTransactionManager 對應的是 SessionFactory。
-
JpaTransactionManager:適用於使用JPA進行資料持久化操作的情況,與 JpaTransactionManager 對應的是 EntityManagerFactory。
原理:
原理: 1)、@EnableTransactionManagement 利用TransactionManagementConfigurationSelector給容器中會匯入元件 匯入兩個元件 AutoProxyRegistrar ProxyTransactionManagementConfiguration
//adviceMode預設是PROXY,所以返回的是一個swich的選項,返回一個自動代理註冊器,一個程式碼事務管理配置 @Override protected String[] selectImports(AdviceMode adviceMode) { switch (adviceMode) { case PROXY: return new String[] {AutoProxyRegistrar.class.getName(), ProxyTransactionManagementConfiguration.class.getName()}; case ASPECTJ: return new String[] {TransactionManagementConfigUtils.TRANSACTION_ASPECT_CONFIGURATION_CLASS_NAME}; default: return null; } }
2)、AutoProxyRegistrar: 給容器中註冊一個 InfrastructureAdvisorAutoProxyCreator 元件; InfrastructureAdvisorAutoProxyCreator:? 利用後置處理器機制在物件建立以後,包裝物件,返回一個代理物件(增強器),代理物件執行方法利用攔截器鏈進 行呼叫;
3)、ProxyTransactionManagementConfiguration 做了什麼? 1、給容器中註冊事務增強器; 1)、事務增強器要用事務註解的資訊,AnnotationTransactionAttributeSource解析事務註解 2)、事務攔截器: TransactionInterceptor;儲存了事務屬性資訊,事務管理器; 他是一個 MethodInterceptor; 在目標方法執行的時候; 執行攔截器鏈; 事務攔截器: 1)、先獲取事務相關的屬性 2)、再獲取PlatformTransactionManager,如果事先沒有新增指定任何transactionmanger 最終會從容器中按照型別獲取一個PlatformTransactionManager; 3)、執行目標方法 如果異常,獲取到事務管理器,利用事務管理回滾操作; 如果正常,利用事務管理器,提交事務
事務的相關屬性有哪些呢?
我這裡就不寫了,給個連結吧,我覺得寫得很好,很生動。
二、
BeanPostProcessor:bean後置處理器,bean建立物件初始化前後進行攔截工作的 1、BeanFactoryPostProcessor:beanFactory的後置處理器; 在BeanFactory標準初始化之後呼叫,來定製和修改BeanFactory的內容; 所有的bean定義已經儲存載入到beanFactory,但是bean的例項還未建立 BeanFactoryPostProcessor原理: 1)、ioc容器建立物件 2)、invokeBeanFactoryPostProcessors(beanFactory); 如何找到所有的BeanFactoryPostProcessor並執行他們的方法; 1)、直接在BeanFactory中找到所有型別是BeanFactoryPostProcessor的元件,並執行他們的方法 2)、在初始化建立其他元件前面執行 2、BeanDefinitionRegistryPostProcessor extends BeanFactoryPostProcessor postProcessBeanDefinitionRegistry(); 在所有bean定義資訊將要被載入,bean例項還未建立的; 優先於BeanFactoryPostProcessor執行; 利用BeanDefinitionRegistryPostProcessor給容器中再額外新增一些元件; 原理: 1)、ioc建立物件 2)、refresh()-》invokeBeanFactoryPostProcessors(beanFactory); 3)、從容器中獲取到所有的BeanDefinitionRegistryPostProcessor元件。 1、依次觸發所有的postProcessBeanDefinitionRegistry()方法 2、再來觸發postProcessBeanFactory()方法BeanFactoryPostProcessor; 4)、再來從容器中找到BeanFactoryPostProcessor元件;然後依次觸發postProcessBeanFactory()方法 3、ApplicationListener:監聽容器中釋出的事件。事件驅動模型開發; public interface ApplicationListener<E extends ApplicationEvent> 監聽 ApplicationEvent 及其下面的子事件; 步驟: 1)、寫一個監聽器(ApplicationListener實現類)來監聽某個事件(ApplicationEvent及其子類) @EventListener; 原理:使用EventListenerMethodProcessor處理器來解析方法上的@EventListener; 2)、把監聽器加入到容器; 3)、只要容器中有相關事件的釋出,我們就能監聽到這個事件; ContextRefreshedEvent:容器重新整理完成(所有bean都完全建立)會發布這個事件; ContextClosedEvent:關閉容器會發布這個事件; 4)、釋出一個事件: applicationContext.publishEvent(); 原理: ContextRefreshedEvent、IOCTest_Ext$1[source=我釋出的時間]、ContextClosedEvent; 1)、ContextRefreshedEvent事件: 1)、容器建立物件:refresh(); 2)、finishRefresh();容器重新整理完成會發布ContextRefreshedEvent事件 2)、自己釋出事件; 3)、容器關閉會發布ContextClosedEvent; 【事件釋出流程】: 3)、publishEvent(new ContextRefreshedEvent(this)); 1)、獲取事件的多播器(派發器):getApplicationEventMulticaster() 2)、multicastEvent派發事件: 3)、獲取到所有的ApplicationListener; for (final ApplicationListener<?> listener : getApplicationListeners(event, type)) { 1)、如果有Executor,可以支援使用Executor進行非同步派發; Executor executor = getTaskExecutor(); 2)、否則,同步的方式直接執行listener方法;invokeListener(listener, event); 拿到listener回撥onApplicationEvent方法; 【事件多播器(派發器)】 1)、容器建立物件:refresh(); 2)、initApplicationEventMulticaster();初始化ApplicationEventMulticaster; 1)、先去容器中找有沒有id=“applicationEventMulticaster”的元件; 2)、如果沒有this.applicationEventMulticaster = new SimpleApplicationEventMulticaster(beanFactory); 並且加入到容器中,我們就可以在其他元件要派發事件,自動注入這個applicationEventMulticaster; 【容器中有哪些監聽器】 1)、容器建立物件:refresh(); 2)、registerListeners(); 從容器中拿到所有的監聽器,把他們註冊到applicationEventMulticaster中; String[] listenerBeanNames = getBeanNamesForType(ApplicationListener.class, true, false); //將listener註冊到ApplicationEventMulticaster中 getApplicationEventMulticaster().addApplicationListenerBean(listenerBeanName); SmartInitializingSingleton 原理:->afterSingletonsInstantiated(); 1)、ioc容器建立物件並refresh(); 2)、finishBeanFactoryInitialization(beanFactory);初始化剩下的單例項bean; 1)、先建立所有的單例項bean;getBean(); 2)、獲取所有建立好的單例項bean,判斷是否是SmartInitializingSingleton型別的; 如果是就呼叫afterSingletonsInstantiated();