前言
前面我們分析了spring ioc邊緣化的很多組件,這些組件是分析Bean加載過程的基石?;衫斫獬上旅娴囊馑迹?/p>
- 基石是高層的基礎
- 基石可以有很多種,這些基石相互組合、繼承、擴展,從而延伸出更多高級的功能
- 單獨的基石只能完成某一部分相對獨立的功能,它不是完整的
- 基石很重要,但是基石的堆砌更重要(即:架構設計的思維)
Spring IOC最核心的功能在于Bean加載過程,也是最能體現(xiàn)架構設計高度的一塊內容。網(wǎng)上有很多這方面的分析文章,在借鑒了這些前輩經(jīng)驗的基礎上,樓主還是想將源碼閱讀的過程記錄下來,并最終對其進行分析總結。
開篇,一個最簡單的入門級例子
Spring IOC容器管理的兩個類。
public interface MessageService {
String getMessage();
}
public class MessageServiceImpl implements MessageService {
public String getMessage() {
return "hello world";
}
}
xml配置信息。
<?xml version="1.0" encoding="UTF-8" ?>
<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://www.springframework.org/schema/beans"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"
default-autowire="byName">
<bean id="messageService" class="com.juconcurrent.learn.spring.MessageServiceImpl"/>
</beans>
如何使用?
public class Main {
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("classpath:application.xml");
MessageService messageService = context.getBean(MessageService.class);
System.out.println(messageService.getMessage());
}
}
輸出結果:
hello world
從上面的例子我們看到,Spring IOC有兩個口子供我們分析:
- ClassPathXmlApplicationContext()構造方法
- context.getBean()方法
構造器
先來看看構造方法,其主要做了以下事情:
- 配置的位置可轉換成多個(即:數(shù)組),默認為一個
-
refresh參數(shù)表示是否自動刷新上下文,默認刷新 -
parent表示父context,默認沒有
/**
* Create a new ClassPathXmlApplicationContext, loading the definitions
* from the given XML file and automatically refreshing the context.
* @param configLocation resource location
* @throws BeansException if context creation failed
*/
public ClassPathXmlApplicationContext(String configLocation) throws BeansException {
this(new String[] {configLocation}, true, null);
}
/**
* Create a new ClassPathXmlApplicationContext with the given parent,
* loading the definitions from the given XML files.
* @param configLocations array of resource locations
* @param refresh whether to automatically refresh the context,
* loading all bean definitions and creating all singletons.
* Alternatively, call refresh manually after further configuring the context.
* @param parent the parent context
* @throws BeansException if context creation failed
* @see #refresh()
*/
public ClassPathXmlApplicationContext(
String[] configLocations, boolean refresh, @Nullable ApplicationContext parent)
throws BeansException {
super(parent);
setConfigLocations(configLocations);
if (refresh) {
refresh();
}
}
我們一直點super(parent),看到最內部的實現(xiàn)如下:
public abstract class AbstractApplicationContext {
public AbstractApplicationContext(@Nullable ApplicationContext parent) {
// 設置解析資源文件的策略類對象,可解析多種類型的資源文件,
// 默認實現(xiàn)為`PathMatchingResourcePatternResolver`。
this();
// 設置父容器,在父容器不為空的情況下,父容器的`Environment`即被繼承過來。
setParent(parent);
}
public AbstractApplicationContext() {
this.resourcePatternResolver = getResourcePatternResolver();
}
protected ResourcePatternResolver getResourcePatternResolver() {
return new PathMatchingResourcePatternResolver(this);
}
public void setParent(@Nullable ApplicationContext parent) {
this.parent = parent;
if (parent != null) {
Environment parentEnvironment = parent.getEnvironment();
if (parentEnvironment instanceof ConfigurableEnvironment) {
getEnvironment().merge((ConfigurableEnvironment) parentEnvironment);
}
}
}
}
接下來看看setConfigLocations()。
/**
* 設置配置的位置。如果不設置,就是空的。
* Set the config locations for this application context.
* <p>If not set, the implementation may use a default as appropriate.
*/
public void setConfigLocations(@Nullable String... locations) {
if (locations != null) {
Assert.noNullElements(locations, "Config locations must not be null");
this.configLocations = new String[locations.length];
for (int i = 0; i < locations.length; i++) {
// 這兒會使用`Environment`進行路徑解析,
// 默認的實現(xiàn)為`StandardEnvironment`。
this.configLocations[i] = resolvePath(locations[i]).trim();
}
}
else {
this.configLocations = null;
}
}
protected String resolvePath(String path) {
return getEnvironment().resolveRequiredPlaceholders(path);
}
public ConfigurableEnvironment getEnvironment() {
if (this.environment == null) {
this.environment = createEnvironment();
}
return this.environment;
}
protected ConfigurableEnvironment createEnvironment() {
return new StandardEnvironment();
}
refresh方法
核心的代碼在于refresh()方法。之所以命名成refresh,而不是init之類的方法,有以下幾個原因:
- 該方法方法可反復調用
- 在配置變動之后,可通過該方法進行重新加載(也就是熱加載)
- refresh英文名為刷新,正符合當前的語境
接下來,我們分析一下這個方法。
public void refresh() throws BeansException, IllegalStateException {
// 先來一個鎖,避免并發(fā)刷新的問題
synchronized (this.startupShutdownMonitor) {
// 為刷新而準備上下文
// Prepare this context for refreshing.
prepareRefresh();
// 告訴子類刷新內部的bean工廠,主要做了以下幾件事:
// 1. 如果存在bean工廠,則先銷毀其管理的所有bean,并關閉工廠
// 2. 創(chuàng)建新的bean工廠
// 3. 加載BeanDefinitions
// Tell the subclass to refresh the internal bean factory.
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
// 準備在上下文中使用這個bean工廠
// Prepare the bean factory for use in this context.
prepareBeanFactory(beanFactory);
try {
// 允許子類重寫此方法,以便增加bean工廠創(chuàng)建后的邏輯。默認什么都不做。
// Allows post-processing of the bean factory in context subclasses.
postProcessBeanFactory(beanFactory);
// 調用bean工廠的后置處理器,這些處理器前面已經(jīng)注冊到了上下文
// Invoke factory processors registered as beans in the context.
invokeBeanFactoryPostProcessors(beanFactory);
// 注冊bean后置處理器,在bean的創(chuàng)建過程中會被調用
// Register bean processors that intercept bean creation.
registerBeanPostProcessors(beanFactory);
// 初始化消息源
// Initialize message source for this context.
initMessageSource();
// 初始化上下文中的事件廣播器
// Initialize event multicaster for this context.
initApplicationEventMulticaster();
// 初始化其他的特殊Bean
// Initialize other special beans in specific context subclasses.
onRefresh();
// 檢查并注冊監(jiān)聽器bean
// Check for listener beans and register them.
registerListeners();
// 實例化所有剩下的`non-lazy-init`單例
// Instantiate all remaining (non-lazy-init) singletons.
finishBeanFactoryInitialization(beanFactory);
// 完成刷新,發(fā)布相應的事件
// Last step: publish corresponding event.
finishRefresh();
}
catch (BeansException ex) {
if (logger.isWarnEnabled()) {
logger.warn("Exception encountered during context initialization - " +
"cancelling refresh attempt: " + ex);
}
// 在加載過程中出現(xiàn)異常的話,將銷毀所有已創(chuàng)建的bean,避免資源懸空
// Destroy already created singletons to avoid dangling resources.
destroyBeans();
// 重置active標記為false
// Reset 'active' flag.
cancelRefresh(ex);
// 將異常傳遞回調用者
// Propagate exception to caller.
throw ex;
}
finally {
// 最后會將中間產生的一些緩存清除掉,這些緩存后期可能永遠都不會再被使用。
// Reset common introspection caches in Spring's core, since we
// might not ever need metadata for singleton beans anymore...
resetCommonCaches();
}
}
}
這個方法包含了Spring IOC容器初始化的所有操作步驟。當我們讀懂了每一行代碼,就意味著我們了解了Spring IOC的所有功能。雖然該方法只有寥寥十多行,但是當下鉆到每個方法的內部,我們就會發(fā)現(xiàn)其調用層級之深,簡直令人發(fā)指,不過這并不能阻礙我們的鉆研。接下來,我們將深入分析每個方法內部的邏輯。
prepareRefresh方法
該方法用于準備上下文。
/**
* Prepare this context for refreshing, setting its startup date and
* active flag as well as performing any initialization of property sources.
*/
protected void prepareRefresh() {
// Switch to active.
// 設置開始時間,設置關閉標記為false,設置激活標記為true
this.startupDate = System.currentTimeMillis();
this.closed.set(false);
this.active.set(true);
// 簡單記錄一下日志
if (logger.isDebugEnabled()) {
if (logger.isTraceEnabled()) {
logger.trace("Refreshing " + this);
}
else {
logger.debug("Refreshing " + getDisplayName());
}
}
// 在上下文環(huán)境中,初始化屬性源(例如:將帶占位符的屬性源進行替換),
// 默認為空實現(xiàn)。
// Initialize any placeholder property sources in the context environment.
initPropertySources();
// 在Environment中,校驗所有需要的屬性(如果那些標注為必需的屬性不存在的話,將拋出異常)
// Validate that all properties marked as required are resolvable:
// see ConfigurablePropertyResolver#setRequiredProperties
getEnvironment().validateRequiredProperties();
// 存儲(或者叫設置)預刷新的應用監(jiān)聽器,需要注意以下兩點:
// 1. 如果`earlyApplicationListeners`不為空,說明用戶自定義過,那么將不需要使用`applicationListeners`進行覆蓋
// 2. 如果`earlyApplicationListeners`為空,說明用戶未自定義過,那么需要根據(jù)`applicationListeners`進行設置
// Store pre-refresh ApplicationListeners...
if (this.earlyApplicationListeners == null) {
this.earlyApplicationListeners = new LinkedHashSet<>(this.applicationListeners);
}
else {
// Reset local application listeners to pre-refresh state.
this.applicationListeners.clear();
this.applicationListeners.addAll(this.earlyApplicationListeners);
}
// 設置初始的早期應用事件
// Allow for the collection of early ApplicationEvents,
// to be published once the multicaster is available...
this.earlyApplicationEvents = new LinkedHashSet<>();
}
根據(jù)上面的源碼,我們知道這個方法主要做了以下幾件事情:
- 設置開始時間和激活標記;
- 校驗所有需要的屬性
- 初始化應用監(jiān)聽器及應用事件
obtainFreshBeanFactory方法
該方法用于獲取一個新鮮的bean工廠。那么,何為新鮮?
- 如果已經(jīng)存在一個bean工廠的話,需要先將其銷毀并關閉
- 創(chuàng)建一個新的bean工廠
那么其內部具體是怎么實現(xiàn)的呢?我們來分析下obtainFreshBeanFactory()方法。
/**
* 先刷新,后獲取。
* Tell the subclass to refresh the internal bean factory.
* @return the fresh BeanFactory instance
* @see #refreshBeanFactory()
* @see #getBeanFactory()
*/
protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
refreshBeanFactory();
return getBeanFactory();
}
refreshBeanFactory()方法:
/**
* This implementation performs an actual refresh of this context's underlying
* bean factory, shutting down the previous bean factory (if any) and
* initializing a fresh bean factory for the next phase of the context's lifecycle.
*/
@Override
protected final void refreshBeanFactory() throws BeansException {
// 如果bean工廠存在,那么銷毀所有的單例bean,并且關閉bean工廠
if (hasBeanFactory()) {
destroyBeans();
closeBeanFactory();
}
try {
// 創(chuàng)建bean工廠
DefaultListableBeanFactory beanFactory = createBeanFactory();
// 設置序列id
beanFactory.setSerializationId(getId());
// 自定義bean工廠
customizeBeanFactory(beanFactory);
// 加載BeanDefinitions
loadBeanDefinitions(beanFactory);
// 設置bean工廠
synchronized (this.beanFactoryMonitor) {
this.beanFactory = beanFactory;
}
}
catch (IOException ex) {
throw new ApplicationContextException("I/O error parsing bean definition source for " + getDisplayName(), ex);
}
}
接下來我們分析下refreshBeanFactory()方法內部調用的方法,這些方法除了loadBeanDefinitions()比較復雜,其他都很簡單。
銷毀相關的方法如下:
/**
* Determine whether this context currently holds a bean factory,
* i.e. has been refreshed at least once and not been closed yet.
*/
protected final boolean hasBeanFactory() {
synchronized (this.beanFactoryMonitor) {
return (this.beanFactory != null);
}
}
// 從這兒看出只是銷毀了所有的單例bean,其他scope的bean并沒有被銷毀
protected void destroyBeans() {
getBeanFactory().destroySingletons();
}
// 關閉bean工廠,就是將bean工廠設置為null
protected final void closeBeanFactory() {
synchronized (this.beanFactoryMonitor) {
if (this.beanFactory != null) {
this.beanFactory.setSerializationId(null);
this.beanFactory = null;
}
}
}
createBeanFactory()方法,內部其實就是一個DefaultListableBeanFactory的實例。
protected DefaultListableBeanFactory createBeanFactory() {
return new DefaultListableBeanFactory(getInternalParentBeanFactory());
}
customizeBeanFactory方法,選擇性地設置了兩個參數(shù):
- 允許bean定義被覆蓋
- 允許循環(huán)依賴
protected void customizeBeanFactory(DefaultListableBeanFactory beanFactory) {
if (this.allowBeanDefinitionOverriding != null) {
beanFactory.setAllowBeanDefinitionOverriding(this.allowBeanDefinitionOverriding);
}
if (this.allowCircularReferences != null) {
beanFactory.setAllowCircularReferences(this.allowCircularReferences);
}
}
由于我們分析的入口是ClassPathXmlApplicationContext,因此Spring IOC管理的bean是從xml中加載過來的。我們分析的loadBeanDefinitions()方法,其內部應該也是如此。
最后有一個賦值語句this.beanFactory = beanFactory;,這說明ApplicationContext和BeanFactory的關系,最終還是組合的關系,這樣的好處就是松耦合,并且方便后續(xù)擴展和維護。
loadBeanDefinitions()
/**
* Loads the bean definitions via an XmlBeanDefinitionReader.
* @see org.springframework.beans.factory.xml.XmlBeanDefinitionReader
* @see #initBeanDefinitionReader
* @see #loadBeanDefinitions
*/
@Override
protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) throws BeansException, IOException {
// 通過bean工廠,實例化一個`XmlBeanDefinitionReader`,表示xml下BeanDefinition的讀取器
// Create a new XmlBeanDefinitionReader for the given BeanFactory.
XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory);
// 配置bean定義讀取器,包括:環(huán)境對象、資源加載器、資源實體處理器
// Configure the bean definition reader with this context's
// resource loading environment.
beanDefinitionReader.setEnvironment(this.getEnvironment());
beanDefinitionReader.setResourceLoader(this);
beanDefinitionReader.setEntityResolver(new ResourceEntityResolver(this));
// Allow a subclass to provide custom initialization of the reader,
// then proceed with actually loading the bean definitions.
// 初始化
initBeanDefinitionReader(beanDefinitionReader);
// 加載
loadBeanDefinitions(beanDefinitionReader);
}
initBeanDefinitionReader()用于初始化操作,主要設置校驗開關。
- 當校驗的時候,校驗模式設置為自動
- 當不校驗的時候,校驗模式設置為“不校驗”,同時設置命名空間驗證,這樣的話,就從側面進行了驗證。
protected void initBeanDefinitionReader(XmlBeanDefinitionReader reader) {
reader.setValidating(this.validating);
}
/**
* Set whether to use XML validation. Default is {@code true}.
* <p>This method switches namespace awareness on if validation is turned off,
* in order to still process schema namespaces properly in such a scenario.
* @see #setValidationMode
* @see #setNamespaceAware
*/
public void setValidating(boolean validating) {
this.validationMode = (validating ? VALIDATION_AUTO : VALIDATION_NONE);
this.namespaceAware = !validating;
}
重載的loadBeanDefinitions()方法傳入?yún)?shù)為reader。
protected void loadBeanDefinitions(XmlBeanDefinitionReader reader) throws BeansException, IOException {
Resource[] configResources = getConfigResources();
if (configResources != null) {
reader.loadBeanDefinitions(configResources);
}
String[] configLocations = getConfigLocations();
if (configLocations != null) {
reader.loadBeanDefinitions(configLocations);
}
}
從上面的代碼我們看出,xml配置加載的方式有兩種,一種是以通用資源的方式,另一種是以配置位置的方式。配置位置的方式,最終將轉換為通用資源的方式。接下來,我們分析下配置位置的方式。
public int loadBeanDefinitions(String... locations) throws BeanDefinitionStoreException {
Assert.notNull(locations, "Location array must not be null");
int count = 0;
for (String location : locations) {
count += loadBeanDefinitions(location);
}
return count;
}
public int loadBeanDefinitions(String location) throws BeanDefinitionStoreException {
return loadBeanDefinitions(location, null);
}
/**
* Load bean definitions from the specified resource location.
* <p>The location can also be a location pattern, provided that the
* ResourceLoader of this bean definition reader is a ResourcePatternResolver.
* @param location the resource location, to be loaded with the ResourceLoader
* (or ResourcePatternResolver) of this bean definition reader
* @param actualResources a Set to be filled with the actual Resource objects
* that have been resolved during the loading process. May be {@code null}
* to indicate that the caller is not interested in those Resource objects.
* @return the number of bean definitions found
* @throws BeanDefinitionStoreException in case of loading or parsing errors
* @see #getResourceLoader()
* @see #loadBeanDefinitions(org.springframework.core.io.Resource)
* @see #loadBeanDefinitions(org.springframework.core.io.Resource[])
*/
public int loadBeanDefinitions(String location, @Nullable Set<Resource> actualResources) throws BeanDefinitionStoreException {
ResourceLoader resourceLoader = getResourceLoader();
if (resourceLoader == null) {
throw new BeanDefinitionStoreException(
"Cannot load bean definitions from location [" + location + "]: no ResourceLoader available");
}
if (resourceLoader instanceof ResourcePatternResolver) {
// Resource pattern matching available.
try {
// 關鍵的代碼在這兒,通過資源加載器將配置位置轉換成了通用資源。
Resource[] resources = ((ResourcePatternResolver) resourceLoader).getResources(location);
int count = loadBeanDefinitions(resources);
if (actualResources != null) {
Collections.addAll(actualResources, resources);
}
if (logger.isTraceEnabled()) {
logger.trace("Loaded " + count + " bean definitions from location pattern [" + location + "]");
}
return count;
}
catch (IOException ex) {
throw new BeanDefinitionStoreException(
"Could not resolve bean definition resource pattern [" + location + "]", ex);
}
}
else {
// Can only load single resources by absolute URL.
Resource resource = resourceLoader.getResource(location);
int count = loadBeanDefinitions(resource);
if (actualResources != null) {
actualResources.add(resource);
}
if (logger.isTraceEnabled()) {
logger.trace("Loaded " + count + " bean definitions from location [" + location + "]");
}
return count;
}
}
通用資源的BeanDefinition加載過程非常地復雜,因為xml配置支持的標簽非常多。限于篇幅,本文不做深入的分析。
在閱讀源碼的時候,樓主發(fā)現(xiàn)BeanDefinition有好幾個實現(xiàn)類,如下所示。我們著重分析紅框內的類。

