Java Spring的refresh方法你知道嗎
spring的refresh方法
前置知識(shí)
方法入口
// org.springframework.context.support.AbstractApplicationContext#refresh
類的結(jié)構(gòu)圖

BeanDefinition 接口定義
public interface BeanDefinition extends AttributeAccessor, BeanMetadataElement {
// 我們可以看到,默認(rèn)只提供 sington 和 prototype 兩種,
// 很多讀者可能知道還有 request, session, globalSession, application, websocket 這幾種,
// 不過(guò),它們屬于基于 web 的擴(kuò)展。
String SCOPE_SINGLETON = ConfigurableBeanFactory.SCOPE_SINGLETON;
String SCOPE_PROTOTYPE = ConfigurableBeanFactory.SCOPE_PROTOTYPE;
// 比較不重要,直接跳過(guò)吧
int ROLE_APPLICATION = 0;
int ROLE_SUPPORT = 1;
int ROLE_INFRASTRUCTURE = 2;
// 設(shè)置父 Bean,這里涉及到 bean 繼承,不是 java 繼承。請(qǐng)參見(jiàn)附錄的詳細(xì)介紹
// 一句話就是:繼承父 Bean 的配置信息而已
void setParentName(String parentName);
// 獲取父 Bean
String getParentName();
// 設(shè)置 Bean 的類名稱,將來(lái)是要通過(guò)反射來(lái)生成實(shí)例的
void setBeanClassName(String beanClassName);
// 獲取 Bean 的類名稱
String getBeanClassName();
// 設(shè)置 bean 的 scope
void setScope(String scope);
String getScope();
// 設(shè)置是否懶加載
void setLazyInit(boolean lazyInit);
boolean isLazyInit();
// 設(shè)置該 Bean 依賴的所有的 Bean,注意,這里的依賴不是指屬性依賴(如 @Autowire 標(biāo)記的),
// 是 depends-on="" 屬性設(shè)置的值。
void setDependsOn(String... dependsOn);
// 返回該 Bean 的所有依賴
String[] getDependsOn();
// 設(shè)置該 Bean 是否可以注入到其他 Bean 中,只對(duì)根據(jù)類型注入有效,
// 如果根據(jù)名稱注入,即使這邊設(shè)置了 false,也是可以的
void setAutowireCandidate(boolean autowireCandidate);
// 該 Bean 是否可以注入到其他 Bean 中
boolean isAutowireCandidate();
// 主要的。同一接口的多個(gè)實(shí)現(xiàn),如果不指定名字的話,Spring 會(huì)優(yōu)先選擇設(shè)置 primary 為 true 的 bean
void setPrimary(boolean primary);
// 是否是 primary 的
boolean isPrimary();
// 如果該 Bean 采用工廠方法生成,指定工廠名稱。對(duì)工廠不熟悉的讀者,請(qǐng)參加附錄
// 一句話就是:有些實(shí)例不是用反射生成的,而是用工廠模式生成的
void setFactoryBeanName(String factoryBeanName);
// 獲取工廠名稱
String getFactoryBeanName();
// 指定工廠類中的 工廠方法名稱
void setFactoryMethodName(String factoryMethodName);
// 獲取工廠類中的 工廠方法名稱
String getFactoryMethodName();
// 構(gòu)造器參數(shù)
ConstructorArgumentValues getConstructorArgumentValues();
// Bean 中的屬性值,后面給 bean 注入屬性值的時(shí)候會(huì)說(shuō)到
MutablePropertyValues getPropertyValues();
// 是否 singleton
boolean isSingleton();
// 是否 prototype
boolean isPrototype();
// 如果這個(gè) Bean 是被設(shè)置為 abstract,那么不能實(shí)例化,
// 常用于作為 父bean 用于繼承,其實(shí)也很少用......
boolean isAbstract();
int getRole();
String getDescription();
String getResourceDescription();
BeanDefinition getOriginatingBeanDefinition();
}
refresh 這里簡(jiǎn)單說(shuō)下為什么是 refresh(),而不是 init() 這種名字的方法。因?yàn)?ApplicationContext 建立起來(lái)以后,其實(shí)我們是可以通過(guò)調(diào)用 refresh() 這個(gè)方法重建的,refresh() 會(huì)將原來(lái)的 ApplicationContext 銷毀,然后再重新執(zhí)行一次初始化操作。
@Override
public void refresh() throws BeansException, IllegalStateException {
// 來(lái)個(gè)鎖,不然 refresh() 還沒(méi)結(jié)束,你又來(lái)個(gè)啟動(dòng)或銷毀容器的操作,那不就亂套了嘛
synchronized (this.startupShutdownMonitor) {
// 準(zhǔn)備工作,記錄下容器的啟動(dòng)時(shí)間、標(biāo)記“已啟動(dòng)”狀態(tài)、處理配置文件中的占位符
prepareRefresh();
// 這步比較關(guān)鍵,這步完成后,配置文件就會(huì)解析成一個(gè)個(gè) Bean 定義,注冊(cè)到 BeanFactory 中,
// 當(dāng)然,這里說(shuō)的 Bean 還沒(méi)有初始化,只是配置信息都提取出來(lái)了,
// 注冊(cè)也只是將這些信息都保存到了注冊(cè)中心(說(shuō)到底核心是一個(gè) beanName-> beanDefinition 的 map)
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
// 設(shè)置 BeanFactory 的類加載器,添加幾個(gè) BeanPostProcessor,手動(dòng)注冊(cè)幾個(gè)特殊的 bean
// 這塊待會(huì)會(huì)展開(kāi)說(shuō)
prepareBeanFactory(beanFactory);
try {
// 【這里需要知道 BeanFactoryPostProcessor 這個(gè)知識(shí)點(diǎn),Bean 如果實(shí)現(xiàn)了此接口,
// 那么在容器初始化以后,Spring 會(huì)負(fù)責(zé)調(diào)用里面的 postProcessBeanFactory 方法?!?
// 這里是提供給子類的擴(kuò)展點(diǎn),到這里的時(shí)候,所有的 Bean 都加載、注冊(cè)完成了,但是都還沒(méi)有初始化
// 具體的子類可以在這步的時(shí)候添加一些特殊的 BeanFactoryPostProcessor 的實(shí)現(xiàn)類或做點(diǎn)什么事
postProcessBeanFactory(beanFactory);
// 調(diào)用 BeanFactoryPostProcessor 各個(gè)實(shí)現(xiàn)類的 postProcessBeanFactory(factory) 方法
invokeBeanFactoryPostProcessors(beanFactory);
// 注冊(cè) BeanPostProcessor 的實(shí)現(xiàn)類,注意看和 BeanFactoryPostProcessor 的區(qū)別
// 此接口兩個(gè)方法: postProcessBeforeInitialization 和 postProcessAfterInitialization
// 兩個(gè)方法分別在 Bean 初始化之前和初始化之后得到執(zhí)行。注意,到這里 Bean 還沒(méi)初始化
registerBeanPostProcessors(beanFactory);
// 初始化當(dāng)前 ApplicationContext 的 MessageSource,國(guó)際化這里就不展開(kāi)說(shuō)了,不然沒(méi)完沒(méi)了了
initMessageSource();
// 初始化當(dāng)前 ApplicationContext 的事件廣播器,這里也不展開(kāi)了
initApplicationEventMulticaster();
// 從方法名就可以知道,典型的模板方法(鉤子方法),
// 具體的子類可以在這里初始化一些特殊的 Bean(在初始化 singleton beans 之前)
onRefresh();
// 注冊(cè)事件監(jiān)聽(tīng)器,監(jiān)聽(tīng)器需要實(shí)現(xiàn) ApplicationListener 接口。這也不是我們的重點(diǎn),過(guò)
registerListeners();
// 重點(diǎn),重點(diǎn),重點(diǎn)
// 初始化所有的 singleton beans
//(lazy-init 的除外)
finishBeanFactoryInitialization(beanFactory);
// 最后,廣播事件,ApplicationContext 初始化完成
finishRefresh();
}
catch (BeansException ex) {
if (logger.isWarnEnabled()) {
logger.warn("Exception encountered during context initialization - " +
"cancelling refresh attempt: " + ex);
}
// Destroy already created singletons to avoid dangling resources.
// 銷毀已經(jīng)初始化的 singleton 的 Beans,以免有些 bean 會(huì)一直占用資源
destroyBeans();
// Reset 'active' flag.
cancelRefresh(ex);
// 把異常往外拋
throw ex;
}
finally {
// Reset common introspection caches in Spring's core, since we
// might not ever need metadata for singleton beans anymore...
resetCommonCaches();
}
}
}
創(chuàng)建 Bean 容器前的準(zhǔn)備工作
// 準(zhǔn)備工作
protected void prepareRefresh() {
// 記錄啟動(dòng)時(shí)間,
// 將 active 屬性設(shè)置為 true,closed 屬性設(shè)置為 false,它們都是 AtomicBoolean 類型
this.startupDate = System.currentTimeMillis();
this.closed.set(false);
this.active.set(true);
if (logger.isInfoEnabled()) {
logger.info("Refreshing " + this);
}
// Initialize any placeholder property sources in the context environment 初始化上下文環(huán)境中的任何占位符屬性源。
initPropertySources();
// 校驗(yàn) xml 配置文件
getEnvironment().validateRequiredProperties();
// 初始化事件集合
this.earlyApplicationEvents = new LinkedHashSet<ApplicationEvent>();
}
創(chuàng)建 Bean 容器,加載并注冊(cè) Bean
// 最重要的方法之一,這里將會(huì)初始化 BeanFactory、加載 Bean、注冊(cè) Bean 等等。
protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
// 關(guān)閉舊的 BeanFactory (如果有),創(chuàng)建新的 BeanFactory,加載 Bean 定義、注冊(cè) Bean 等等
refreshBeanFactory();
// 返回剛剛創(chuàng)建的 BeanFactory
ConfigurableListableBeanFactory beanFactory = getBeanFactory();
if (logger.isDebugEnabled()) {
logger.debug("Bean factory for " + getDisplayName() + ": " + beanFactory);
}
return beanFactory;
}
// refreshBeanFactory
@Override
protected final void refreshBeanFactory() throws BeansException {
// 如果 ApplicationContext 中已經(jīng)加載過(guò) BeanFactory 了,銷毀所有 Bean,關(guān)閉 BeanFactory
// 注意,應(yīng)用中 BeanFactory 本來(lái)就是可以多個(gè)的,這里可不是說(shuō)應(yīng)用全局是否有 BeanFactory,而是當(dāng)前
// ApplicationContext 是否有 BeanFactory
if (hasBeanFactory()) {
destroyBeans();
closeBeanFactory();
}
try {
// 初始化一個(gè) DefaultListableBeanFactory,為什么用這個(gè),我們馬上說(shuō)。
DefaultListableBeanFactory beanFactory = createBeanFactory();
// 用于 BeanFactory 的序列化,我想大部分人應(yīng)該都用不到
beanFactory.setSerializationId(getId());
// 下面這兩個(gè)方法很重要,別跟丟了,具體細(xì)節(jié)之后說(shuō)
// 設(shè)置 BeanFactory 的兩個(gè)配置屬性:是否允許 Bean 覆蓋、是否允許循環(huán)引用
customizeBeanFactory(beanFactory);
// 加載 Bean 到 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);
}
}
// customizeBeanFactory 配置是否允許 BeanDefinition 覆蓋、是否允許循環(huán)引用。
protected void customizeBeanFactory(DefaultListableBeanFactory beanFactory) {
if (this.allowBeanDefinitionOverriding != null) {
// 是否允許 Bean 定義覆蓋 在配置文件中定義 bean 時(shí)使用了相同的 id 或 name,默認(rèn)情況下,allowBeanDefinitionOverriding 屬性為 null,如果在同一配置文件中重復(fù)了,會(huì)拋錯(cuò),但是如果不是同一配置文件中,會(huì)發(fā)生覆蓋。
beanFactory.setAllowBeanDefinitionOverriding(this.allowBeanDefinitionOverriding);
}
if (this.allowCircularReferences != null) {
// 是否允許 Bean 間的循環(huán)依賴 如:A 依賴 B,而 B 依賴 A?;?A 依賴 B,B 依賴 C,而 C 依賴 A。
beanFactory.setAllowCircularReferences(this.allowCircularReferences);
}
}
// loadBeanDefinitions 加載bean,放入 BeanFactory 中 org.springframework.context.support.AbstractXmlApplicationContext#loadBeanDefinitions(org.springframework.beans.factory.support.DefaultListableBeanFactory)
/** 我們可以看到,此方法將通過(guò)一個(gè) XmlBeanDefinitionReader 實(shí)例來(lái)加載各個(gè) Bean。*/
@Override
protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) throws BeansException, IOException {
// 給這個(gè) BeanFactory 實(shí)例化一個(gè) XmlBeanDefinitionReader
XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory);
// Configure the bean definition reader with this context's
// resource loading environment.
beanDefinitionReader.setEnvironment(this.getEnvironment());
beanDefinitionReader.setResourceLoader(this);
beanDefinitionReader.setEntityResolver(new ResourceEntityResolver(this));
// 初始化 BeanDefinitionReader,其實(shí)這個(gè)是提供給子類覆寫的,
// 我看了一下,沒(méi)有類覆寫這個(gè)方法,我們姑且當(dāng)做不重要吧
initBeanDefinitionReader(beanDefinitionReader);
// 重點(diǎn)來(lái)了,繼續(xù)往下
loadBeanDefinitions(beanDefinitionReader);
}
protected void loadBeanDefinitions(XmlBeanDefinitionReader reader) throws BeansException, IOException {
Resource[] configResources = getConfigResources();
if (configResources != null) {
// 往下看
reader.loadBeanDefinitions(configResources);
}
String[] configLocations = getConfigLocations();
if (configLocations != null) {
// 2
reader.loadBeanDefinitions(configLocations);
}
}
// 上面雖然有兩個(gè)分支,不過(guò)第二個(gè)分支很快通過(guò)解析路徑轉(zhuǎn)換為 Resource 以后也會(huì)進(jìn)到這里
@Override
public int loadBeanDefinitions(Resource... resources) throws BeanDefinitionStoreException {
Assert.notNull(resources, "Resource array must not be null");
int counter = 0;
// 注意這里是個(gè) for 循環(huán),也就是每個(gè)文件是一個(gè) resource
for (Resource resource : resources) {
// 繼續(xù)往下看
counter += loadBeanDefinitions(resource);
}
// 最后返回 counter,表示總共加載了多少的 BeanDefinition
return counter;
}
// XmlBeanDefinitionReader 303
@Override
public int loadBeanDefinitions(Resource resource) throws BeanDefinitionStoreException {
return loadBeanDefinitions(new EncodedResource(resource));
}
// XmlBeanDefinitionReader 314
public int loadBeanDefinitions(EncodedResource encodedResource) throws BeanDefinitionStoreException {
Assert.notNull(encodedResource, "EncodedResource must not be null");
if (logger.isInfoEnabled()) {
logger.info("Loading XML bean definitions from " + encodedResource.getResource());
}
// 用一個(gè) ThreadLocal 來(lái)存放配置文件資源
Set<EncodedResource> currentResources = this.resourcesCurrentlyBeingLoaded.get();
if (currentResources == null) {
currentResources = new HashSet<EncodedResource>(4);
this.resourcesCurrentlyBeingLoaded.set(currentResources);
}
if (!currentResources.add(encodedResource)) {
throw new BeanDefinitionStoreException(
"Detected cyclic loading of " + encodedResource + " - check your import definitions!");
}
try {
InputStream inputStream = encodedResource.getResource().getInputStream();
try {
InputSource inputSource = new InputSource(inputStream);
if (encodedResource.getEncoding() != null) {
inputSource.setEncoding(encodedResource.getEncoding());
}
// 核心部分是這里,往下面看
return doLoadBeanDefinitions(inputSource, encodedResource.getResource());
}
finally {
inputStream.close();
}
}
catch (IOException ex) {
throw new BeanDefinitionStoreException(
"IOException parsing XML document from " + encodedResource.getResource(), ex);
}
finally {
currentResources.remove(encodedResource);
if (currentResources.isEmpty()) {
this.resourcesCurrentlyBeingLoaded.remove();
}
}
}
// 還在這個(gè)文件中,第 388 行
protected int doLoadBeanDefinitions(InputSource inputSource, Resource resource)
throws BeanDefinitionStoreException {
try {
// 這里就不看了,將 xml 文件轉(zhuǎn)換為 Document 對(duì)象
Document doc = doLoadDocument(inputSource, resource);
// 繼續(xù)
return registerBeanDefinitions(doc, resource);
}
catch (...
}
// 還在這個(gè)文件中,第 505 行
// 返回值:返回從當(dāng)前配置文件加載了多少數(shù)量的 Bean
public int registerBeanDefinitions(Document doc, Resource resource) throws BeanDefinitionStoreException {
BeanDefinitionDocumentReader documentReader = createBeanDefinitionDocumentReader();
int countBefore = getRegistry().getBeanDefinitionCount();
// 這里
documentReader.registerBeanDefinitions(doc, createReaderContext(resource));
return getRegistry().getBeanDefinitionCount() - countBefore;
}
// DefaultBeanDefinitionDocumentReader 90
@Override
public void registerBeanDefinitions(Document doc, XmlReaderContext readerContext) {
this.readerContext = readerContext;
logger.debug("Loading bean definitions");
Element root = doc.getDocumentElement();
// 從 xml 根節(jié)點(diǎn)開(kāi)始解析文件
doRegisterBeanDefinitions(root);
}
// doRegisterBeanDefinitions 經(jīng)過(guò)漫長(zhǎng)的鏈路,一個(gè)配置文件終于轉(zhuǎn)換為一顆 DOM 樹了,注意,這里指的是其中一個(gè)配置文件,不是所有的,讀者可以看到上面有個(gè) for 循環(huán)的。下面開(kāi)始從根節(jié)點(diǎn)開(kāi)始解析:
// DefaultBeanDefinitionDocumentReader 116
protected void doRegisterBeanDefinitions(Element root) {
// 我們看名字就知道,BeanDefinitionParserDelegate 必定是一個(gè)重要的類,它負(fù)責(zé)解析 Bean 定義,
// 這里為什么要定義一個(gè) parent? 看到后面就知道了,是遞歸問(wèn)題,
// 因?yàn)?<beans /> 內(nèi)部是可以定義 <beans /> 的,所以這個(gè)方法的 root 其實(shí)不一定就是 xml 的根節(jié)點(diǎn),也可以是嵌套在里面的 <beans /> 節(jié)點(diǎn),從源碼分析的角度,我們當(dāng)做根節(jié)點(diǎn)就好了
BeanDefinitionParserDelegate parent = this.delegate;
this.delegate = createDelegate(getReaderContext(), root, parent);
if (this.delegate.isDefaultNamespace(root)) {
// 這塊說(shuō)的是根節(jié)點(diǎn) <beans ... profile="dev" /> 中的 profile 是否是當(dāng)前環(huán)境需要的,
// 如果當(dāng)前環(huán)境配置的 profile 不包含此 profile,那就直接 return 了,不對(duì)此 <beans /> 解析
// 不熟悉 profile 為何物,不熟悉怎么配置 profile 讀者的請(qǐng)移步附錄區(qū)
String profileSpec = root.getAttribute(PROFILE_ATTRIBUTE);
if (StringUtils.hasText(profileSpec)) {
String[] specifiedProfiles = StringUtils.tokenizeToStringArray(
profileSpec, BeanDefinitionParserDelegate.MULTI_VALUE_ATTRIBUTE_DELIMITERS);
if (!getReaderContext().getEnvironment().acceptsProfiles(specifiedProfiles)) {
if (logger.isInfoEnabled()) {
logger.info("Skipped XML bean definition file due to specified profiles [" + profileSpec +
"] not matching: " + getReaderContext().getResource());
}
return;
}
}
}
preProcessXml(root); // 鉤子 preProcessXml(root) 和 postProcessXml(root) 是給子類用的鉤子方法,鑒于沒(méi)有被使用到,也不是我們的重點(diǎn),我們直接跳過(guò)。
// 往下看
parseBeanDefinitions(root, this.delegate);
postProcessXml(root); // 鉤子
this.delegate = parent;
}
// default namespace 涉及到的就四個(gè)標(biāo)簽 <import />、<alias />、<bean /> 和 <beans />,
// 其他的屬于 custom 的
protected void parseBeanDefinitions(Element root, BeanDefinitionParserDelegate delegate) {
if (delegate.isDefaultNamespace(root)) {
NodeList nl = root.getChildNodes();
for (int i = 0; i < nl.getLength(); i++) {
Node node = nl.item(i);
if (node instanceof Element) {
Element ele = (Element) node;
if (delegate.isDefaultNamespace(ele)) {
// 解析 default namespace 下面的幾個(gè)元素
parseDefaultElement(ele, delegate);
}
else {
// 解析其他 namespace 的元素
delegate.parseCustomElement(ele);
}
}
}
}
else {
delegate.parseCustomElement(root);
}
}
private void parseDefaultElement(Element ele, BeanDefinitionParserDelegate delegate) {
if (delegate.nodeNameEquals(ele, IMPORT_ELEMENT)) {
// 處理 <import /> 標(biāo)簽
importBeanDefinitionResource(ele);
}
else if (delegate.nodeNameEquals(ele, ALIAS_ELEMENT)) {
// 處理 <alias /> 標(biāo)簽定義
// <alias name="fromName" alias="toName"/>
processAliasRegistration(ele);
}
else if (delegate.nodeNameEquals(ele, BEAN_ELEMENT)) {
// 處理 <bean /> 標(biāo)簽定義,這也算是我們的重點(diǎn)吧
processBeanDefinition(ele, delegate);
}
else if (delegate.nodeNameEquals(ele, NESTED_BEANS_ELEMENT)) {
// 如果碰到的是嵌套的 <beans /> 標(biāo)簽,需要遞歸
doRegisterBeanDefinitions(ele);
}
}
// DefaultBeanDefinitionDocumentReader 298
protected void processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate) {
// 將 <bean /> 節(jié)點(diǎn)中的信息提取出來(lái),然后封裝到一個(gè) BeanDefinitionHolder 中,細(xì)節(jié)往下看
BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele);
// 下面的幾行先不要看,跳過(guò)先,跳過(guò)先,跳過(guò)先,后面會(huì)繼續(xù)說(shuō)的
if (bdHolder != null) {
bdHolder = delegate.decorateBeanDefinitionIfRequired(ele, bdHolder);
try {
// Register the final decorated instance.
BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, getReaderContext().getRegistry());
}
catch (BeanDefinitionStoreException ex) {
getReaderContext().error("Failed to register bean definition with name '" +
bdHolder.getBeanName() + "'", ele, ex);
}
// Send registration event.
getReaderContext().fireComponentRegistered(new BeanComponentDefinition(bdHolder));
}
}
// BeanDefinitionParserDelegate 428
public BeanDefinitionHolder parseBeanDefinitionElement(Element ele) {
return parseBeanDefinitionElement(ele, null);
}
public BeanDefinitionHolder parseBeanDefinitionElement(Element ele, BeanDefinition containingBean) {
String id = ele.getAttribute(ID_ATTRIBUTE);
String nameAttr = ele.getAttribute(NAME_ATTRIBUTE);
List<String> aliases = new ArrayList<String>();
// 將 name 屬性的定義按照 “逗號(hào)、分號(hào)、空格” 切分,形成一個(gè) 別名列表數(shù)組,
// 當(dāng)然,如果你不定義 name 屬性的話,就是空的了
// 我在附錄中簡(jiǎn)單介紹了一下 id 和 name 的配置,大家可以看一眼,有個(gè)20秒就可以了
if (StringUtils.hasLength(nameAttr)) {
String[] nameArr = StringUtils.tokenizeToStringArray(nameAttr, MULTI_VALUE_ATTRIBUTE_DELIMITERS);
aliases.addAll(Arrays.asList(nameArr));
}
String beanName = id;
// 如果沒(méi)有指定id, 那么用別名列表的第一個(gè)名字作為beanName
if (!StringUtils.hasText(beanName) && !aliases.isEmpty()) {
beanName = aliases.remove(0);
if (logger.isDebugEnabled()) {
logger.debug("No XML 'id' specified - using '" + beanName +
"' as bean name and " + aliases + " as aliases");
}
}
if (containingBean == null) {
checkNameUniqueness(beanName, aliases, ele);
}
// 根據(jù) <bean ...>...</bean> 中的配置創(chuàng)建 BeanDefinition,然后把配置中的信息都設(shè)置到實(shí)例中,
// 細(xì)節(jié)后面細(xì)說(shuō),先知道下面這行結(jié)束后,一個(gè) BeanDefinition 實(shí)例就出來(lái)了。
AbstractBeanDefinition beanDefinition = parseBeanDefinitionElement(ele, beanName, containingBean);
// 到這里,整個(gè) <bean /> 標(biāo)簽就算解析結(jié)束了,一個(gè) BeanDefinition 就形成了。
if (beanDefinition != null) {
// 如果都沒(méi)有設(shè)置 id 和 name,那么此時(shí)的 beanName 就會(huì)為 null,進(jìn)入下面這塊代碼產(chǎn)生
// 如果讀者不感興趣的話,我覺(jué)得不需要關(guān)心這塊代碼,對(duì)本文源碼分析來(lái)說(shuō),這些東西不重要
if (!StringUtils.hasText(beanName)) {
try {
if (containingBean != null) {// 按照我們的思路,這里 containingBean 是 null 的
beanName = BeanDefinitionReaderUtils.generateBeanName(
beanDefinition, this.readerContext.getRegistry(), true);
}
else {
// 如果我們不定義 id 和 name,那么我們引言里的那個(gè)例子:
// 1. beanName 為:com.javadoop.example.MessageServiceImpl#0
// 2. beanClassName 為:com.javadoop.example.MessageServiceImpl
beanName = this.readerContext.generateBeanName(beanDefinition);
String beanClassName = beanDefinition.getBeanClassName();
if (beanClassName != null &&
beanName.startsWith(beanClassName) && beanName.length() > beanClassName.length() &&
!this.readerContext.getRegistry().isBeanNameInUse(beanClassName)) {
// 把 beanClassName 設(shè)置為 Bean 的別名
aliases.add(beanClassName);
}
}
if (logger.isDebugEnabled()) {
logger.debug("Neither XML 'id' nor 'name' specified - " +
"using generated bean name [" + beanName + "]");
}
}
catch (Exception ex) {
error(ex.getMessage(), ele);
return null;
}
}
String[] aliasesArray = StringUtils.toStringArray(aliases);
// 返回 BeanDefinitionHolder
return new BeanDefinitionHolder(beanDefinition, beanName, aliasesArray);
}
return null;
}
看到這里的時(shí)候,我覺(jué)得讀者就應(yīng)該站在高處看 ApplicationContext 了,ApplicationContext 繼承自 BeanFactory,但是它不應(yīng)該被理解為 BeanFactory 的實(shí)現(xiàn)類,而是說(shuō)其內(nèi)部持有一個(gè)實(shí)例化的 BeanFactory(DefaultListableBeanFactory)。以后所有的 BeanFactory 相關(guān)的操作其實(shí)是委托給這個(gè)實(shí)例來(lái)處理的。
我們說(shuō)說(shuō)為什么選擇實(shí)例化 DefaultListableBeanFactory ?前面我們說(shuō)了有個(gè)很重要的接口 ConfigurableListableBeanFactory,它實(shí)現(xiàn)了 BeanFactory 下面一層的所有三個(gè)接口,我把之前的繼承圖再拿過(guò)來(lái)大家再仔細(xì)看一下:

