深入理解Spring原始碼之IOC 擴充套件原理BeanFactoryPostProcessor和事件監聽ApplicationListener
2.BeanFactoryPostProcessor
一個好的框架必備的特性至少得有開閉原則,可擴充套件性BeanFactoryPostProcessor
也是Spring可擴充套件性的一個體現,我們讀一下這個介面的原始碼
public interface BeanFactoryPostProcessor {
/**
* Modify the application context's internal bean factory after its standard
* initialization. All bean definitions will have been loaded, but no beans
* will have been instantiated yet. This allows for overriding or adding
* properties even to eager-initializing beans.
* @param beanFactory the bean factory used by the application context
* @throws org.springframework.beans.BeansException in case of errors
*/
void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException;
}
允許我們在工廠裡所有的bean被載入進來後但是還沒初始化前,對所有bean的屬性進行修改也可以add屬性值。
bean工廠後置處理器—>構造方法—>init-method。
3、ApplicationListener
3.1、測試程式碼:
package com.atguigu.ext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import com.atguigu.bean.Blue;
@ComponentScan("com.atguigu.ext")
@Configuration
public class ExtConfig {
@Bean
public Blue blue(){
return new Blue();
}
}
import org.junit.Test;
import org.springframework.context.ApplicationEvent;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import com.atguigu.ext.ExtConfig;
public class IOCTest_Ext {
@Test
public void test01(){
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(ExtConfig.class);
//釋出事件;
applicationContext.publishEvent(new ApplicationEvent(new String("我釋出的時間")) {
});
applicationContext.close();
}
}
3.2、ApplicationListener的應用
ApplicationListener:監聽容器中釋出的事件。事件驅動模型開發;
public interface ApplicationListener<E extends ApplicationEvent>
監聽 ApplicationEvent 及其下面的子事件;
步驟:
1)、寫一個監聽器(ApplicationListener實現類)來監聽某個事件(ApplicationEvent及其子類)
@EventListener;
原理:使用EventListenerMethodProcessor處理器來解析方法上的@EventListener;
2)、把監聽器加入到容器;
3)、只要容器中有相關事件的釋出,我們就能監聽到這個事件;
ContextRefreshedEvent:容器重新整理完成(所有bean都完全建立)會發布這個事件;
ContextClosedEvent:關閉容器會發布這個事件;
4)、釋出一個事件:
applicationContext.publishEvent();
3.3、ApplicationListener的原理
【事件釋出流程】:
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方法;
註解:為了便於理解下面只保留了最核心的原始碼,只在關鍵的呼叫地方打中文註釋
public abstract class AbstractApplicationContext extends DefaultResourceLoader
implements ConfigurableApplicationContext, DisposableBean {
@Override
public void publishEvent(ApplicationEvent event) {
publishEvent(event, null);
}
protected void publishEvent(Object event, ResolvableType eventType) {
ApplicationEvent applicationEvent;
if (event instanceof ApplicationEvent) {
applicationEvent = (ApplicationEvent) event;
}
else {
applicationEvent = new PayloadApplicationEvent<Object>(this, event);
if (eventType == null) {
eventType = ((PayloadApplicationEvent)applicationEvent).getResolvableType();
}
}
if (this.earlyApplicationEvents != null) {
this.earlyApplicationEvents.add(applicationEvent);
}
else {
getApplicationEventMulticaster().multicastEvent(applicationEvent, eventType);
}
}
}
public class SimpleApplicationEventMulticaster extends AbstractApplicationEventMulticaster {
private Executor taskExecutor;
private ErrorHandler errorHandler;
@Override
public void multicastEvent(ApplicationEvent event) {
multicastEvent(event, resolveDefaultEventType(event));
}
@Override
public void multicastEvent(final ApplicationEvent event, ResolvableType eventType) {
ResolvableType type = (eventType != null ? eventType : resolveDefaultEventType(event));
for (final ApplicationListener<?> listener : getApplicationListeners(event, type)) {
Executor executor = getTaskExecutor();
if (executor != null) {
executor.execute(new Runnable() {
@Override
public void run() {
invokeListener(listener, event);
}
});
}
else {
invokeListener(listener, event);
}
}
}
}
3.4、 @EventListener
3.4.1、基於註解的方式建立監聽器:
import org.springframework.context.ApplicationEvent;
import org.springframework.context.event.EventListener;
import org.springframework.stereotype.Service;
@Service
public class UserInfoService {
@EventListener(classes={ApplicationEvent.class})
public void listen(ApplicationEvent event){
System.out.println("UserService。。監聽到的事件:"+event);
}
}
3.4.2 @EventListener註解原理
原理:使用EventListenerMethodProcessor處理器來解析方法上的@EventListener;
再看SmartInitializingSingleton 這個類的原理即可
public class EventListenerMethodProcessor implements SmartInitializingSingleton, ApplicationContextAware
SmartInitializingSingleton 原理:->執行這個方法afterSingletonsInstantiated();
afterSingletonsInstantiated();是在所有bean初始化完成之後呼叫的,
斷點在EventListenerMethodProcessor.afterSingletonsInstantiated()方法上檢視執行流程
1)、ioc容器建立物件並refresh();
2)、finishBeanFactoryInitialization(beanFactory);初始化剩下的單例項bean;
1)、DefaultListableBeanFactory.preInstantiateSingletons()->先建立所有的單例項bean;getBean();
2)、獲取所有建立好的單例項bean,判斷是否是SmartInitializingSingleton型別的;如果是就呼叫afterSingletonsInstantiated();
public abstract class AbstractApplicationContext extends DefaultResourceLoader
implements ConfigurableApplicationContext, DisposableBean {
//ioc容器建立物件並refresh();
@Override
public void refresh() throws BeansException, IllegalStateException {
synchronized (this.startupShutdownMonitor) {
prepareRefresh();
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
prepareBeanFactory(beanFactory);
try {
postProcessBeanFactory(beanFactory);
invokeBeanFactoryPostProcessors(beanFactory);
registerBeanPostProcessors(beanFactory);
initMessageSource();
initApplicationEventMulticaster();
onRefresh();
registerListeners();
// 初始化剩下的單例項bean
finishBeanFactoryInitialization(beanFactory);
finishRefresh();
}
catch (BeansException ex) {
destroyBeans();
cancelRefresh(ex);
throw ex;
}
finally {
resetCommonCaches();
}
}
}
}
public abstract class AbstractApplicationContext extends DefaultResourceLoader
implements ConfigurableApplicationContext, DisposableBean {
protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {
if (beanFactory.containsBean(CONVERSION_SERVICE_BEAN_NAME) &&
beanFactory.isTypeMatch(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class)) {
beanFactory.setConversionService(
beanFactory.getBean(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class));
}
if (!beanFactory.hasEmbeddedValueResolver()) {
beanFactory.addEmbeddedValueResolver(new StringValueResolver() {
@Override
public String resolveStringValue(String strVal) {
return getEnvironment().resolvePlaceholders(strVal);
}
});
}
String[] weaverAwareNames = beanFactory.getBeanNamesForType(LoadTimeWeaverAware.class, false, false);
for (String weaverAwareName : weaverAwareNames) {
getBean(weaverAwareName);
}
beanFactory.setTempClassLoader(null);
beanFactory.freezeConfiguration();
//先建立所有的單例項bean
beanFactory.preInstantiateSingletons();
}
}
@SuppressWarnings("serial")
public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFactory
implements ConfigurableListableBeanFactory, BeanDefinitionRegistry, Serializable {
@Override
public void preInstantiateSingletons() throws BeansException {
if (this.logger.isDebugEnabled()) {
this.logger.debug("Pre-instantiating singletons in " + this);
}
List<String> beanNames = new ArrayList<String>(this.beanDefinitionNames);
for (String beanName : beanNames) {
RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
if (isFactoryBean(beanName)) {
final FactoryBean<?> factory = (FactoryBean<?>) getBean(FACTORY_BEAN_PREFIX + beanName);
boolean isEagerInit;
if (System.getSecurityManager() != null && factory instanceof SmartFactoryBean) {
isEagerInit = AccessController.doPrivileged(new PrivilegedAction<Boolean>() {
@Override
public Boolean run() {
return ((SmartFactoryBean<?>) factory).isEagerInit();
}
}, getAccessControlContext());
}
else {
isEagerInit = (factory instanceof SmartFactoryBean &&
((SmartFactoryBean<?>) factory).isEagerInit());
}
if (isEagerInit) {
getBean(beanName);
}
}
else {
getBean(beanName);
}
}
}
for (String beanName : beanNames) {
Object singletonInstance = getSingleton(beanName);
//獲取所有建立好的單例項bean,判斷是否是SmartInitializingSingleton型別的;
if (singletonInstance instanceof SmartInitializingSingleton) {
final SmartInitializingSingleton smartSingleton = (SmartInitializingSingleton) singletonInstance;
if (System.getSecurityManager() != null) {
AccessController.doPrivileged(new PrivilegedAction<Object>() {
@Override
public Object run() {
smartSingleton.afterSingletonsInstantiated();
return null;
}
}, getAccessControlContext());
}
else {
//如果是就呼叫afterSingletonsInstantiated();
smartSingleton.afterSingletonsInstantiated();
}
}
}
}
}
待續。。。
相關文章
- 深入理解Spring IOC容器及擴充套件Spring套件
- Spring擴充套件之二:ApplicationListenerSpring套件APP
- 聊聊Spring擴充套件點BeanPostProcessor和BeanFactoryPostProcessorSpring套件Bean
- Spring IoC 容器的擴充套件Spring套件
- 深入理解Spring IOC原始碼分析Spring原始碼
- Spring原始碼之容器的功能擴充套件和refresh方法解析Spring原始碼套件
- 【spring原始碼學習】spring的IOC容器之BeanFactoryPostProcessor介面學習Spring原始碼Bean
- PHP原始碼系列之擴充套件的原理與開發PHP原始碼套件
- Spring事件監聽機制原始碼解析Spring事件原始碼
- 【spring原始碼學習】spring的IOC容器之自定義xml配置標籤擴充套件namspaceHandler向IOC容器中註冊beanSpring原始碼XML套件Bean
- Spring原始碼解析之BeanFactoryPostProcessor(三)Spring原始碼Bean
- Spring原始碼解析之BeanFactoryPostProcessor(一)Spring原始碼Bean
- Spring原始碼解析之BeanFactoryPostProcessor(二)Spring原始碼Bean
- 深入理解Spring 之 Spring 進階開發必知必會 之 Spring 擴充套件介面Spring套件
- 深入原始碼理解Spring整合MyBatis原理原始碼SpringMyBatis
- spring4.1.8擴充套件實戰之五:改變bean的定義(BeanFactoryPostProcessor介面)Spring套件Bean
- spring4.1.8擴充套件實戰之三:廣播與監聽Spring套件
- Spring Boot 事件和監聽Spring Boot事件
- Spring5原始碼解析-Spring框架中的事件和監聽器Spring原始碼框架事件
- 「Android」分析EventBus原始碼擴充套件Weex事件機制Android原始碼套件事件
- Spring原始碼分析-BeanFactoryPostProcessorSpring原始碼Bean
- Spring IOC(6)BeanFactoryPostProcessor(3)摻雜@MapperScan原理分析SpringBeanAPP
- Spring原始碼分析之`BeanFactoryPostProcessor`呼叫過程Spring原始碼Bean
- 深入理解ES6 ---- 正則擴充套件套件
- Spring 事件監聽機制及原理分析Spring事件
- COLA的擴充套件性使用和原始碼研究套件原始碼
- 原始碼安裝memcached和php memcache擴充套件原始碼PHP套件
- Spring:原始碼解讀Spring IOC原理Spring原始碼
- 深入理解監聽
- 【spring原始碼學習】spring的事件釋出監聽機制原始碼解析Spring原始碼事件
- spring ioc原理解析Spring
- Spring原始碼解讀之BeanFactoryPostProcessor的處理Spring原始碼Bean
- Spring原始碼之BeanFactoryPostProcessor(後置處理器)Spring原始碼Bean
- 深入理解Spring IOC容器Spring
- TP5.1 原始碼窺探之反射和 Yaconf 配置擴充套件原始碼反射套件
- kotlin 擴充套件(擴充套件函式和擴充套件屬性)Kotlin套件函式
- 【spring原始碼】十二、監聽器Spring原始碼
- ajax 原始碼解讀之如何擴充套件 ajax 的功能原始碼套件