亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

Spring ApplicationContext上下文核心容器深入探究

 更新時間:2023年01月10日 11:26:23   作者:趙韓兵先生  
ApplicationContext是Spring應(yīng)用程序中的中央接口,由于繼承了多個組件,使得ApplicationContext擁有了許多Spring的核心功能,如獲取bean組件,注冊監(jiān)聽事件,加載資源文件等

Spring 容器核心可歸納為兩個類: BeanFactory 和 ApplicationContext,ApplicationContext 繼承自 BeanFactory ,其不僅包含 BeanFactory 所有功能,還擴(kuò)展了容器功能。ApplicationContext 核心其實是 refresh 方法,容器一系列功能都在該方法中實現(xiàn),如:注冊 Bean、注入 Bean 等。

整體流程

refresh 方法定義在 ConfigurableApplicationContext 接口中,被 AbstractApplicationContext 抽象類實現(xiàn),該方法由十幾個子方法組成,這些子方法各司其職完成容器的初始化。

public interface ConfigurableApplicationContext extends ApplicationContext, Lifecycle, Closeable {
	......
	//加載或刷新配置的持久表示形式,
    //可能是XML文件、屬性文件或關(guān)系數(shù)據(jù)庫模式。
    //由于這是一個啟動方法,它應(yīng)該銷毀已經(jīng)創(chuàng)建的單例
    //如果失敗,則避免懸而未決的資源。換句話說,在調(diào)用該方法之后,要么全部實例化,要么根本不實例化。
    //如果無法初始化bean工廠,則拋出BeanException異常,拋出IllegalStateException異常
    //如果已初始化且不支持多次刷新嘗試
	void refresh() throws BeansException, IllegalStateException;
    ......
}
public abstract class AbstractApplicationContext extends DefaultResourceLoader
		implements ConfigurableApplicationContext {
    ......
	@Override
	public void refresh() throws BeansException, IllegalStateException {
		synchronized (this.startupShutdownMonitor) {
			// 準(zhǔn)備此上下文以進(jìn)行刷新
			prepareRefresh();
			// 告訴子類刷新內(nèi)部bean工廠
			ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
			// 準(zhǔn)備bean工廠,以便在此上下文中使用
			prepareBeanFactory(beanFactory);
			try {
				// 允許在上下文子類中對bean工廠進(jìn)行后處理
				postProcessBeanFactory(beanFactory);
				// 調(diào)用在上下文中注冊為bean的工廠處理器
				invokeBeanFactoryPostProcessors(beanFactory);
				// 注冊攔截bean創(chuàng)建的bean處理器
				registerBeanPostProcessors(beanFactory);
				// 為此上下文初始化消息源。
				initMessageSource();
				// 為此上下文初始化事件多播
				initApplicationEventMulticaster();
				// 初始化特定上下文子類中的其他特殊bean
				onRefresh();
				// 檢查偵聽器bean并注冊它們
				registerListeners();
				// 實例化所有剩余的(非懶加載)單例
				finishBeanFactoryInitialization(beanFactory);
				// 最后一步:發(fā)布相應(yīng)的事件
				finishRefresh();
			}
			catch (BeansException ex) {
				if (logger.isWarnEnabled()) {
					logger.warn("Exception encountered during context initialization - " +
							"cancelling refresh attempt: " + ex);
				}
				// 銷毀已創(chuàng)建的單例以避免懸空資源
				destroyBeans();
				// 重置“活動”標(biāo)志
				cancelRefresh(ex);
				// 將異常傳播到調(diào)用方
				throw ex;
			}
			finally {
				// 重置Spring核心中的常見內(nèi)省緩存,因為我們可能不再需要單例bean的元數(shù)據(jù)。。。
				resetCommonCaches();
			}
		}
	}
 ......
}

在spring中AbstractApplicationContext的實現(xiàn)類通過調(diào)用父類的方法完成容器的初始化,下文以ClassPathXmlApplicationContext為例來追蹤容器的創(chuàng)建流程。

public class contextText {
	ApplicationContext context = new ClassPathXmlApplicationContext("spring-bean.xml");
}
public class ClassPathXmlApplicationContext extends AbstractXmlApplicationContext {
......
	public ClassPathXmlApplicationContext(
			String[] configLocations, boolean refresh, @Nullable ApplicationContext parent)
			throws BeansException {
		super(parent);
		setConfigLocations(configLocations);
		if (refresh) {
			refresh();
		}
	}
......
}