我們可以看到 ConfigurableListableBeanFactory 只有一個(gè)實(shí)現(xiàn)類DefaultListableBeanFactory,而且實(shí)現(xiàn)類 DefaultListableBeanFactory 還通過(guò)實(shí)現(xiàn)右邊的 AbstractAutowireCapableBeanFactory 通吃了右路。所以結(jié)論就是,最底下這個(gè)家伙 DefaultListableBeanFactory 基本上是最牛的 BeanFactory 了,這也是為什么這邊會(huì)使用這個(gè)類來(lái)實(shí)例化的原因。
循環(huán)依賴

總結(jié)
本篇文章就到這里了,希望能夠給你帶來(lái)幫助,也希望您能夠多多關(guān)注腳本之家的更多內(nèi)容!
相關(guān)文章
Springboot?2.x?RabbitTemplate默認(rèn)消息持久化的原因解析
這篇文章主要介紹了Springboot?2.x?RabbitTemplate默認(rèn)消息持久化的原因解析,本文通過(guò)示例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2022-03-03
10個(gè)實(shí)現(xiàn)Java集合,Map類型自由轉(zhuǎn)換的實(shí)用工具方法
這篇文章主要為大家整理了整理了10個(gè)實(shí)用工具方法,可以滿足?Collection、List、Set、Map?之間各種類型轉(zhuǎn)化,文中的示例代碼講解詳細(xì),需要的可以參考下2023-09-09
Spring boot打包jar分離lib和resources方法實(shí)例
這篇文章主要介紹了Spring boot打包jar分離lib和resources方法實(shí)例,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-05-05
面試題:Java 實(shí)現(xiàn)查找旋轉(zhuǎn)數(shù)組的最小數(shù)字
這篇文章主要介紹了Java 實(shí)現(xiàn)查找旋轉(zhuǎn)數(shù)組的最小數(shù)字,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2018-07-07
基于eclipse.ini內(nèi)存設(shè)置的問(wèn)題詳解
本篇文章是對(duì)eclipse.ini內(nèi)存設(shè)置的問(wèn)題進(jìn)行了詳細(xì)的分析介紹,需要的朋友參考下2013-05-05
Spring boot 跳轉(zhuǎn)到j(luò)sp頁(yè)面的實(shí)現(xiàn)方法
本篇文章主要介紹了Spring boot 跳轉(zhuǎn)到j(luò)sp頁(yè)面的實(shí)現(xiàn)方法,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2017-04-04