他們的區(qū)別大致是這樣的。
-
AnnotatedBeanDefinition,包含有注解@Bean的Bean定義。一般情況下,通過注解的方式得到Bean定義,類型都是該接口的實現(xiàn)類。 -
AnnotatedGenericBeanDefinition,有@Configuration注解的類,會生成AnnotatedGenericBeanDefinition類型的Bean定義。 -
ScannedGenericBeanDefinition,有@Component注解的類,會生成ScannedGenericBeanDefinition類型的Bean定義。注意其它繼承了@Component的注解,同@Component。 -
RootBeanDefinition、ChildBeanDefinition、GenericBeanDefinition,這幾個類均繼承了AbstractBeanDefinition。從官方文檔里,我們得到了以下一些信息:
RootBeanDefinition是最常用的實現(xiàn)類,它對應一般性的<bean>元素標簽,GenericBeanDefinition是自2.5以后新加入的bean文件配置屬性定義類,是一站式服務類。在配置文件中可以定義父<bean>和子<bean>,父<bean>用RootBeanDefinition表示,而子<bean>用ChildBeanDefiniton表示,而沒有父<bean>的<bean>就使用RootBeanDefinition表示。AbstractBeanDefinition對兩者共同的類信息進行了抽象。
prepareBeanFactory方法
用于設置一些bean工廠相關的信息。例如:
- bean的類加載器、表達式處理、屬性編輯器注冊器
- 手動添加了一些bean后置處理器
- 指定某些依賴接口不被spring ioc容器所管理
- 手動注入一些關鍵的bean,例如bean工廠、應用上下文、環(huán)境相關的bean等等
/**
* Configure the factory's standard context characteristics,
* such as the context's ClassLoader and post-processors.
* @param beanFactory the BeanFactory to configure
*/
protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory) {
// Tell the internal bean factory to use the context's class loader etc.
// 設置bean的類加載器
beanFactory.setBeanClassLoader(getClassLoader());
// 設置bean的表達式處理器
beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver(beanFactory.getBeanClassLoader()));
// 設置屬性編輯器注冊器
beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this, getEnvironment()));
// Configure the bean factory with context callbacks.
// 添加bean后置處理器,用于給管理的bean設置“應用上下文”
beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));
// 忽略依賴接口,凡是繼承這些接口的類實例將不會被spring ioc容器管理
beanFactory.ignoreDependencyInterface(EnvironmentAware.class);
beanFactory.ignoreDependencyInterface(EmbeddedValueResolverAware.class);
beanFactory.ignoreDependencyInterface(ResourceLoaderAware.class);
beanFactory.ignoreDependencyInterface(ApplicationEventPublisherAware.class);
beanFactory.ignoreDependencyInterface(MessageSourceAware.class);
beanFactory.ignoreDependencyInterface(ApplicationContextAware.class);
// BeanFactory interface not registered as resolvable type in a plain factory.
// MessageSource registered (and found for autowiring) as a bean.
// 手動注入`BeanFactory`、`ResourceLoader`、`ApplicationEventPublisher`和`ApplicationContext`。
beanFactory.registerResolvableDependency(BeanFactory.class, beanFactory);
beanFactory.registerResolvableDependency(ResourceLoader.class, this);
beanFactory.registerResolvableDependency(ApplicationEventPublisher.class, this);
beanFactory.registerResolvableDependency(ApplicationContext.class, this);
// Register early post-processor for detecting inner beans as ApplicationListeners.
// 添加bean后置處理器,用于探測內部bean
beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(this));
// Detect a LoadTimeWeaver and prepare for weaving, if found.
// 添加bean后置處理器,用于AOP運行時織入
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.
// 注冊一些默認的環(huán)境相關的單例bean
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方法
該方法用于bean工廠加載后的后置處理,默認為空實現(xiàn)。
/**
* 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 registering special
* BeanPostProcessors etc in certain ApplicationContext implementations.
* @param beanFactory the bean factory used by the application context
*/
protected void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) {
}
invokeBeanFactoryPostProcessors方法
該方法用于調用bean工廠的后置處理器(已注冊的)。
/**
* Instantiate and invoke all registered BeanFactoryPostProcessor beans,
* respecting explicit order if given.
* <p>Must be called before singleton instantiation.
*/
protected void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory) {
PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, getBeanFactoryPostProcessors());
// Detect a LoadTimeWeaver and prepare for weaving, if found in the meantime
// (e.g. through an @Bean method registered by ConfigurationClassPostProcessor)
// 運行時切面織入相關的配置
if (beanFactory.getTempClassLoader() == null && beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {
beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));
beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));
}
}
PostProcessorRegistrationDelegate是一個工具類,其下的invokeBeanFactoryPostProcessors方法非常復雜。為啥會這么復雜,主要是由于以下幾個方面:
-
BeanFactoryPostProcessor可以被配置; -
BeanFactoryPostProcessor有一個特殊的子類BeanDefinitionRegistryPostProcessor,其用途就是方便BeanFactoryPostProcessor可以靈活地配置; -
BeanFactoryPostProcessor可以定義優(yōu)先級、順序性,以及無順序性。
接下來,我們具體看看源代碼。
// 該類是final修飾,說明其不可繼承。同時其構造器是私有的,說明不能被實例化。因此其就是一個靜態(tài)工具類。
final class PostProcessorRegistrationDelegate {
private PostProcessorRegistrationDelegate() {
}
public static void invokeBeanFactoryPostProcessors(
ConfigurableListableBeanFactory beanFactory, List<BeanFactoryPostProcessor> beanFactoryPostProcessors) {
// Invoke BeanDefinitionRegistryPostProcessors first, if any.
Set<String> processedBeans = new HashSet<>();
// 因為beanFactory的默認實現(xiàn)為`DefaultListableBeanFactory`,所以本身就繼承了`BeanDefinitionRegistry`。
// 這兒,我們僅分析if語句塊就可以了。
if (beanFactory instanceof BeanDefinitionRegistry) {
// bean工廠就是`BeanDefinitionRegistry`
BeanDefinitionRegistry registry = (BeanDefinitionRegistry) beanFactory;
// 分離出標準的后置處理器,以及注冊器后置處理器
List<BeanFactoryPostProcessor> regularPostProcessors = new ArrayList<>();
List<BeanDefinitionRegistryPostProcessor> registryProcessors = new ArrayList<>();
for (BeanFactoryPostProcessor postProcessor : beanFactoryPostProcessors) {
if (postProcessor instanceof BeanDefinitionRegistryPostProcessor) {
BeanDefinitionRegistryPostProcessor registryProcessor =
(BeanDefinitionRegistryPostProcessor) postProcessor;
registryProcessor.postProcessBeanDefinitionRegistry(registry);
registryProcessors.add(registryProcessor);
}
else {
regularPostProcessors.add(postProcessor);
}
}
// Do not initialize FactoryBeans here: We need to leave all regular beans
// uninitialized to let the bean factory post-processors apply to them!
// Separate between BeanDefinitionRegistryPostProcessors that implement
// PriorityOrdered, Ordered, and the rest.
// 1. 工廠bean不會被實例化
// 2. 優(yōu)先處理注冊器后置處理器
List<BeanDefinitionRegistryPostProcessor> currentRegistryProcessors = new ArrayList<>();
// First, invoke the BeanDefinitionRegistryPostProcessors that implement PriorityOrdered.
// 第一步,處理實現(xiàn)了`PriorityOrdered`接口的`BeanDefinitionRegistryPostProcessor`,包括:
// 1. 排序
// 2. 添加到`registryProcessors`,方便后續(xù)統(tǒng)一處理
// 3. 調用`postProcessBeanDefinitionRegistry`方法
// 4. 清理currentRegistryProcessors,方便后續(xù)復用
String[] postProcessorNames =
beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
for (String ppName : postProcessorNames) {
if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
processedBeans.add(ppName);
}
}
sortPostProcessors(currentRegistryProcessors, beanFactory);
registryProcessors.addAll(currentRegistryProcessors);
invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
currentRegistryProcessors.clear();
// Next, invoke the BeanDefinitionRegistryPostProcessors that implement Ordered.
// 第二步,處理實現(xiàn)了`Ordered`接口的`BeanDefinitionRegistryPostProcessor`,處理步驟和第一步相同
postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
for (String ppName : postProcessorNames) {
if (!processedBeans.contains(ppName) && beanFactory.isTypeMatch(ppName, Ordered.class)) {
currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
processedBeans.add(ppName);
}
}
sortPostProcessors(currentRegistryProcessors, beanFactory);
registryProcessors.addAll(currentRegistryProcessors);
invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
currentRegistryProcessors.clear();
// Finally, invoke all other BeanDefinitionRegistryPostProcessors until no further ones appear.
// 最終,調用所有除了實現(xiàn)`PriorityOrdered`和`Ordered`的`BeanDefinitionRegistryPostProcessors`,
// 處理步驟和第一步相同
// 注意,這兒使用了while循環(huán),而不是if,樓主也不知道是為什么
boolean reiterate = true;
while (reiterate) {
reiterate = false;
postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
for (String ppName : postProcessorNames) {
if (!processedBeans.contains(ppName)) {
currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
processedBeans.add(ppName);
reiterate = true;
}
}
sortPostProcessors(currentRegistryProcessors, beanFactory);
registryProcessors.addAll(currentRegistryProcessors);
invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
currentRegistryProcessors.clear();
}
// Now, invoke the postProcessBeanFactory callback of all processors handled so far.
// OK,上面的都做完了,就可以開始調用bean工廠的后置處理器了
invokeBeanFactoryPostProcessors(registryProcessors, beanFactory);
invokeBeanFactoryPostProcessors(regularPostProcessors, beanFactory);
}
else {
// Invoke factory processors registered with the context instance.
invokeBeanFactoryPostProcessors(beanFactoryPostProcessors, beanFactory);
}
// Do not initialize FactoryBeans here: We need to leave all regular beans
// uninitialized to let the bean factory post-processors apply to them!
// 除了上面的bean工廠后置處理器,我們還可以自己配置一些bean工廠后置處理器,例如:
// 1. 在xml中通過<bean>的方式
// 2. 在java config中通過@Bean的方式
// 3. 在自動裝配中通過@Componet的方式
// 因此,在這兒我們需要對這些后置處理器進行處理。
// 同樣地,根據(jù)是否是`PriorityOrdered`、`Ordered`,會有特殊的處理。
String[] postProcessorNames =
beanFactory.getBeanNamesForType(BeanFactoryPostProcessor.class, true, false);
// Separate between BeanFactoryPostProcessors that implement PriorityOrdered,
// Ordered, and the rest.
List<BeanFactoryPostProcessor> priorityOrderedPostProcessors = new ArrayList<>();
List<String> orderedPostProcessorNames = new ArrayList<>();
List<String> nonOrderedPostProcessorNames = new ArrayList<>();
for (String ppName : postProcessorNames) {
if (processedBeans.contains(ppName)) {
// skip - already processed in first phase above
}
else if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
priorityOrderedPostProcessors.add(beanFactory.getBean(ppName, BeanFactoryPostProcessor.class));
}
else if (beanFactory.isTypeMatch(ppName, Ordered.class)) {
orderedPostProcessorNames.add(ppName);
}
else {
nonOrderedPostProcessorNames.add(ppName);
}
}
// First, invoke the BeanFactoryPostProcessors that implement PriorityOrdered.
sortPostProcessors(priorityOrderedPostProcessors, beanFactory);
invokeBeanFactoryPostProcessors(priorityOrderedPostProcessors, beanFactory);
// Next, invoke the BeanFactoryPostProcessors that implement Ordered.
List<BeanFactoryPostProcessor> orderedPostProcessors = new ArrayList<>(orderedPostProcessorNames.size());
for (String postProcessorName : orderedPostProcessorNames) {
orderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class));
}
sortPostProcessors(orderedPostProcessors, beanFactory);
invokeBeanFactoryPostProcessors(orderedPostProcessors, beanFactory);
// Finally, invoke all other BeanFactoryPostProcessors.
List<BeanFactoryPostProcessor> nonOrderedPostProcessors = new ArrayList<>(nonOrderedPostProcessorNames.size());
for (String postProcessorName : nonOrderedPostProcessorNames) {
nonOrderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class));
}
invokeBeanFactoryPostProcessors(nonOrderedPostProcessors, beanFactory);
// Clear cached merged bean definitions since the post-processors might have
// modified the original metadata, e.g. replacing placeholders in values...
beanFactory.clearMetadataCache();
}
}
registerBeanPostProcessors方法
該方法用于注冊bean后置處理器,最終調用的仍然是PostProcessorRegistrationDelegate中的工具方法,我們來看一下。
protected void registerBeanPostProcessors(ConfigurableListableBeanFactory beanFactory) {
PostProcessorRegistrationDelegate.registerBeanPostProcessors(beanFactory, this);
}
public static void registerBeanPostProcessors(
ConfigurableListableBeanFactory beanFactory, AbstractApplicationContext applicationContext) {
String[] postProcessorNames = beanFactory.getBeanNamesForType(BeanPostProcessor.class, true, false);
// Register BeanPostProcessorChecker that logs an info message when
// a bean is created during BeanPostProcessor instantiation, i.e. when
// a bean is not eligible for getting processed by all BeanPostProcessors.
// 這兒會做兩件事情:
// 1. 統(tǒng)計bean后置處理器的個數(shù),格式是根據(jù)以下地方進行統(tǒng)計的
// 1. bean工廠內部的
// 2. 隨后添加的一個檢查bean后置處理器
// 3. 用戶自己定義的
// 2. 添加一個bean后置處理器,用于檢查目的,當檢查不通過時,將記錄info級別的日志
int beanProcessorTargetCount = beanFactory.getBeanPostProcessorCount() + 1 + postProcessorNames.length;
beanFactory.addBeanPostProcessor(new BeanPostProcessorChecker(beanFactory, beanProcessorTargetCount));
// Separate between BeanPostProcessors that implement PriorityOrdered,
// Ordered, and the rest.
// 分離出`PriorityOrdered`、`Ordered`和剩下的bean后置處理器
List<BeanPostProcessor> priorityOrderedPostProcessors = new ArrayList<>();
List<BeanPostProcessor> internalPostProcessors = new ArrayList<>();
List<String> orderedPostProcessorNames = new ArrayList<>();
List<String> nonOrderedPostProcessorNames = new ArrayList<>();
for (String ppName : postProcessorNames) {
if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
priorityOrderedPostProcessors.add(pp);
if (pp instanceof MergedBeanDefinitionPostProcessor) {
internalPostProcessors.add(pp);
}
}
else if (beanFactory.isTypeMatch(ppName, Ordered.class)) {
orderedPostProcessorNames.add(ppName);
}
else {
nonOrderedPostProcessorNames.add(ppName);
}
}
// First, register the BeanPostProcessors that implement PriorityOrdered.
// 第一步,排序并重新注冊到bean工廠(PriorityOrdered)
sortPostProcessors(priorityOrderedPostProcessors, beanFactory);
registerBeanPostProcessors(beanFactory, priorityOrderedPostProcessors);
// Next, register the BeanPostProcessors that implement Ordered.
// 第二步,排序并重新注冊到bean工廠(Ordered)
List<BeanPostProcessor> orderedPostProcessors = new ArrayList<>(orderedPostProcessorNames.size());
for (String ppName : orderedPostProcessorNames) {
BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
orderedPostProcessors.add(pp);
if (pp instanceof MergedBeanDefinitionPostProcessor) {
internalPostProcessors.add(pp);
}
}
sortPostProcessors(orderedPostProcessors, beanFactory);
registerBeanPostProcessors(beanFactory, orderedPostProcessors);
// Now, register all regular BeanPostProcessors.
// 第三步,注冊剩余的到bean工廠
List<BeanPostProcessor> nonOrderedPostProcessors = new ArrayList<>(nonOrderedPostProcessorNames.size());
for (String ppName : nonOrderedPostProcessorNames) {
BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
nonOrderedPostProcessors.add(pp);
if (pp instanceof MergedBeanDefinitionPostProcessor) {
internalPostProcessors.add(pp);
}
}
registerBeanPostProcessors(beanFactory, nonOrderedPostProcessors);
// Finally, re-register all internal BeanPostProcessors.
// 最后一步,重新注冊內部的到bean工廠,目的是將他們排序到最后位置
sortPostProcessors(internalPostProcessors, beanFactory);
registerBeanPostProcessors(beanFactory, internalPostProcessors);
// Re-register post-processor for detecting inner beans as ApplicationListeners,
// moving it to the end of the processor chain (for picking up proxies etc).
// 添加一個事件監(jiān)聽的bean后置處理器,但是不納入bean后置處理器個數(shù)的統(tǒng)計
beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(applicationContext));
}
initMessageSource方法
該方法用于初始化消息源。所謂消息源,是為了支持國際化而服務的,本文我們不會過多地對此進行分析。
initApplicationEventMulticaster方法
該方法用于初始化應用事件廣播器。
/**
* Initialize the ApplicationEventMulticaster.
* Uses SimpleApplicationEventMulticaster if none defined in the context.
* @see org.springframework.context.event.SimpleApplicationEventMulticaster
*/
protected void initApplicationEventMulticaster() {
ConfigurableListableBeanFactory beanFactory = getBeanFactory();
// 如果bean工廠包含應用事件廣播器,那么就使用它
// 否則,使用`SimpleApplicationEventMulticaster`創(chuàng)建一個默認的應用事件廣播器
if (beanFactory.containsLocalBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME)) {
this.applicationEventMulticaster =
beanFactory.getBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, ApplicationEventMulticaster.class);
if (logger.isTraceEnabled()) {
logger.trace("Using ApplicationEventMulticaster [" + this.applicationEventMulticaster + "]");
}
}
else {
this.applicationEventMulticaster = new SimpleApplicationEventMulticaster(beanFactory);
beanFactory.registerSingleton(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, this.applicationEventMulticaster);
if (logger.isTraceEnabled()) {
logger.trace("No '" + APPLICATION_EVENT_MULTICASTER_BEAN_NAME + "' bean, using " +
"[" + this.applicationEventMulticaster.getClass().getSimpleName() + "]");
}
}
}
onRefresh方法
該方法用于初始化其他特殊的bean,默認為空實現(xiàn)
registerListeners方法
用于注冊應用監(jiān)聽器到應用事件廣播器中。
/**
* Add beans that implement ApplicationListener as listeners.
* Doesn't affect other listeners, which can be added without being beans.
*/
protected void registerListeners() {
// Register statically specified listeners first.
// 注冊靜態(tài)的監(jiān)聽器
for (ApplicationListener<?> listener : getApplicationListeners()) {
getApplicationEventMulticaster().addApplicationListener(listener);
}
// Do not initialize FactoryBeans here: We need to leave all regular beans
// uninitialized to let post-processors apply to them!
// 注冊自定義的監(jiān)聽器
String[] listenerBeanNames = getBeanNamesForType(ApplicationListener.class, true, false);
for (String listenerBeanName : listenerBeanNames) {
getApplicationEventMulticaster().addApplicationListenerBean(listenerBeanName);
}
// Publish early application events now that we finally have a multicaster...
// 對預設置的事件進行廣播
Set<ApplicationEvent> earlyEventsToProcess = this.earlyApplicationEvents;
this.earlyApplicationEvents = null;
if (earlyEventsToProcess != null) {
for (ApplicationEvent earlyEvent : earlyEventsToProcess) {
getApplicationEventMulticaster().multicastEvent(earlyEvent);
}
}
}
finishBeanFactoryInitialization方法
用于實例化所有剩余的非懶加載的單例bean。
/**
* Finish the initialization of this context's bean factory,
* initializing all remaining singleton beans.
*/
protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {
// Initialize conversion service for this context.
// 初始化轉換服務
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));
}
// Register a default embedded value resolver if no bean post-processor
// (such as a PropertyPlaceholderConfigurer bean) registered any before:
// at this point, primarily for resolution in annotation attribute values.
// 如果沒有嵌套值處理器,那么注冊一個默認的嵌套值處理器
if (!beanFactory.hasEmbeddedValueResolver()) {
beanFactory.addEmbeddedValueResolver(strVal -> getEnvironment().resolvePlaceholders(strVal));
}
// Initialize LoadTimeWeaverAware beans early to allow for registering their transformers early.
// 初始化運行時織入的bean
String[] weaverAwareNames = beanFactory.getBeanNamesForType(LoadTimeWeaverAware.class, false, false);
for (String weaverAwareName : weaverAwareNames) {
getBean(weaverAwareName);
}
// Stop using the temporary ClassLoader for type matching.
// 停止臨時的類加載器
beanFactory.setTempClassLoader(null);
// Allow for caching all bean definition metadata, not expecting further changes.
// 凍結配置(即:配置不可再被修改)
beanFactory.freezeConfiguration();
// Instantiate all remaining (non-lazy-init) singletons.
// 調用工廠方法`preInstantiateSingletons`,預實例化所有的單例bean。
// 該方法非常關鍵,其內部解決循環(huán)依賴問題的思路非常有意思。
beanFactory.preInstantiateSingletons();
}
preInstantiateSingletons方法
該方法用于初始化所有的單例bean,其最最核心和關鍵的內容在于使用三級緩存解決循環(huán)依賴的問題。
那么,Spring為什么能解決循環(huán)依賴的問題呢?網(wǎng)上有很多這方面的分析,各種前因后果,細細道來冗長而繁瑣。
為了便于理解,樓主直接說結果。能解決的根本原因在于
引用傳遞。對象初始化之后,其引用就已經(jīng)確定下來了,后期也不會再變化,因此引用可以被其他地方使用。我們可以將初始化的過程分成兩個階段:
- 構造器創(chuàng)建對象(創(chuàng)建a對象,傳播b對象)
- 設置依賴關系(給a對象設置b對象引用,給b對象設置a對象引用)
在此基礎上,Spring衍生出了三級緩存,其僅支持單例的循環(huán)依賴。
- 不能解決的情況:
- 構造器注入循環(huán)依賴
-
prototypefield屬性注入(或者setter方法注入)循環(huán)依賴
- 能解決的情況:
- field屬性注入(或者setter方法注入)循環(huán)依賴
好了,步入正軌,我們開始分析這個方法。
public void preInstantiateSingletons() throws BeansException {
// 簡單記錄一下跟蹤日志
if (logger.isTraceEnabled()) {
logger.trace("Pre-instantiating singletons in " + this);
}
// Iterate over a copy to allow for init methods which in turn register new bean definitions.
// While this may not be part of the regular factory bootstrap, it does otherwise work fine.
// bean定義的名稱,就是bean的名稱
List<String> beanNames = new ArrayList<>(this.beanDefinitionNames);
// Trigger initialization of all non-lazy singleton beans...
for (String beanName : beanNames) {
// 合并bean定義
RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
// 只有非抽象的、單例的、非懶加載的bean定義,才會實例化成bean,并注冊到bean工廠
if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
// 1. 如果是工廠bean,同時為預加載的話,那么直接調用`getBean`方法加載bean
// 2. 如果不是工廠bean,直接調用`getBean`方法加載bean
if (isFactoryBean(beanName)) {
Object bean = getBean(FACTORY_BEAN_PREFIX + beanName);
if (bean instanceof FactoryBean) {
final FactoryBean<?> factory = (FactoryBean<?>) bean;
boolean isEagerInit;
if (System.getSecurityManager() != null && factory instanceof SmartFactoryBean) {
isEagerInit = AccessController.doPrivileged((PrivilegedAction<Boolean>)
((SmartFactoryBean<?>) factory)::isEagerInit,
getAccessControlContext());
}
else {
isEagerInit = (factory instanceof SmartFactoryBean &&
((SmartFactoryBean<?>) factory).isEagerInit());
}
if (isEagerInit) {
getBean(beanName);
}
}
}
else {
getBean(beanName);
}
}
}
// Trigger post-initialization callback for all applicable beans...
// bean加載之后,如果bean為`SmartInitializingSingleton`類型,那么將觸發(fā)方法`afterSingletonsInstantiated()`
for (String beanName : beanNames) {
Object singletonInstance = getSingleton(beanName);
if (singletonInstance instanceof SmartInitializingSingleton) {
final SmartInitializingSingleton smartSingleton = (SmartInitializingSingleton) singletonInstance;
if (System.getSecurityManager() != null) {
AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
smartSingleton.afterSingletonsInstantiated();
return null;
}, getAccessControlContext());
}
else {
smartSingleton.afterSingletonsInstantiated();
}
}
}
}
getBean()方法至關重要,用于獲取一個bean。其調用的是doGetBean()方法,根據(jù)名稱獲取一個bean。
public Object getBean(String name) throws BeansException {
return doGetBean(name, null, null, false);
}
接下來,我們分析一下doGetBean()方法。
/**
* Return an instance, which may be shared or independent, of the specified bean.
* @param name the name of the bean to retrieve
* @param requiredType the required type of the bean to retrieve
* @param args arguments to use when creating a bean instance using explicit arguments
* (only applied when creating a new instance as opposed to retrieving an existing one)
* @param typeCheckOnly whether the instance is obtained for a type check,
* not for actual use
* @return an instance of the bean
* @throws BeansException if the bean could not be created
*/
@SuppressWarnings("unchecked")
protected <T> T doGetBean(final String name, @Nullable final Class<T> requiredType,
@Nullable final Object[] args, boolean typeCheckOnly) throws BeansException {
// 獲取bean最初的名稱,因為傳入的bean名稱可能是一個別名,也可能是一個工廠bean的名稱
final String beanName = transformedBeanName(name);
Object bean;
// Eagerly check singleton cache for manually registered singletons.
// 這兒嘗試從三級緩存獲取單例對象
Object sharedInstance = getSingleton(beanName);
if (sharedInstance != null && args == null) {
if (logger.isTraceEnabled()) {
if (isSingletonCurrentlyInCreation(beanName)) {
logger.trace("Returning eagerly cached instance of singleton bean '" + beanName +
"' that is not fully initialized yet - a consequence of a circular reference");
}
else {
logger.trace("Returning cached instance of singleton bean '" + beanName + "'");
}
}
// 從三級緩存獲取到之后,將嘗試將bean手動注冊到bean工廠
bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
}
else {
// Fail if we're already creating this bean instance:
// We're assumably within a circular reference.
// 如果三級緩存沒獲取到,且bean為prototype類型,那么拋出異常
if (isPrototypeCurrentlyInCreation(beanName)) {
throw new BeanCurrentlyInCreationException(beanName);
}
// Check if bean definition exists in this factory.
// 如果當前bean工廠不包含bean的定義,則委托給父工廠進行get處理
BeanFactory parentBeanFactory = getParentBeanFactory();
if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
// Not found -> check parent.
String nameToLookup = originalBeanName(name);
if (parentBeanFactory instanceof AbstractBeanFactory) {
return ((AbstractBeanFactory) parentBeanFactory).doGetBean(
nameToLookup, requiredType, args, typeCheckOnly);
}
else if (args != null) {
// Delegation to parent with explicit args.
return (T) parentBeanFactory.getBean(nameToLookup, args);
}
else if (requiredType != null) {
// No args -> delegate to standard getBean method.
return parentBeanFactory.getBean(nameToLookup, requiredType);
}
else {
return (T) parentBeanFactory.getBean(nameToLookup);
}
}
// 如果不僅僅是類型檢查,那么將beanName放入已創(chuàng)建的bean名稱集合里面
if (!typeCheckOnly) {
markBeanAsCreated(beanName);
// 這就是上面方法的實現(xiàn)
/*
protected void markBeanAsCreated(String beanName) {
if (!this.alreadyCreated.contains(beanName)) {
synchronized (this.mergedBeanDefinitions) {
if (!this.alreadyCreated.contains(beanName)) {
// Let the bean definition get re-merged now that we're actually creating
// the bean... just in case some of its metadata changed in the meantime.
clearMergedBeanDefinition(beanName);
this.alreadyCreated.add(beanName);
}
}
}
}
*/
}
try {
// 獲取合并的bean定義,并檢查(這兒判斷是否為abstract)
final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
checkMergedBeanDefinition(mbd, beanName, args);
// Guarantee initialization of beans that the current bean depends on.
// 這兒會判斷是否存在構造器的循環(huán)依賴,如果存在則拋出異常,否則的話就先注冊依賴關系,再get這個bean
String[] dependsOn = mbd.getDependsOn();
if (dependsOn != null) {
for (String dep : dependsOn) {
if (isDependent(beanName, dep)) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"Circular depends-on relationship between '" + beanName + "' and '" + dep + "'");
}
registerDependentBean(dep, beanName);
try {
getBean(dep);
}
catch (NoSuchBeanDefinitionException ex) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"'" + beanName + "' depends on missing bean '" + dep + "'", ex);
}
}
}
// Create bean instance.
// 創(chuàng)建單例
if (mbd.isSingleton()) {
// 創(chuàng)建單例的時候,會傳入一個ObjectFactory的對象。首先它是一個工廠,然后他會創(chuàng)一個對象。
sharedInstance = getSingleton(beanName, () -> {
try {
return createBean(beanName, mbd, args);
}
catch (BeansException ex) {
// Explicitly remove instance from singleton cache: It might have been put there
// eagerly by the creation process, to allow for circular reference resolution.
// Also remove any beans that received a temporary reference to the bean.
destroySingleton(beanName);
throw ex;
}
});
// 獲取到bean的時候,為啥不直接返回,原因在于獲取到的bean可能是一個工廠bean,工廠bean又可能是工廠bean的工廠bean。
// 因此,這個方法就是解決這個問題而存在的。
bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
}
// 創(chuàng)建prototype
else if (mbd.isPrototype()) {
// It's a prototype -> create a new instance.
Object prototypeInstance = null;
try {
beforePrototypeCreation(beanName);
prototypeInstance = createBean(beanName, mbd, args);
}
finally {
afterPrototypeCreation(beanName);
}
bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
}
// 創(chuàng)建其他Scope
else {
String scopeName = mbd.getScope();
final Scope scope = this.scopes.get(scopeName);
if (scope == null) {
throw new IllegalStateException("No Scope registered for scope name '" + scopeName + "'");
}
try {
Object scopedInstance = scope.get(beanName, () -> {
beforePrototypeCreation(beanName);
try {
return createBean(beanName, mbd, args);
}
finally {
afterPrototypeCreation(beanName);
}
});
bean = getObjectForBeanInstance(scopedInstance, name, beanName, mbd);
}
catch (IllegalStateException ex) {
throw new BeanCreationException(beanName,
"Scope '" + scopeName + "' is not active for the current thread; consider " +
"defining a scoped proxy for this bean if you intend to refer to it from a singleton",
ex);
}
}
}
catch (BeansException ex) {
cleanupAfterBeanCreationFailure(beanName);
throw ex;
}
}
// Check if required type matches the type of the actual bean instance.
// 如果類型不匹配,則需要通過轉換器進行轉換。當轉換不成功,則拋出異常。
if (requiredType != null && !requiredType.isInstance(bean)) {
try {
T convertedBean = getTypeConverter().convertIfNecessary(bean, requiredType);
if (convertedBean == null) {
throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
}
return convertedBean;
}
catch (TypeMismatchException ex) {
if (logger.isTraceEnabled()) {
logger.trace("Failed to convert bean '" + name + "' to required type '" +
ClassUtils.getQualifiedName(requiredType) + "'", ex);
}
throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
}
}
return (T) bean;
}
重點來了!
在分析完doGetBean()方法后,我們發(fā)現(xiàn)不管是當前bean,還是依賴的bean,最終調用的都是getSingleton()方法。該方法有好幾個重載方法,我們依次來分析。
/** Cache of singleton objects: bean name to bean instance. */
// 一級緩存,緩存已實例化的bean
private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256);
/** Cache of early singleton objects: bean name to bean instance. */
// 二級緩存,緩存`early`(可提前暴露)的bean
private final Map<String, Object> earlySingletonObjects = new HashMap<>(16);
/** Cache of singleton factories: bean name to ObjectFactory. */
// 三級緩存,緩存對象工廠對象
private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap<>(16);
/** Set of registered singletons, containing the bean names in registration order. */
// 已注冊的單例bean名稱
private final Set<String> registeredSingletons = new LinkedHashSet<>(256);
/** Names of beans that are currently in creation. */
// 當前正在創(chuàng)建的單例bean名稱
private final Set<String> singletonsCurrentlyInCreation =
Collections.newSetFromMap(new ConcurrentHashMap<>(16));
// 調用的是下面那個方法,且參數(shù)`allowEarlyReference`為true
public Object getSingleton(String beanName) {
return getSingleton(beanName, true);
}
protected Object getSingleton(String beanName, boolean allowEarlyReference) {
// 1. 先從一級緩存`singletonObjects`中去獲取。(如果獲取到就直接return)
Object singletonObject = this.singletonObjects.get(beanName);
if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
synchronized (this.singletonObjects) {
// 2. 如果獲取不到或者對象正在創(chuàng)建中(isSingletonCurrentlyInCreation()),那就再從二級緩存earlySingletonObjects中獲取。(如果獲取到就直接return)
singletonObject = this.earlySingletonObjects.get(beanName);
if (singletonObject == null && allowEarlyReference) {
// 3. 如果還是獲取不到,且允許`singletonFactories`(`allowEarlyReference = true`)通過`getObject()`獲取。
// 就從三級緩存`singletonFactory.getObject()`獲取。
// (如果獲取到了就從`singletonFactories`中移除,并且放進`earlySingletonObjects`。
// 其實也就是從三級緩存移動(是剪切、不是復制哦~)到了二級緩存)
ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
if (singletonFactory != null) {
singletonObject = singletonFactory.getObject();
this.earlySingletonObjects.put(beanName, singletonObject);
this.singletonFactories.remove(beanName);
}
}
}
}
return singletonObject;
}
/**
* 相比較于上個方法,多了錯誤校驗、異常處理、外置化`ObjectFactory`創(chuàng)建對象的操作。
* Return the (raw) singleton object registered under the given name,
* creating and registering a new one if none registered yet.
* @param beanName the name of the bean
* @param singletonFactory the ObjectFactory to lazily create the singleton
* with, if necessary
* @return the registered singleton object
*/
public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) {
Assert.notNull(beanName, "Bean name must not be null");
synchronized (this.singletonObjects) {
Object singletonObject = this.singletonObjects.get(beanName);
if (singletonObject == null) {
if (this.singletonsCurrentlyInDestruction) {
throw new BeanCreationNotAllowedException(beanName,
"Singleton bean creation not allowed while singletons of this factory are in destruction " +
"(Do not request a bean from a BeanFactory in a destroy method implementation!)");
}
if (logger.isDebugEnabled()) {
logger.debug("Creating shared instance of singleton bean '" + beanName + "'");
}
beforeSingletonCreation(beanName);
boolean newSingleton = false;
boolean recordSuppressedExceptions = (this.suppressedExceptions == null);
if (recordSuppressedExceptions) {
this.suppressedExceptions = new LinkedHashSet<>();
}
try {
singletonObject = singletonFactory.getObject();
newSingleton = true;
}
catch (IllegalStateException ex) {
// Has the singleton object implicitly appeared in the meantime ->
// if yes, proceed with it since the exception indicates that state.
singletonObject = this.singletonObjects.get(beanName);
if (singletonObject == null) {
throw ex;
}
}
catch (BeanCreationException ex) {
if (recordSuppressedExceptions) {
for (Exception suppressedException : this.suppressedExceptions) {
ex.addRelatedCause(suppressedException);
}
}
throw ex;
}
finally {
if (recordSuppressedExceptions) {
this.suppressedExceptions = null;
}
afterSingletonCreation(beanName);
}
if (newSingleton) {
addSingleton(beanName, singletonObject);
}
}
return singletonObject;
}
}
簡單總結一下,Spring解決循環(huán)依賴的三級緩存邏輯如下:
- 先從一級緩存
singletonObjects中去獲取。(如果獲取到就直接return)- 如果獲取不到或者對象正在創(chuàng)建中(isSingletonCurrentlyInCreation()),那就再從二級緩存earlySingletonObjects中獲取。(如果獲取到就直接return)
- 如果還是獲取不到,且允許
singletonFactories(allowEarlyReference = true)通過getObject()獲取。就從三級緩存singletonFactory.getObject()獲取。(如果獲取到了就從singletonFactories中移除,并且放進earlySingletonObjects。其實也就是從三級緩存移動(是剪切、不是復制哦~)到了二級緩存)。
生命周期
在分析finishRefresh()方法之前,我們有必要澄清一下,何為生命周期?
所謂生命周期,其實是一系列的回調。包括:
- Initialization callbacks(初始化回調)
- Destruction callbacks(銷毀回調)
要與容器的bean生命周期管理交互,即容器在啟動后和容器在銷毀前對每個bean執(zhí)行操作,有如下三種方法:
- 實現(xiàn)Spring框架的
InitializingBean和DisposableBean接口。容器為前者調用afterPropertiesSet()方法,為后者調用destroy()方法,以允許bean在初始化和銷毀的時候執(zhí)行某些操作。
public class HelloLifeCycle implements InitializingBean, DisposableBean {
public void afterPropertiesSet() throws Exception {
System.out.println("afterPropertiesSet 啟動");
}
public void destroy() throws Exception {
System.out.println("DisposableBean 停止");
}
}
- 在xml配置中,bean在定義的時候,指定初始化方法和銷毀方法。
<bean id="helloLifeCycle" class="com.hzways.life.cycle.HelloLifeCycle" init-method="init3" destroy-method="destroy3"/>
- JSR-250中,
@PostConstruct和@PreDestroy注解,可用于bean的初始化后和銷毀前操作。
-
@PostConstruct注解用于方法上,該方法在初始化完成之后被執(zhí)行。 -
@PreDestroy注解用于方法上,該方法在銷毀前被執(zhí)行。
@Service
public class HelloLifeCycle {
@PostConstruct
private void init2() {
System.out.println("PostConstruct 啟動");
}
@PreDestroy
private void destroy2() {
System.out.println("PreDestroy 停止");
}
}
finishRefresh方法
該方法主要調用了生命周期處理器的onRefresh()方法。
/**
* Finish the refresh of this context, invoking the LifecycleProcessor's
* onRefresh() method and publishing the
* {@link org.springframework.context.event.ContextRefreshedEvent}.
*/
protected void finishRefresh() {
// Clear context-level resource caches (such as ASM metadata from scanning).
// 清除上下文級別的資源緩存
clearResourceCaches();
// Initialize lifecycle processor for this context.
// 初始化生命周期處理器
initLifecycleProcessor();
// Propagate refresh to lifecycle processor first.
// 傳播刷新操作到聲明周期處理器
getLifecycleProcessor().onRefresh();
// Publish the final event.
// 發(fā)布事件
publishEvent(new ContextRefreshedEvent(this));
// Participate in LiveBeansView MBean, if active.
// MBean管理相關
LiveBeansView.registerApplicationContext(this);
}
這兒我們著重關注兩個方法:initLifecycleProcessor()和getLifecycleProcessor().onRefresh()。
initLifecycleProcessor方法
該方法很簡單。
- 首先嘗試從bean工廠獲取生命周期處理器;
- 如果bean工廠未獲取到,初始化一個默認的生命周期處理器(
DefaultLifecycleProcessor),并注冊到bean工廠; - 在前面兩部的基礎上,設置處理到
AbstractApplicationContext的成員變量lifecycleProcessor上,供后續(xù)使用。
/**
* Initialize the LifecycleProcessor.
* Uses DefaultLifecycleProcessor if none defined in the context.
* @see org.springframework.context.support.DefaultLifecycleProcessor
*/
protected void initLifecycleProcessor() {
ConfigurableListableBeanFactory beanFactory = getBeanFactory();
if (beanFactory.containsLocalBean(LIFECYCLE_PROCESSOR_BEAN_NAME)) {
this.lifecycleProcessor =
beanFactory.getBean(LIFECYCLE_PROCESSOR_BEAN_NAME, LifecycleProcessor.class);
if (logger.isTraceEnabled()) {
logger.trace("Using LifecycleProcessor [" + this.lifecycleProcessor + "]");
}
}
else {
DefaultLifecycleProcessor defaultProcessor = new DefaultLifecycleProcessor();
defaultProcessor.setBeanFactory(beanFactory);
this.lifecycleProcessor = defaultProcessor;
beanFactory.registerSingleton(LIFECYCLE_PROCESSOR_BEAN_NAME, this.lifecycleProcessor);
if (logger.isTraceEnabled()) {
logger.trace("No '" + LIFECYCLE_PROCESSOR_BEAN_NAME + "' bean, using " +
"[" + this.lifecycleProcessor.getClass().getSimpleName() + "]");
}
}
}
onRefresh方法
分析該方法前,先看看getLifecycleProcessor(),其實就是檢查并返回成員變量lifecycleProcessor。
LifecycleProcessor getLifecycleProcessor() throws IllegalStateException {
if (this.lifecycleProcessor == null) {
throw new IllegalStateException("LifecycleProcessor not initialized - " +
"call 'refresh' before invoking lifecycle methods via the context: " + this);
}
return this.lifecycleProcessor;
}
public void onRefresh() {
startBeans(true);
this.running = true;
}
onRefresh()方法調用了startBeans方法,之后更新了運行狀態(tài)。
private void startBeans(boolean autoStartupOnly) {
// 獲取所有Bean工廠管理的`Lifecycle`對象
Map<String, Lifecycle> lifecycleBeans = getLifecycleBeans();
Map<Integer, LifecycleGroup> phases = new HashMap<>();
// 根據(jù)`phase`進行分組
lifecycleBeans.forEach((beanName, bean) -> {
if (!autoStartupOnly || (bean instanceof SmartLifecycle && ((SmartLifecycle) bean).isAutoStartup())) {
int phase = getPhase(bean);
LifecycleGroup group = phases.get(phase);
if (group == null) {
group = new LifecycleGroup(phase, this.timeoutPerShutdownPhase, lifecycleBeans, autoStartupOnly);
phases.put(phase, group);
}
group.add(beanName, bean);
}
});
// 根據(jù)分組,調用對象的`start()`方法
if (!phases.isEmpty()) {
List<Integer> keys = new ArrayList<>(phases.keySet());
Collections.sort(keys);
for (Integer key : keys) {
phases.get(key).start();
}
}
}
startBeans()方法做了以下事情:
- 首先獲取所有Bean工廠管理的
Lifecycle對象; - 對
Lifecycle對象根據(jù)phase(階段的意思,其實是一個int值)進行分組。相同phase的對象劃到一個組; - 根據(jù)
phase的值大小,升序調用其Lifecycle對象的start()方法。
getLifecycleBeans()方法用于獲取對象。
/**
* Retrieve all applicable Lifecycle beans: all singletons that have already been created,
* as well as all SmartLifecycle beans (even if they are marked as lazy-init).
* @return the Map of applicable beans, with bean names as keys and bean instances as values
*/
protected Map<String, Lifecycle> getLifecycleBeans() {
ConfigurableListableBeanFactory beanFactory = getBeanFactory();
Map<String, Lifecycle> beans = new LinkedHashMap<>();
// 獲取所有類型為`Lifecycle`的bean名稱
String[] beanNames = beanFactory.getBeanNamesForType(Lifecycle.class, false, false);
for (String beanName : beanNames) {
String beanNameToRegister = BeanFactoryUtils.transformedBeanName(beanName);
boolean isFactoryBean = beanFactory.isFactoryBean(beanNameToRegister);
String beanNameToCheck = (isFactoryBean ? BeanFactory.FACTORY_BEAN_PREFIX + beanName : beanName);
// 這兒對bean加了一些限制條件
// 1. 如果是單例的話,不能是工廠bean,且類型必須為`Lifecycle`
// 2. 如果不是單例的話,類型必須為`SmartLifecycle`
if ((beanFactory.containsSingleton(beanNameToRegister) &&
(!isFactoryBean || matchesBeanType(Lifecycle.class, beanNameToCheck, beanFactory))) ||
matchesBeanType(SmartLifecycle.class, beanNameToCheck, beanFactory)) {
Object bean = beanFactory.getBean(beanNameToCheck);
if (bean != this && bean instanceof Lifecycle) {
beans.put(beanNameToRegister, (Lifecycle) bean);
}
}
}
return beans;
}
最關鍵的地方在于start()方法的調用。
public void start() {
if (this.members.isEmpty()) {
return;
}
if (logger.isDebugEnabled()) {
logger.debug("Starting beans in phase " + this.phase);
}
// 對分組內的bean按照名稱進行排序,并最終調用了`doStart()`方法
Collections.sort(this.members);
for (LifecycleGroupMember member : this.members) {
doStart(this.lifecycleBeans, member.name, this.autoStartupOnly);
}
}
/**
* Start the specified bean as part of the given set of Lifecycle beans,
* making sure that any beans that it depends on are started first.
* @param lifecycleBeans a Map with bean name as key and Lifecycle instance as value
* @param beanName the name of the bean to start
*/
private void doStart(Map<String, ? extends Lifecycle> lifecycleBeans, String beanName, boolean autoStartupOnly) {
Lifecycle bean = lifecycleBeans.remove(beanName);
if (bean != null && bean != this) {
String[] dependenciesForBean = getBeanFactory().getDependenciesForBean(beanName);
for (String dependency : dependenciesForBean) {
// 這兒有遞歸調用。
// 需要特別注意的地方在于,如果一個`Lifecycle`依賴另外一個`Lifecycle`,則會優(yōu)先調用被依賴的`Lifecycle`。
doStart(lifecycleBeans, dependency, autoStartupOnly);
}
if (!bean.isRunning() &&
(!autoStartupOnly || !(bean instanceof SmartLifecycle) || ((SmartLifecycle) bean).isAutoStartup())) {
if (logger.isTraceEnabled()) {
logger.trace("Starting bean '" + beanName + "' of type [" + bean.getClass().getName() + "]");
}
try {
// 廬山真面目,最終調到了`Lifecycle`的`start`方法。
bean.start();
}
catch (Throwable ex) {
throw new ApplicationContextException("Failed to start bean '" + beanName + "'", ex);
}
if (logger.isDebugEnabled()) {
logger.debug("Successfully started bean '" + beanName + "'");
}
}
}
}
至此,onRefresh()方法分析完成。
destroyBeans方法
該方法用于銷毀bean,內部調用的是bean工廠的destroySingletons()方法?!咀⒁狻浚哼@兒僅銷毀了單例bean!
總結
我們從源碼層面分析了bean加載的整個過程,每個步驟各司其職,環(huán)環(huán)相扣,非常地精彩。其中最顯眼的地方在于Spring對bean循環(huán)依賴的解決方案(三級緩存)。
借鑒于網(wǎng)上的一張圖,bean加載的過程如下所示:

而這張圖標綠的地方,單獨解釋如下:
-
獲取 BeanName,對傳入的 name 進行解析,轉化為可以從 Map 中獲取到BeanDefinition的 bean name。 -
合并 Bean 定義,對父類的定義進行合并和覆蓋,如果父類還有父類,會進行遞歸合并,以獲取完整的Bean定義信息。 -
實例化,使用構造或者工廠方法創(chuàng)建Bean實例。
屬性填充,尋找并且注入依賴,依賴的Bean還會遞歸調用getBean方法獲取。 -
初始化,調用自定義的初始化方法。 -
獲取最終的 Bean,如果是FactoryBean需要調用getObject方法,如果需要類型轉換調用TypeConverter進行轉化。
除此之外,我們還需要關注一下bean的生命周期,這是貫穿Spring IOC的一條主線。
- 實例化bean
- 設置屬性值
- 調用
BeanNameAware.setBeanName()方法 - 調用
BeanFactoryAware.setBeanFactory()方法 - 調用
BeanPostProcessor.postProcessBeforeInitialization()方法- 調用
ApplicationContextAware.setApplicationContext()方法 - 調用
@PostConstruct所在的方法 - 其他...
- 調用
- 調用
InitializingBean.afterPropertiesSet()方法 - 調用init方法
- 調用
BeanPostProcessor.postProcessAfterInitialization()方法 - 調用
DisposableBean.destroy()方法 - 調用destory方法
參考文檔
- https://blog.csdn.net/nuomizhende45/article/details/81158383
- http://www.itdecent.cn/p/9ea61d204559
- https://www.cnblogs.com/lqmblog/p/8592817.html
- http://www.itdecent.cn/p/e4ca039a2272
- http://www.itdecent.cn/p/a6a03d94d6f7
- http://www.itdecent.cn/p/43b65ed2e166
- https://blog.csdn.net/f641385712/article/details/92801300