refresh 方法中,前四個子方法主要進(jìn)行上下文準(zhǔn)備工作。

prepareRefresh

public void refresh() throws BeansException, IllegalStateException {
	synchronized (this.startupShutdownMonitor) {
		// 初始化上下文環(huán)境,就是記錄下容器的啟動時間、活動狀態(tài)等
		prepareRefresh();
		...
    }
}
public abstract class AbstractApplicationContext {
    ...
    private long startupDate;
    private final AtomicBoolean active = new AtomicBoolean();
	private final AtomicBoolean closed = new AtomicBoolean();
    private Set<ApplicationEvent> earlyApplicationEvents;
    ...
    protected void prepareRefresh() {
        // 記錄此上下文開始時的系統(tǒng)時間(以毫秒為單位)
    	this.startupDate = System.currentTimeMillis();
    	// 記錄此上下文是否已關(guān)閉,這里設(shè)置為未關(guān)閉
    	this.closed.set(false);
    	// 記錄此上下文是否處于活動狀態(tài),這里設(shè)置為活動狀態(tài)
    	this.active.set(true);
    	if (logger.isInfoEnabled()) {
    		logger.info("Refreshing " + this);
    	}
    	// 這也是交由子類擴(kuò)展的方法。具體子類為 GenericWebApplicationContext,主要是初始化屬性源,
    	// 將 ServletContext 和 ServletConfig 屬性配置添加到 Environment 環(huán)境上下文中
    	initPropertySources();
    	// 校驗 Environment 中那些必備的屬性配置是否存在,不存在則拋異常。
    	getEnvironment().validateRequiredProperties();
    	// 創(chuàng)建 ApplicationEvent 事件集合
    	this.earlyApplicationEvents = new LinkedHashSet<>();
    }
}

refresh 中的 prepareRefresh 方法執(zhí)行結(jié)束,主要是記錄容器的啟動時間、活動狀態(tài)、檢查必備屬性是否存在。

obtainFreshBeanFactory

public abstract class AbstractApplicationContext {
    ...
    public void refresh() throws BeansException, IllegalStateException {
    	synchronized (this.startupShutdownMonitor) {
    		...
    		ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
    		...
    	}
    }
    ...
    protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
        // 該方法也是由子類擴(kuò)展,其子類有 AbstractRefreshableApplicationContext 和 GenericApplicationContext,
        // 該方法主要設(shè)置 BeanFactory 的 serializationId 屬性值,也就是序列化id
    	refreshBeanFactory();
    	// 通過 getBeanFactory 返回 BeanFactory 對象。同樣也是由子類擴(kuò)展,調(diào)用的是 GenericApplicationContext 類中的 getBeanFactory 方法。
    	// 返回的是 DefaultListableBeanFactory 。
    	ConfigurableListableBeanFactory beanFactory = getBeanFactory();
    	if (logger.isDebugEnabled()) {
    		logger.debug("Bean factory for " + getDisplayName() + ": " + beanFactory);
    	}
    	return beanFactory;
    }
    ...
}

obtainFreshBeanFactory 方法很簡單,因為當(dāng)前使用的是ClasspathXmlApplicationContext容器類,從類的繼承關(guān)系可以看出執(zhí)行的就是 AbstractRefreshableApplicationContext 中的 refreshBeanFactory 方法,返回的是DefaultListableBeanFactory,之后該方法還返回了 BeanFactory 對象,從這也可以看出 ApplicationContext 底層是以 BeanFactory 為基礎(chǔ),逐步擴(kuò)展 Spring 容器功能。

public abstract class AbstractRefreshableApplicationContext extends AbstractApplicationContext {
   ......
	/** Bean factory for this context */
	@Nullable
	private DefaultListableBeanFactory beanFactory;
    ......
	@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

prepareBeanFactory 方法主要是對 BeanFactory 做一些配置,包含各種類加載器、需要忽略的依賴以及后置處理器、解析器等

public void refresh() throws BeansException, IllegalStateException {
    synchronized (this.startupShutdownMonitor) {
        ...
		prepareBeanFactory(beanFactory);
		...	
    }
    ...
}
protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory) {
	// 設(shè)置類加載器
	beanFactory.setBeanClassLoader(getClassLoader());
	// 設(shè)置表達(dá)式解析器,主要用來解析 EL 表達(dá)式; Bean 初始化完成后填充屬性時會用到
	beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver(beanFactory.getBeanClassLoader()));
	// 設(shè)置屬性注冊解析器,主要用來解析 Bean 中的各種屬性類型,如 String、int 等
	beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this, getEnvironment()));
	// 添加一個后置處理器:ApplicationContextAwareProcessor。
	// 該后置處理器用于向?qū)崿F(xiàn)了 Aware 系列接口的 bean 設(shè)置相應(yīng)屬性。
	// (后置處理器和 Aware 接口也是比較核心的概念,后面會有文章詳細(xì)討論)
	beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));
	// 以下接口,在自動注入時會被忽略,其都是 Aware 系列接口
	beanFactory.ignoreDependencyInterface(EnvironmentAware.class);
	beanFactory.ignoreDependencyInterface(EmbeddedValueResolverAware.class);
	beanFactory.ignoreDependencyInterface(ResourceLoaderAware.class);
	beanFactory.ignoreDependencyInterface(ApplicationEventPublisherAware.class);
	beanFactory.ignoreDependencyInterface(MessageSourceAware.class);
	beanFactory.ignoreDependencyInterface(ApplicationContextAware.class);
	// 當(dāng)以下特殊的 Bean 需自動注入時,指定其注入的類型 。
	// 如:注入 BeanFactory 時,注入的類型對象為 ConfigurableListableBeanFactory 。
	beanFactory.registerResolvableDependency(BeanFactory.class, beanFactory);
	beanFactory.registerResolvableDependency(ResourceLoader.class, this);
	beanFactory.registerResolvableDependency(ApplicationEventPublisher.class, this);
	beanFactory.registerResolvableDependency(ApplicationContext.class, this);
	// 添加 ApplicationListenerDetector 后置處理器。
	// 該后置處理器用來檢測那些實現(xiàn)了 ApplicationListener 接口的 bean,并將其添加到應(yīng)用上下文的事件廣播器上。
	beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(this));
	// 判斷容器中是否存在 loadTimeWeaver Bean,如果存在則上下文使用臨時的 ClassLoader 進(jìn)行類型匹配。
	// 集成 AspectJ 時會用到 loadTimeWeaver 對象。
	if (beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {
		beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));
		beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));
	}
	// 注冊和環(huán)境相關(guān)的 Bean,如 environment、systemProperties、systemEnvironment
	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());
	}
}

在 prepareBeanFactory 方法中,主要對 BeanFactory 添加了一系列屬性項,如添加忽略自動注入的接口、添加 BeanPostProcessor 后置處理器、手動注冊部分特殊的 Bean及環(huán)境相關(guān)的 Bean 。

postProcessBeanFactory

public void refresh() throws BeansException, IllegalStateException {
    synchronized (this.startupShutdownMonitor) {
        ...
        postProcessBeanFactory(beanFactory);
        ...   
    }
}

postProcessBeanFactory 方法是上下文準(zhǔn)備的最后一步,spring中并沒有具體去實現(xiàn)postProcessBeanFactory方法,是提供給想要實現(xiàn)BeanPostProcessor的三方框架使用的。誰要使用誰就去實現(xiàn)。作用是在BeanFactory準(zhǔn)備工作完成后做一些定制化的處理,一般結(jié)合BeanPostProcessor接口的實現(xiàn)類一起使用,注入一些重要資源(類似Application的屬性和ServletContext的屬性)。最后需要設(shè)置忽略這類BeanPostProcessor子接口的自動裝配。

總結(jié)

ApplicationContext 上下文準(zhǔn)備工作基本結(jié)束,主要還是在 BeanFactory 中添加一系列后置處理器、注冊特殊的 Bean 及設(shè)置忽略自動注入的接口。其中還提到了 Spring 容器的三個核心部分:Aware 系列接口、BeanPostProcessor 后置處理器、BeanDefinition ,這部分在后面的文章會逐步跟蹤。

到此這篇關(guān)于Spring ApplicationContext上下文核心容器深入探究的文章就介紹到這了,更多相關(guān)Spring ApplicationContext內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

最新評論