Spring啓動過程寫的過於冗雜,若是對於這部分不感興趣能夠直接跳到Dubbo和Spring的關係,依然可以愉快的閱讀。java
第一步:node
ClassPathXmlApplicationContext的構造方法:spring
public class ClassPathXmlApplicationContext extends AbstractXmlApplicationContext {
private Resource[] configResources;
// 若是已經有 ApplicationContext 並須要配置成父子關係,那麼調用這個構造方法
public ClassPathXmlApplicationContext(ApplicationContext parent) {
super(parent);
}
...
public ClassPathXmlApplicationContext(String[] configLocations, boolean refresh, ApplicationContext parent) throws BeansException {
super(parent);
// 根據提供的路徑,處理成配置文件數組(以分號、逗號、空格、tab、換行符分割)
setConfigLocations(configLocations);
if (refresh) {
refresh(); // 核心方法
}
}
...
}
複製代碼
接下來,就是refresh(),將原來的ApplicationContext銷燬,而後從新執行一次初始化操做。express
@Override
public void refresh() throws BeansException, IllegalStateException {
// 來個鎖,否則 refresh() 還沒結束,你又來個啓動或銷燬容器的操做,那不就亂套了嘛
synchronized (this.startupShutdownMonitor) {
// 準備工做,記錄下容器的啓動時間、標記「已啓動」狀態、處理配置文件中的佔位符
prepareRefresh();
// 這步比較關鍵,這步完成後,配置文件就會解析成一個個 Bean 定義,註冊到 BeanFactory 中,
// 固然,這裏說的 Bean 尚未初始化,只是配置信息都提取出來了,
// 註冊也只是將這些信息都保存到了註冊中心(說到底核心是一個 beanName-> beanDefinition 的 map)
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
// 設置 BeanFactory 的類加載器,添加幾個 BeanPostProcessor,手動註冊幾個特殊的 bean
// 這塊待會會展開說
prepareBeanFactory(beanFactory);
try {
// 【這裏須要知道 BeanFactoryPostProcessor 這個知識點,Bean 若是實現了此接口,
// 那麼在容器初始化之後,Spring 會負責調用裏面的 postProcessBeanFactory 方法。】
// 這裏是提供給子類的擴展點,到這裏的時候,全部的 Bean 都加載、註冊完成了,可是都尚未初始化
// 具體的子類能夠在這步的時候添加一些特殊的 BeanFactoryPostProcessor 的實現類或作點什麼事
postProcessBeanFactory(beanFactory);
// 調用 BeanFactoryPostProcessor 各個實現類的 postProcessBeanFactory(factory) 方法
invokeBeanFactoryPostProcessors(beanFactory);
// 註冊 BeanPostProcessor 的實現類,注意看和 BeanFactoryPostProcessor 的區別
// 此接口兩個方法: postProcessBeforeInitialization 和 postProcessAfterInitialization
// 兩個方法分別在 Bean 初始化以前和初始化以後獲得執行。注意,到這裏 Bean 還沒初始化
registerBeanPostProcessors(beanFactory);
// 初始化當前 ApplicationContext 的 MessageSource,國際化這裏就不展開說了,否則沒完沒了了
initMessageSource();
// 初始化當前 ApplicationContext 的事件廣播器,這裏也不展開了
initApplicationEventMulticaster();
// 從方法名就能夠知道,典型的模板方法(鉤子方法),
// 具體的子類能夠在這裏初始化一些特殊的 Bean(在初始化 singleton beans 以前)
onRefresh();
// 註冊事件監聽器,監聽器須要實現 ApplicationListener 接口。這也不是咱們的重點,過
registerListeners();
// 重點,重點,重點
// 初始化全部的 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.
// 銷燬已經初始化的 singleton 的 Beans,以避免有些 bean 會一直佔用資源
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();
}
}
}
複製代碼
建立Bean容器前的準備工做:apache
protected void prepareRefresh() {
// 記錄啓動時間,
// 將 active 屬性設置爲 true,closed 屬性設置爲 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
initPropertySources();
// 校驗 xml 配置文件
getEnvironment().validateRequiredProperties();
this.earlyApplicationEvents = new LinkedHashSet<ApplicationEvent>();
}
複製代碼
建立Bean容器,加載並註冊Bean數組
這裏會初始化BeanFactory、加載Bean、註冊Bean等等。bash
AbstractApplicationContext.javaapp
protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
//關閉就得BeanFactory,建立新的BeanFactory,加載Bean定義、註冊Bean等等。
this.refreshBeanFactory();
//返回剛剛建立的BeanFactory
ConfigurableListableBeanFactory beanFactory = this.getBeanFactory();
if (this.logger.isDebugEnabled()) {
this.logger.debug("Bean factory for " + this.getDisplayName() + ": " + beanFactory);
}
return beanFactory;
}
複製代碼
AbstractRefreshableApplicationContext.java 120框架
@Override
protected final void refreshBeanFactory() throws BeansException {
// 若是 ApplicationContext 中已經加載過 BeanFactory 了,銷燬全部 Bean,關閉 BeanFactory
// 注意,應用中 BeanFactory 原本就是能夠多個的,這裏可不是說應用全局是否有 BeanFactory,而是當前
// ApplicationContext 是否有 BeanFactory
if (hasBeanFactory()) {
destroyBeans();
closeBeanFactory();
}
try {
// 初始化一個 DefaultListableBeanFactory,爲何用這個,咱們立刻說。
DefaultListableBeanFactory beanFactory = createBeanFactory();
// 用於 BeanFactory 的序列化,我想不部分人應該都用不到
beanFactory.setSerializationId(getId());
// 下面這兩個方法很重要,別跟丟了,具體細節以後說
// 設置 BeanFactory 的兩個配置屬性:是否容許 Bean 覆蓋、是否容許循環引用
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(beanFactory)less
protected void customizeBeanFactory(DefaultListableBeanFactory beanFactory) {
if (this.allowBeanDefinitionOverriding != null) {
// 是否容許 Bean 定義覆蓋
beanFactory.setAllowBeanDefinitionOverriding(this.allowBeanDefinitionOverriding);
}
if (this.allowCircularReferences != null) {
// 是否容許 Bean 間的循環依賴
beanFactory.setAllowCircularReferences(this.allowCircularReferences);
}
}
複製代碼
AbstractXmlApplicationContext.java 80 loadBeanDefinitions(beanFactory)
/** 咱們能夠看到,此方法將經過一個 XmlBeanDefinitionReader 實例來加載各個 Bean。*/
@Override
protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) throws BeansException, IOException {
// 給這個 BeanFactory 實例化一個 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,其實這個是提供給子類覆寫的,
// 我看了一下,沒有類覆寫這個方法,咱們姑且當作不重要吧
initBeanDefinitionReader(beanDefinitionReader);
// 重點來了,繼續往下
loadBeanDefinitions(beanDefinitionReader);
}
複製代碼
如今還在這個類中,接下來用剛剛初始化的 Reader 開始來加載 xml 配置,這塊代碼讀者能夠選擇性跳過,不是很重要。也就是說,下面這個代碼塊,讀者能夠很輕鬆地略過。
// AbstractXmlApplicationContext.java 120
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);
}
}
// 上面雖然有兩個分支,不過第二個分支很快經過解析路徑轉換爲 Resource 之後也會進到這裏
@Override
public int loadBeanDefinitions(Resource... resources) throws BeanDefinitionStoreException {
Assert.notNull(resources, "Resource array must not be null");
int counter = 0;
// 注意這裏是個 for 循環,也就是每一個文件是一個 resource
for (Resource resource : resources) {
// 繼續往下看
counter += loadBeanDefinitions(resource);
}
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());
}
// 用一個 ThreadLocal 來存放全部的配置文件資源
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();
}
}
}
// 還在這個文件中,第 388 行
protected int doLoadBeanDefinitions(InputSource inputSource, Resource resource) throws BeanDefinitionStoreException {
try {
// 這裏就不看了
Document doc = doLoadDocument(inputSource, resource);
// 繼續
return registerBeanDefinitions(doc, resource);
}
catch (...
}
// 還在這個文件中,第 505 行
// 返回從當前配置文件加載了多少數量的 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();
doRegisterBeanDefinitions(root);
}
複製代碼
通過漫長的鏈路,一個配置文件終於轉換爲一顆DOM樹了,注意,這裏指的是其中一個配置文件,不是全部。下面從根節點開始解析:
doRegisterBeanDefinitions:
// DefaultBeanDefinitionDocumentReader 116
protected void doRegisterBeanDefinitions(Element root) {
// 咱們看名字就知道,BeanDefinitionParserDelegate 一定是一個重要的類,它負責解析 Bean 定義,
// 這裏爲何要定義一個 parent? 看到後面就知道了,是遞歸問題,
// 由於 <beans /> 內部是能夠定義 <beans /> 的,因此這個方法的 root 其實不必定就是 xml 的根節點,也能夠是嵌套在裏面的 <beans /> 節點,從源碼分析的角度,咱們當作根節點就行了
BeanDefinitionParserDelegate parent = this.delegate;
this.delegate = createDelegate(getReaderContext(), root, parent);
if (this.delegate.isDefaultNamespace(root)) {
// 這塊說的是根節點 <beans ... profile="dev" /> 中的 profile 是不是當前環境須要的,
// 若是當前環境配置的 profile 不包含此 profile,那就直接 return 了,不對此 <beans /> 解析
// 不熟悉 profile 爲什麼物,不熟悉怎麼配置 profile 讀者的請移步附錄區
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); // 鉤子
parseBeanDefinitions(root, this.delegate);
postProcessXml(root); // 鉤子
this.delegate = parent;
}
複製代碼
接下來,看核心解析方法parseBeanDefinitions(roo,this.delegate):
// default namespace 涉及到的就四個標籤 <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)) {
parseDefaultElement(ele, delegate);
}
else {
delegate.parseCustomElement(ele);
}
}
}
}
else {
delegate.parseCustomElement(root);
}
}
複製代碼
從上面的代碼,咱們能夠看到,對於每一個配置來講,分別進入到 parseDefaultElement(ele, delegate); 和 delegate.parseCustomElement(ele); 這兩個分支了。
parseDefaultElement(ele, delegate) 表明解析的節點是 <import />
、<alias />
、<bean />
、<beans />
這幾個。
這裏的四個標籤之因此是 default 的,是由於它們是處於這個 namespace 下定義的:
http://www.springframework.org/schema/beans
複製代碼
回過神來,看看處理 default 標籤的方法:
private void parseDefaultElement(Element ele, BeanDefinitionParserDelegate delegate) {
if (delegate.nodeNameEquals(ele, IMPORT_ELEMENT)) {
// 處理 <import /> 標籤
importBeanDefinitionResource(ele);
}
else if (delegate.nodeNameEquals(ele, ALIAS_ELEMENT)) {
// 處理 <alias /> 標籤訂義
// <alias name="fromName" alias="toName"/>
processAliasRegistration(ele);
}
else if (delegate.nodeNameEquals(ele, BEAN_ELEMENT)) {
// 處理 <bean /> 標籤訂義,這也算是咱們的重點吧
processBeanDefinition(ele, delegate);
}
else if (delegate.nodeNameEquals(ele, NESTED_BEANS_ELEMENT)) {
// 若是碰到的是嵌套的 <beans /> 標籤,須要遞歸
doRegisterBeanDefinitions(ele);
}
}
複製代碼
若是每一個標籤都說,那我不吐血,大家都要吐血了。咱們挑咱們的重點 <bean />
標籤出來講。
processBeanDefinition
下面是 processBeanDefinition 解析 <bean />
標籤:
// DefaultBeanDefinitionDocumentReader 298
protected void processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate) {
// 將 <bean /> 節點中的信息提取出來,而後封裝到一個 BeanDefinitionHolder 中,細節往下看
BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele);
// 下面的幾行先不要看,跳過先,跳過先,跳過先,後面會繼續說的
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));
}
}
複製代碼
繼續往下看怎麼解析以前,咱們先看下 標籤中能夠定義哪些屬性:
Property | |
---|---|
class | 類的全限定名 |
name | 可指定 id、name(用逗號、分號、空格分隔) |
scope | 做用域 |
constructor arguments | 指定構造參數 |
properties | 設置屬性的值 |
autowiring mode | no(默認值)、byName、byType、 constructor |
lazy-initialization mode | 是否懶加載(若是被非懶加載的bean依賴了那麼其實也就不能懶加載了) |
initialization method | bean 屬性設置完成後,會調用這個方法 |
destruction method | bean 銷燬後的回調方法 |
上面表格中的內容我想你們都很是熟悉吧,若是不熟悉,那就是你不夠了解 Spring 的配置了。
簡單地說就是像下面這樣子:
<bean id="exampleBean" name="name1, name2, name3" class="com.javadoop.ExampleBean" scope="singleton" lazy-init="true" init-method="init" destroy-method="cleanup">
<!-- 能夠用下面三種形式指定構造參數 -->
<constructor-arg type="int" value="7500000"/>
<constructor-arg name="years" value="7500000"/>
<constructor-arg index="0" value="7500000"/>
<!-- property 的幾種狀況 -->
<property name="beanOne">
<ref bean="anotherExampleBean"/>
</property>
<property name="beanTwo" ref="yetAnotherBean"/>
<property name="integerProperty" value="1"/>
</bean>
複製代碼
固然,除了上面舉例出來的這些,還有 factory-bean、factory-method、<lockup-method />
、<replaced-method />
、<meta />
、<qualifier />
這幾個,你們是否是熟悉呢?
有了以上這些知識之後,咱們再繼續往裏看怎麼解析 bean 元素,是怎麼轉換到 BeanDefinitionHolder 的。
// 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 屬性的定義按照 」逗號、分號、空格「 切分,造成一個別名列表數組,
// 固然,若是你不定義的話,就是空的了
// 我在附錄中簡單介紹了一下 id 和 name 的配置,你們能夠看一眼,有個20秒就能夠了
if (StringUtils.hasLength(nameAttr)) {
String[] nameArr = StringUtils.tokenizeToStringArray(nameAttr, MULTI_VALUE_ATTRIBUTE_DELIMITERS);
aliases.addAll(Arrays.asList(nameArr));
}
String beanName = id;
// 若是沒有指定id, 那麼用別名列表的第一個名字做爲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);
}
// 根據 <bean ...>...</bean> 中的配置建立 BeanDefinition,而後把配置中的信息都設置到實例中,
// 細節後面再說
AbstractBeanDefinition beanDefinition = parseBeanDefinitionElement(ele, beanName, containingBean);
// 到這裏,整個 <bean /> 標籤就算解析結束了,一個 BeanDefinition 就造成了。
if (beanDefinition != null) {
// 若是都沒有設置 id 和 name,那麼此時的 beanName 就會爲 null,進入下面這塊代碼產生
// 若是讀者不感興趣的話,我以爲不須要關心這塊代碼,對本文源碼分析來講,這些東西不重要
if (!StringUtils.hasText(beanName)) {
try {
if (containingBean != null) {// 按照咱們的思路,這裏 containingBean 是 null 的
beanName = BeanDefinitionReaderUtils.generateBeanName(
beanDefinition, this.readerContext.getRegistry(), true);
}
else {
// 若是咱們不定義 id 和 name,那麼咱們引言裏的那個例子:
// 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 設置爲 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;
}
複製代碼
看看怎麼根據配置建立 BeanDefinition:
public AbstractBeanDefinition parseBeanDefinitionElement( Element ele, String beanName, BeanDefinition containingBean) {
this.parseState.push(new BeanEntry(beanName));
String className = null;
if (ele.hasAttribute(CLASS_ATTRIBUTE)) {
className = ele.getAttribute(CLASS_ATTRIBUTE).trim();
}
try {
String parent = null;
if (ele.hasAttribute(PARENT_ATTRIBUTE)) {
parent = ele.getAttribute(PARENT_ATTRIBUTE);
}
// 建立 BeanDefinition,而後設置類信息而已,很簡單,就不貼代碼了
AbstractBeanDefinition bd = createBeanDefinition(className, parent);
// 設置 BeanDefinition 的一堆屬性,這些屬性定義在 AbstractBeanDefinition 中
parseBeanDefinitionAttributes(ele, beanName, containingBean, bd);
bd.setDescription(DomUtils.getChildElementValueByTagName(ele, DESCRIPTION_ELEMENT));
/** * 下面的一堆是解析 <bean>......</bean> 內部的子元素, * 解析出來之後的信息都放到 bd 的屬性中 */
// 解析 <meta />
parseMetaElements(ele, bd);
// 解析 <lookup-method />
parseLookupOverrideSubElements(ele, bd.getMethodOverrides());
// 解析 <replaced-method />
parseReplacedMethodSubElements(ele, bd.getMethodOverrides());
// 解析 <constructor-arg />
parseConstructorArgElements(ele, bd);
// 解析 <property />
parsePropertyElements(ele, bd);
// 解析 <qualifier />
parseQualifierElements(ele, bd);
bd.setResource(this.readerContext.getResource());
bd.setSource(extractSource(ele));
return bd;
}
catch (ClassNotFoundException ex) {
error("Bean class [" + className + "] not found", ele, ex);
}
catch (NoClassDefFoundError err) {
error("Class that bean class [" + className + "] depends on not found", ele, err);
}
catch (Throwable ex) {
error("Unexpected failure during bean definition parsing", ele, ex);
}
finally {
this.parseState.pop();
}
return null;
}
複製代碼
到這裏,咱們已經完成了根據 <bean />
配置建立了一個 BeanDefinitionHolder 實例。注意,是一個。
咱們回到解析 <bean />
的入口方法:
protected void processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate) {
// 將 <bean /> 節點轉換爲 BeanDefinitionHolder,就是上面說的一堆
BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele);
if (bdHolder != null) {
// 若是有自定義屬性的話,進行相應的解析,先忽略
bdHolder = delegate.decorateBeanDefinitionIfRequired(ele, bdHolder);
try {
// 咱們把這步叫作 註冊Bean 吧
BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, getReaderContext().getRegistry());
}
catch (BeanDefinitionStoreException ex) {
getReaderContext().error("Failed to register bean definition with name '" +
bdHolder.getBeanName() + "'", ele, ex);
}
// 註冊完成後,發送事件,本文不展開說這個
getReaderContext().fireComponentRegistered(new BeanComponentDefinition(bdHolder));
}
}
複製代碼
你們再仔細看一下這塊吧,咱們後面就不回來講這個了。這裏已經根據一個 <bean />
標籤產生了一個 BeanDefinitionHolder 的實例,這個實例裏面也就是一個 BeanDefinition 的實例和它的 beanName、aliases 這三個信息,注意,咱們的關注點始終在 BeanDefinition 上:
public class BeanDefinitionHolder implements BeanMetadataElement {
private final BeanDefinition beanDefinition;
private final String beanName;
private final String[] aliases;
...
複製代碼
而後咱們準備註冊這個 BeanDefinition,最後,把這個註冊事件發送出去。
下面,咱們開始說註冊 Bean 吧。
註冊 Bean
// BeanDefinitionReaderUtils 143
public static void registerBeanDefinition( BeanDefinitionHolder definitionHolder, BeanDefinitionRegistry registry) throws BeanDefinitionStoreException {
String beanName = definitionHolder.getBeanName();
// 註冊這個 Bean
registry.registerBeanDefinition(beanName, definitionHolder.getBeanDefinition());
// 若是還有別名的話,也要根據別名通通註冊一遍,否則根據別名就找不到 Bean 了,這咱們就不開心了
String[] aliases = definitionHolder.getAliases();
if (aliases != null) {
for (String alias : aliases) {
// alias -> beanName 保存它們的別名信息,這個很簡單,用一個 map 保存一下就能夠了,
// 獲取的時候,會先將 alias 轉換爲 beanName,而後再查找
registry.registerAlias(beanName, alias);
}
}
}
複製代碼
別名註冊的放一邊,畢竟它很簡單,咱們看看怎麼註冊 Bean。
// DefaultListableBeanFactory 793
@Override
public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition) throws BeanDefinitionStoreException {
Assert.hasText(beanName, "Bean name must not be empty");
Assert.notNull(beanDefinition, "BeanDefinition must not be null");
if (beanDefinition instanceof AbstractBeanDefinition) {
try {
((AbstractBeanDefinition) beanDefinition).validate();
}
catch (BeanDefinitionValidationException ex) {
throw new BeanDefinitionStoreException(...);
}
}
// old? 還記得 「容許 bean 覆蓋」 這個配置嗎?allowBeanDefinitionOverriding
BeanDefinition oldBeanDefinition;
// 以後會看到,全部的 Bean 註冊後會放入這個 beanDefinitionMap 中
oldBeanDefinition = this.beanDefinitionMap.get(beanName);
// 處理重複名稱的 Bean 定義的狀況
if (oldBeanDefinition != null) {
if (!isAllowBeanDefinitionOverriding()) {
// 若是不容許覆蓋的話,拋異常
throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription()...
}
else if (oldBeanDefinition.getRole() < beanDefinition.getRole()) {
// log...用框架定義的 Bean 覆蓋用戶自定義的 Bean
}
else if (!beanDefinition.equals(oldBeanDefinition)) {
// log...用新的 Bean 覆蓋舊的 Bean
}
else {
// log...用同等的 Bean 覆蓋舊的 Bean,這裏指的是 equals 方法返回 true 的 Bean
}
// 覆蓋
this.beanDefinitionMap.put(beanName, beanDefinition);
}
else {
// 判斷是否已經有其餘的 Bean 開始初始化了.
// 注意,"註冊Bean" 這個動做結束,Bean 依然尚未初始化,咱們後面會有大篇幅說初始化過程,
// 在 Spring 容器啓動的最後,會 預初始化 全部的 singleton beans
if (hasBeanCreationStarted()) {
// Cannot modify startup-time collection elements anymore (for stable iteration)
synchronized (this.beanDefinitionMap) {
this.beanDefinitionMap.put(beanName, beanDefinition);
List<String> updatedDefinitions = new ArrayList<String>(this.beanDefinitionNames.size() + 1);
updatedDefinitions.addAll(this.beanDefinitionNames);
updatedDefinitions.add(beanName);
this.beanDefinitionNames = updatedDefinitions;
if (this.manualSingletonNames.contains(beanName)) {
Set<String> updatedSingletons = new LinkedHashSet<String>(this.manualSingletonNames);
updatedSingletons.remove(beanName);
this.manualSingletonNames = updatedSingletons;
}
}
}
else {
// 最正常的應該是進到這裏。
// 將 BeanDefinition 放到這個 map 中,這個 map 保存了全部的 BeanDefinition
this.beanDefinitionMap.put(beanName, beanDefinition);
// 這是個 ArrayList,因此會按照 bean 配置的順序保存每個註冊的 Bean 的名字
this.beanDefinitionNames.add(beanName);
// 這是個 LinkedHashSet,表明的是手動註冊的 singleton bean,
// 注意這裏是 remove 方法,到這裏的 Bean 固然不是手動註冊的
// 手動指的是經過調用如下方法註冊的 bean :
// registerSingleton(String beanName, Object singletonObject)
// 這不是重點,解釋只是爲了避免讓你們疑惑。Spring 會在後面"手動"註冊一些 Bean,如 "environment"、"systemProperties" 等 bean
this.manualSingletonNames.remove(beanName);
}
// 這個不重要,在預初始化的時候會用到,沒必要管它。
this.frozenBeanDefinitionNames = null;
}
if (oldBeanDefinition != null || containsSingleton(beanName)) {
resetBeanDefinition(beanName);
}
}
複製代碼
Bean 容器實例化完成後
說到這裏,咱們回到 refresh() 方法,我從新貼了一遍代碼,看看咱們說到哪了。是的,咱們才說完 obtainFreshBeanFactory() 方法。
考慮到篇幅,這裏開始大幅縮減掉不必詳細介紹的部分,你們直接看下面的代碼中的註釋就行了。
@Override
public void refresh() throws BeansException, IllegalStateException {
// 來個鎖,否則 refresh() 還沒結束,你又來個啓動或銷燬容器的操做,那不就亂套了嘛
synchronized (this.startupShutdownMonitor) {
// 準備工做,記錄下容器的啓動時間、標記「已啓動」狀態、處理配置文件中的佔位符
prepareRefresh();
// 這步比較關鍵,這步完成後,配置文件就會解析成一個個 Bean 定義,註冊到 BeanFactory 中,
// 固然,這裏說的 Bean 尚未初始化,只是配置信息都提取出來了,
// 註冊也只是將這些信息都保存到了註冊中心(說到底核心是一個 beanName-> beanDefinition 的 map)
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
// 設置 BeanFactory 的類加載器,添加幾個 BeanPostProcessor,手動註冊幾個特殊的 bean
// 這塊待會會展開說
prepareBeanFactory(beanFactory);
try {
// 【這裏須要知道 BeanFactoryPostProcessor 這個知識點,Bean 若是實現了此接口,
// 那麼在容器初始化之後,Spring 會負責調用裏面的 postProcessBeanFactory 方法。】
// 這裏是提供給子類的擴展點,到這裏的時候,全部的 Bean 都加載、註冊完成了,可是都尚未初始化
// 具體的子類能夠在這步的時候添加一些特殊的 BeanFactoryPostProcessor 的實現類或作點什麼事
postProcessBeanFactory(beanFactory);
// 調用 BeanFactoryPostProcessor 各個實現類的 postProcessBeanFactory(factory) 方法
invokeBeanFactoryPostProcessors(beanFactory);
// 註冊 BeanPostProcessor 的實現類,注意看和 BeanFactoryPostProcessor 的區別
// 此接口兩個方法: postProcessBeforeInitialization 和 postProcessAfterInitialization
// 兩個方法分別在 Bean 初始化以前和初始化以後獲得執行。注意,到這裏 Bean 還沒初始化
registerBeanPostProcessors(beanFactory);
// 初始化當前 ApplicationContext 的 MessageSource,國際化這裏就不展開說了,否則沒完沒了了
initMessageSource();
// 初始化當前 ApplicationContext 的事件廣播器,這裏也不展開了
initApplicationEventMulticaster();
// 從方法名就能夠知道,典型的模板方法(鉤子方法),
// 具體的子類能夠在這裏初始化一些特殊的 Bean(在初始化 singleton beans 以前)
onRefresh();
// 註冊事件監聽器,監聽器須要實現 ApplicationListener 接口。這也不是咱們的重點,過
registerListeners();
// 重點,重點,重點
// 初始化全部的 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.
// 銷燬已經初始化的 singleton 的 Beans,以避免有些 bean 會一直佔用資源
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();
}
}
}
複製代碼
準備 Bean 容器: prepareBeanFactory
這裏簡單介紹下 prepareBeanFactory(factory) 方法:
/** * 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) {
// 設置 BeanFactory 的類加載器,咱們知道 BeanFactory 須要加載類,也就須要類加載器,
// 這裏設置爲當前 ApplicationContext 的類加載器
beanFactory.setBeanClassLoader(getClassLoader());
// 設置 BeanExpressionResolver
beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver(beanFactory.getBeanClassLoader()));
//
beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this, getEnvironment()));
// 添加一個 BeanPostProcessor,這個 processor 比較簡單,
// 實現了 Aware 接口的幾個特殊的 beans 在初始化的時候,這個 processor 負責回調
beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));
// 下面幾行的意思就是,若是某個 bean 依賴於如下幾個接口的實現類,在自動裝配的時候忽略它們,
// Spring 會經過其餘方式來處理這些依賴。
beanFactory.ignoreDependencyInterface(EnvironmentAware.class);
beanFactory.ignoreDependencyInterface(EmbeddedValueResolverAware.class);
beanFactory.ignoreDependencyInterface(ResourceLoaderAware.class);
beanFactory.ignoreDependencyInterface(ApplicationEventPublisherAware.class);
beanFactory.ignoreDependencyInterface(MessageSourceAware.class);
beanFactory.ignoreDependencyInterface(ApplicationContextAware.class);
/** * 下面幾行就是爲特殊的幾個 bean 賦值,若是有 bean 依賴瞭如下幾個,會注入這邊相應的值, * 以前咱們說過,"當前 ApplicationContext 持有一個 BeanFactory",這裏解釋了第一行 * ApplicationContext 繼承了 ResourceLoader、ApplicationEventPublisher、MessageSource * 因此對於這幾個,能夠賦值爲 this,注意 this 是一個 ApplicationContext * 那這裏怎麼沒看到爲 MessageSource 賦值呢?那是由於 MessageSource 被註冊成爲了一個普通的 bean */
beanFactory.registerResolvableDependency(BeanFactory.class, beanFactory);
beanFactory.registerResolvableDependency(ResourceLoader.class, this);
beanFactory.registerResolvableDependency(ApplicationEventPublisher.class, this);
beanFactory.registerResolvableDependency(ApplicationContext.class, this);
// 這個 BeanPostProcessor 也很簡單,在 bean 實例化後,若是是 ApplicationListener 的子類,
// 那麼將其添加到 listener 列表中,能夠理解成:註冊事件監聽器
beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(this));
// Detect a LoadTimeWeaver and prepare for weaving, if found.
// 這裏涉及到特殊的 bean,名爲:loadTimeWeaver,這不是咱們的重點,忽略它
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()));
}
/** * 從下面幾行代碼咱們能夠知道,Spring 每每很 "智能" 就是由於它會幫咱們默認註冊一些有用的 bean, * 咱們也能夠選擇覆蓋 */
// 若是沒有定義 "environment" 這個 bean,那麼 Spring 會 "手動" 註冊一個
if (!beanFactory.containsLocalBean(ENVIRONMENT_BEAN_NAME)) {
beanFactory.registerSingleton(ENVIRONMENT_BEAN_NAME, getEnvironment());
}
// 若是沒有定義 "systemProperties" 這個 bean,那麼 Spring 會 "手動" 註冊一個
if (!beanFactory.containsLocalBean(SYSTEM_PROPERTIES_BEAN_NAME)) {
beanFactory.registerSingleton(SYSTEM_PROPERTIES_BEAN_NAME, getEnvironment().getSystemProperties());
}
// 若是沒有定義 "systemEnvironment" 這個 bean,那麼 Spring 會 "手動" 註冊一個
if (!beanFactory.containsLocalBean(SYSTEM_ENVIRONMENT_BEAN_NAME)) {
beanFactory.registerSingleton(SYSTEM_ENVIRONMENT_BEAN_NAME, getEnvironment().getSystemEnvironment());
}
}
複製代碼
初始化全部的 singleton beans
咱們的重點固然是 finishBeanFactoryInitialization(beanFactory); 這個巨頭了,這裏會負責初始化全部的 singleton beans。
注意,後面的描述中,我都會使用初始化或預初始化來表明這個階段。主要是 Spring 須要在這個階段完成全部的 singleton beans 的實例化。
咱們來總結一下,到目前爲止,應該說 BeanFactory 已經建立完成,而且全部的實現了 BeanFactoryPostProcessor 接口的 Bean 都已經初始化而且其中的 postProcessBeanFactory(factory) 方法已經獲得執行了。全部實現了 BeanPostProcessor 接口的 Bean 也都完成了初始化。
剩下的就是初始化其餘還沒被初始化的 singleton beans 了,咱們知道它們是單例的,若是沒有設置懶加載,那麼 Spring 會在接下來初始化全部的 singleton beans。
// AbstractApplicationContext.java 834
// 初始化剩餘的 singleton beans
protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {
// 什麼,看代碼這裏沒有初始化 Bean 啊!
// 注意了,初始化的動做包裝在 beanFactory.getBean(...) 中,這裏先不說細節,先往下看吧
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(new StringValueResolver() {
@Override
public String resolveStringValue(String strVal) {
return getEnvironment().resolvePlaceholders(strVal);
}
});
}
// 先初始化 LoadTimeWeaverAware 類型的 Bean
// 通常用於織入第三方模塊,在 class 文件載入 JVM 的時候動態織入,這裏不展開說
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);
// 沒什麼別的目的,由於到這一步的時候,Spring 已經開始預初始化 singleton beans 了,
// 確定不但願這個時候還出現 bean 定義解析、加載、註冊。
beanFactory.freezeConfiguration();
// 開始初始化剩下的
beanFactory.preInstantiateSingletons();
}
複製代碼
從上面最後一行往裏看,咱們又回到 DefaultListableBeanFactory 這個類了,這個類你們應該都不陌生了吧。
preInstantiateSingletons
// DefaultListableBeanFactory 728
@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);
// 觸發全部的非懶加載的 singleton beans 的初始化操做
for (String beanName : beanNames) {
// 合併父 Bean 中的配置,注意 <bean id="" class="" parent="" /> 中的 parent,用的很少吧,
// 考慮到這可能會影響你們的理解,我在附錄中解釋了一下 "Bean 繼承",請移步
RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
// 非抽象、非懶加載的 singletons。若是配置了 'abstract = true',那是不須要初始化的
if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
// 處理 FactoryBean(讀者若是不熟悉 FactoryBean,請移步附錄區瞭解)
if (isFactoryBean(beanName)) {
// FactoryBean 的話,在 beanName 前面加上 ‘&’ 符號。再調用 getBean,getBean 方法別急
final FactoryBean<?> factory = (FactoryBean<?>) getBean(FACTORY_BEAN_PREFIX + beanName);
// 判斷當前 FactoryBean 是不是 SmartFactoryBean 的實現,此處忽略,直接跳過
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 {
// 對於普通的 Bean,只要調用 getBean(beanName) 這個方法就能夠進行初始化了
getBean(beanName);
}
}
}
// 到這裏說明全部的非懶加載的 singleton beans 已經完成了初始化
// 若是咱們定義的 bean 是實現了 SmartInitializingSingleton 接口的,那麼在這裏獲得回調,忽略
for (String beanName : beanNames) {
Object singletonInstance = getSingleton(beanName);
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 {
smartSingleton.afterSingletonsInstantiated();
}
}
}
}
複製代碼
接下來,咱們就進入到 getBean(beanName) 方法了,這個方法咱們常常用來從 BeanFactory 中獲取一個 Bean,而初始化的過程也封裝到了這個方法裏。
getBean
在繼續前進以前,讀者應該具有 FactoryBean 的知識,若是讀者還不熟悉,請移步附錄部分了解 FactoryBean。
// AbstractBeanFactory 196
@Override
public Object getBean(String name) throws BeansException {
return doGetBean(name, null, null, false);
}
// 咱們在剖析初始化 Bean 的過程,可是 getBean 方法咱們常常是用來從容器中獲取 Bean 用的,注意切換思路,
// 已經初始化過了就從容器中直接返回,不然就先初始化再返回
@SuppressWarnings("unchecked")
protected <T> T doGetBean( final String name, final Class<T> requiredType, final Object[] args, boolean typeCheckOnly) throws BeansException {
// 獲取一個 「正統的」 beanName,處理兩種狀況,一個是前面說的 FactoryBean(前面帶 ‘&’),
// 一個是別名問題,由於這個方法是 getBean,獲取 Bean 用的,你要是傳一個別名進來,是徹底能夠的
final String beanName = transformedBeanName(name);
// 注意跟着這個,這個是返回值
Object bean;
// 檢查下是否是已經建立過了
Object sharedInstance = getSingleton(beanName);
// 這裏說下 args 唄,雖然看上去一點不重要。前面咱們一路進來的時候都是 getBean(beanName),
// 因此 args 實際上是 null 的,可是若是 args 不爲空的時候,那麼意味着調用方不是但願獲取 Bean,而是建立 Bean
if (sharedInstance != null && args == null) {
if (logger.isDebugEnabled()) {
if (isSingletonCurrentlyInCreation(beanName)) {
logger.debug("...");
}
else {
logger.debug("Returning cached instance of singleton bean '" + beanName + "'");
}
}
// 下面這個方法:若是是普通 Bean 的話,直接返回 sharedInstance,
// 若是是 FactoryBean 的話,返回它建立的那個實例對象
// (FactoryBean 知識,讀者若不清楚請移步附錄)
bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
}
else {
if (isPrototypeCurrentlyInCreation(beanName)) {
// 當前線程已經建立過了此 beanName 的 prototype 類型的 bean,那麼拋異常
throw new BeanCurrentlyInCreationException(beanName);
}
// 檢查一下這個 BeanDefinition 在容器中是否存在
BeanFactory parentBeanFactory = getParentBeanFactory();
if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
// 若是當前容器不存在這個 BeanDefinition,試試父容器中有沒有
String nameToLookup = originalBeanName(name);
if (args != null) {
// 返回父容器的查詢結果
return (T) parentBeanFactory.getBean(nameToLookup, args);
}
else {
// No args -> delegate to standard getBean method.
return parentBeanFactory.getBean(nameToLookup, requiredType);
}
}
if (!typeCheckOnly) {
// typeCheckOnly 爲 false,將當前 beanName 放入一個 alreadyCreated 的 Set 集合中。
markBeanAsCreated(beanName);
}
/* * 稍稍總結一下: * 到這裏的話,要準備建立 Bean 了,對於 singleton 的 Bean 來講,容器中還沒建立過此 Bean; * 對於 prototype 的 Bean 來講,原本就是要建立一個新的 Bean。 */
try {
final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
checkMergedBeanDefinition(mbd, beanName, args);
// 先初始化依賴的全部 Bean,這個很好理解。
// 注意,這裏的依賴指的是 depends-on 中定義的依賴
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);
// 先初始化被依賴項
getBean(dep);
}
}
// 建立 singleton 的實例
if (mbd.isSingleton()) {
sharedInstance = getSingleton(beanName, new ObjectFactory<Object>() {
@Override
public Object getObject() throws BeansException {
try {
// 執行建立 Bean,詳情後面再說
return createBean(beanName, mbd, args);
}
catch (BeansException ex) {
destroySingleton(beanName);
throw ex;
}
}
});
bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
}
// 建立 prototype 的實例
else if (mbd.isPrototype()) {
// It's a prototype -> create a new instance.
Object prototypeInstance = null;
try {
beforePrototypeCreation(beanName);
// 執行建立 Bean
prototypeInstance = createBean(beanName, mbd, args);
}
finally {
afterPrototypeCreation(beanName);
}
bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
}
// 若是不是 singleton 和 prototype 的話,須要委託給相應的實現類來處理
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, new ObjectFactory<Object>() {
@Override
public Object getObject() throws BeansException {
beforePrototypeCreation(beanName);
try {
// 執行建立 Bean
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;
}
}
// 最後,檢查一下類型對不對,不對的話就拋異常,對的話就返回了
if (requiredType != null && bean != null && !requiredType.isInstance(bean)) {
try {
return getTypeConverter().convertIfNecessary(bean, requiredType);
}
catch (TypeMismatchException ex) {
if (logger.isDebugEnabled()) {
logger.debug("Failed to convert bean '" + name + "' to required type '" +
ClassUtils.getQualifiedName(requiredType) + "'", ex);
}
throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
}
}
return (T) bean;
}
複製代碼
你們應該也猜到了,接下來固然是分析 createBean 方法:
protected abstract Object createBean(String beanName, RootBeanDefinition mbd, Object[] args) throws BeanCreationException;
複製代碼
第三個參數 args 數組表明建立實例須要的參數,不就是給構造方法用的參數,或者是工廠 Bean 的參數嘛,不過要注意,在咱們的初始化階段,args 是 null。
這回咱們要到一個新的類了 AbstractAutowireCapableBeanFactory,看類名,AutowireCapable?類名是否是也說明了點問題了。
主要是爲了如下場景,採用 @Autowired 註解注入屬性值:
public class MessageServiceImpl implements MessageService {
@Autowired
private UserService userService;
public String getMessage() {
return userService.getMessage();
}
}
複製代碼
<bean id="messageService" class="com.javadoop.example.MessageServiceImpl" />
複製代碼
// AbstractAutowireCapableBeanFactory 447
/** * Central method of this class: creates a bean instance, * populates the bean instance, applies post-processors, etc. * @see #doCreateBean */
@Override
protected Object createBean(String beanName, RootBeanDefinition mbd, Object[] args) throws BeanCreationException {
if (logger.isDebugEnabled()) {
logger.debug("Creating instance of bean '" + beanName + "'");
}
RootBeanDefinition mbdToUse = mbd;
// 確保 BeanDefinition 中的 Class 被加載
Class<?> resolvedClass = resolveBeanClass(mbd, beanName);
if (resolvedClass != null && !mbd.hasBeanClass() && mbd.getBeanClassName() != null) {
mbdToUse = new RootBeanDefinition(mbd);
mbdToUse.setBeanClass(resolvedClass);
}
// 準備方法覆寫,這裏又涉及到一個概念:MethodOverrides,它來自於 bean 定義中的 <lookup-method />
// 和 <replaced-method />,若是讀者感興趣,回到 bean 解析的地方看看對這兩個標籤的解析。
// 我在附錄中也對這兩個標籤的相關知識點進行了介紹,讀者能夠移步去看看
try {
mbdToUse.prepareMethodOverrides();
}
catch (BeanDefinitionValidationException ex) {
throw new BeanDefinitionStoreException(mbdToUse.getResourceDescription(),
beanName, "Validation of method overrides failed", ex);
}
try {
// 讓 BeanPostProcessor 在這一步有機會返回代理,而不是 bean 實例,
// 要完全瞭解清楚這個,須要去看 InstantiationAwareBeanPostProcessor 接口,這裏就不展開說了
Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
if (bean != null) {
return bean;
}
}
catch (Throwable ex) {
throw new BeanCreationException(mbdToUse.getResourceDescription(), beanName,
"BeanPostProcessor before instantiation of bean failed", ex);
}
// 重頭戲,建立 bean
Object beanInstance = doCreateBean(beanName, mbdToUse, args);
if (logger.isDebugEnabled()) {
logger.debug("Finished creating instance of bean '" + beanName + "'");
}
return beanInstance;
}
複製代碼
建立 Bean
往裏看 doCreateBean 這個方法:
/** * Actually create the specified bean. Pre-creation processing has already happened * at this point, e.g. checking {@code postProcessBeforeInstantiation} callbacks. * <p>Differentiates between default bean instantiation, use of a * factory method, and autowiring a constructor. * @param beanName the name of the bean * @param mbd the merged bean definition for the bean * @param args explicit arguments to use for constructor or factory method invocation * @return a new instance of the bean * @throws BeanCreationException if the bean could not be created * @see #instantiateBean * @see #instantiateUsingFactoryMethod * @see #autowireConstructor */
protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final Object[] args) throws BeanCreationException {
// Instantiate the bean.
BeanWrapper instanceWrapper = null;
if (mbd.isSingleton()) {
instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
}
if (instanceWrapper == null) {
// 說明不是 FactoryBean,這裏實例化 Bean,這裏很是關鍵,細節以後再說
instanceWrapper = createBeanInstance(beanName, mbd, args);
}
// 這個就是 Bean 裏面的 咱們定義的類 的實例,不少地方我描述成 "bean 實例"
final Object bean = (instanceWrapper != null ? instanceWrapper.getWrappedInstance() : null);
// 類型
Class<?> beanType = (instanceWrapper != null ? instanceWrapper.getWrappedClass() : null);
mbd.resolvedTargetType = beanType;
// 建議跳過吧,涉及接口:MergedBeanDefinitionPostProcessor
synchronized (mbd.postProcessingLock) {
if (!mbd.postProcessed) {
try {
// MergedBeanDefinitionPostProcessor,這個我真不展開說了,直接跳過吧,不多用的
applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
}
catch (Throwable ex) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"Post-processing of merged bean definition failed", ex);
}
mbd.postProcessed = true;
}
}
// Eagerly cache singletons to be able to resolve circular references
// even when triggered by lifecycle interfaces like BeanFactoryAware.
// 下面這塊代碼是爲了解決循環依賴的問題,之後有時間,我再對循環依賴這個問題進行解析吧
boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
isSingletonCurrentlyInCreation(beanName));
if (earlySingletonExposure) {
if (logger.isDebugEnabled()) {
logger.debug("Eagerly caching bean '" + beanName +
"' to allow for resolving potential circular references");
}
addSingletonFactory(beanName, new ObjectFactory<Object>() {
@Override
public Object getObject() throws BeansException {
return getEarlyBeanReference(beanName, mbd, bean);
}
});
}
// Initialize the bean instance.
Object exposedObject = bean;
try {
// 這一步也是很是關鍵的,這一步負責屬性裝配,由於前面的實例只是實例化了,並無設值,這裏就是設值
populateBean(beanName, mbd, instanceWrapper);
if (exposedObject != null) {
// 還記得 init-method 嗎?還有 InitializingBean 接口?還有 BeanPostProcessor 接口?
// 這裏就是處理 bean 初始化完成後的各類回調
exposedObject = initializeBean(beanName, exposedObject, mbd);
}
}
catch (Throwable ex) {
if (ex instanceof BeanCreationException && beanName.equals(((BeanCreationException) ex).getBeanName())) {
throw (BeanCreationException) ex;
}
else {
throw new BeanCreationException(
mbd.getResourceDescription(), beanName, "Initialization of bean failed", ex);
}
}
if (earlySingletonExposure) {
//
Object earlySingletonReference = getSingleton(beanName, false);
if (earlySingletonReference != null) {
if (exposedObject == bean) {
exposedObject = earlySingletonReference;
}
else if (!this.allowRawInjectionDespiteWrapping && hasDependentBean(beanName)) {
String[] dependentBeans = getDependentBeans(beanName);
Set<String> actualDependentBeans = new LinkedHashSet<String>(dependentBeans.length);
for (String dependentBean : dependentBeans) {
if (!removeSingletonIfCreatedForTypeCheckOnly(dependentBean)) {
actualDependentBeans.add(dependentBean);
}
}
if (!actualDependentBeans.isEmpty()) {
throw new BeanCurrentlyInCreationException(beanName,
"Bean with name '" + beanName + "' has been injected into other beans [" +
StringUtils.collectionToCommaDelimitedString(actualDependentBeans) +
"] in its raw version as part of a circular reference, but has eventually been " +
"wrapped. This means that said other beans do not use the final version of the " +
"bean. This is often the result of over-eager type matching - consider using " +
"'getBeanNamesOfType' with the 'allowEagerInit' flag turned off, for example.");
}
}
}
}
// Register bean as disposable.
try {
registerDisposableBeanIfNecessary(beanName, bean, mbd);
}
catch (BeanDefinitionValidationException ex) {
throw new BeanCreationException(
mbd.getResourceDescription(), beanName, "Invalid destruction signature", ex);
}
return exposedObject;
}
複製代碼
到這裏,咱們已經分析完了 doCreateBean 方法,總的來講,咱們已經說完了整個初始化流程。
接下來咱們挑 doCreateBean 中的三個細節出來講說。一個是建立 Bean 實例的 createBeanInstance 方法,一個是依賴注入的 populateBean 方法,還有就是回調方法 initializeBean。
注意了,接下來的這三個方法要認真說那也是極其複雜的,不少地方我就點到爲止了,感興趣的讀者能夠本身往裏看,最好就是碰到不懂的,本身寫代碼去調試它。
建立 Bean 實例
咱們先看看 createBeanInstance 方法。須要說明的是,這個方法若是每一個分支都分析下去,必然也是極其複雜冗長的,咱們挑重點說。此方法的目的就是實例化咱們指定的類。
protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, Object[] args) {
// 確保已經加載了此 class
Class<?> beanClass = resolveBeanClass(mbd, beanName);
// 校驗一下這個類的訪問權限
if (beanClass != null && !Modifier.isPublic(beanClass.getModifiers()) && !mbd.isNonPublicAccessAllowed()) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"Bean class isn't public, and non-public access not allowed: " + beanClass.getName());
}
if (mbd.getFactoryMethodName() != null) {
// 採用工廠方法實例化,不熟悉這個概念的讀者請看附錄,注意,不是 FactoryBean
return instantiateUsingFactoryMethod(beanName, mbd, args);
}
// 若是不是第一次建立,好比第二次建立 prototype bean。
// 這種狀況下,咱們能夠從第一次建立知道,採用無參構造函數,仍是構造函數依賴注入 來完成實例化
boolean resolved = false;
boolean autowireNecessary = false;
if (args == null) {
synchronized (mbd.constructorArgumentLock) {
if (mbd.resolvedConstructorOrFactoryMethod != null) {
resolved = true;
autowireNecessary = mbd.constructorArgumentsResolved;
}
}
}
if (resolved) {
if (autowireNecessary) {
// 構造函數依賴注入
return autowireConstructor(beanName, mbd, null, null);
}
else {
// 無參構造函數
return instantiateBean(beanName, mbd);
}
}
// 判斷是否採用有參構造函數
Constructor<?>[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName);
if (ctors != null ||
mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_CONSTRUCTOR ||
mbd.hasConstructorArgumentValues() || !ObjectUtils.isEmpty(args)) {
// 構造函數依賴注入
return autowireConstructor(beanName, mbd, ctors, args);
}
// 調用無參構造函數
return instantiateBean(beanName, mbd);
}
複製代碼
挑個簡單的無參構造函數構造實例來看看:
protected BeanWrapper instantiateBean(final String beanName, final RootBeanDefinition mbd) {
try {
Object beanInstance;
final BeanFactory parent = this;
if (System.getSecurityManager() != null) {
beanInstance = AccessController.doPrivileged(new PrivilegedAction<Object>() {
@Override
public Object run() {
return getInstantiationStrategy().instantiate(mbd, beanName, parent);
}
}, getAccessControlContext());
}
else {
// 實例化
beanInstance = getInstantiationStrategy().instantiate(mbd, beanName, parent);
}
// 包裝一下,返回
BeanWrapper bw = new BeanWrapperImpl(beanInstance);
initBeanWrapper(bw);
return bw;
}
catch (Throwable ex) {
throw new BeanCreationException(
mbd.getResourceDescription(), beanName, "Instantiation of bean failed", ex);
}
}
複製代碼
咱們能夠看到,關鍵的地方在於:
beanInstance = getInstantiationStrategy().instantiate(mbd, beanName, parent);
複製代碼
這裏會進行實際的實例化過程,咱們進去看看:
// SimpleInstantiationStrategy 59
@Override
public Object instantiate(RootBeanDefinition bd, String beanName, BeanFactory owner) {
// 若是不存在方法覆寫,那就使用 java 反射進行實例化,不然使用 CGLIB,
// 方法覆寫 請參見附錄"方法注入"中對 lookup-method 和 replaced-method 的介紹
if (bd.getMethodOverrides().isEmpty()) {
Constructor<?> constructorToUse;
synchronized (bd.constructorArgumentLock) {
constructorToUse = (Constructor<?>) bd.resolvedConstructorOrFactoryMethod;
if (constructorToUse == null) {
final Class<?> clazz = bd.getBeanClass();
if (clazz.isInterface()) {
throw new BeanInstantiationException(clazz, "Specified class is an interface");
}
try {
if (System.getSecurityManager() != null) {
constructorToUse = AccessController.doPrivileged(new PrivilegedExceptionAction<Constructor<?>>() {
@Override
public Constructor<?> run() throws Exception {
return clazz.getDeclaredConstructor((Class[]) null);
}
});
}
else {
constructorToUse = clazz.getDeclaredConstructor((Class[]) null);
}
bd.resolvedConstructorOrFactoryMethod = constructorToUse;
}
catch (Throwable ex) {
throw new BeanInstantiationException(clazz, "No default constructor found", ex);
}
}
}
// 利用構造方法進行實例化
return BeanUtils.instantiateClass(constructorToUse);
}
else {
// 存在方法覆寫,利用 CGLIB 來完成實例化,須要依賴於 CGLIB 生成子類,這裏就不展開了
return instantiateWithMethodInjection(bd, beanName, owner);
}
}
複製代碼
到這裏,咱們就算實例化完成了。咱們開始說怎麼進行屬性注入。
bean 屬性注入
// AbstractAutowireCapableBeanFactory 1203
protected void populateBean(String beanName, RootBeanDefinition mbd, BeanWrapper bw) {
// bean 實例的全部屬性都在這裏了
PropertyValues pvs = mbd.getPropertyValues();
if (bw == null) {
if (!pvs.isEmpty()) {
throw new BeanCreationException(
mbd.getResourceDescription(), beanName, "Cannot apply property values to null instance");
}
else {
// Skip property population phase for null instance.
return;
}
}
// 到這步的時候,bean 實例化完成(經過工廠方法或構造方法),可是還沒開始屬性設值,
// InstantiationAwareBeanPostProcessor 的實現類能夠在這裏對 bean 進行狀態修改,
// 我也沒找到有實際的使用,因此咱們暫且忽略這塊吧
boolean continueWithPropertyPopulation = true;
if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
for (BeanPostProcessor bp : getBeanPostProcessors()) {
if (bp instanceof InstantiationAwareBeanPostProcessor) {
InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
// 若是返回 false,表明不須要進行後續的屬性設值,也不須要再通過其餘的 BeanPostProcessor 的處理
if (!ibp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) {
continueWithPropertyPopulation = false;
break;
}
}
}
}
if (!continueWithPropertyPopulation) {
return;
}
if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_NAME ||
mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_TYPE) {
MutablePropertyValues newPvs = new MutablePropertyValues(pvs);
// 經過名字找到全部屬性值,若是是 bean 依賴,先初始化依賴的 bean。記錄依賴關係
if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_NAME) {
autowireByName(beanName, mbd, bw, newPvs);
}
// 經過類型裝配。複雜一些
if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_TYPE) {
autowireByType(beanName, mbd, bw, newPvs);
}
pvs = newPvs;
}
boolean hasInstAwareBpps = hasInstantiationAwareBeanPostProcessors();
boolean needsDepCheck = (mbd.getDependencyCheck() != RootBeanDefinition.DEPENDENCY_CHECK_NONE);
if (hasInstAwareBpps || needsDepCheck) {
PropertyDescriptor[] filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
if (hasInstAwareBpps) {
for (BeanPostProcessor bp : getBeanPostProcessors()) {
if (bp instanceof InstantiationAwareBeanPostProcessor) {
InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
// 這裏有個很是有用的 BeanPostProcessor 進到這裏: AutowiredAnnotationBeanPostProcessor
// 對採用 @Autowired、@Value 註解的依賴進行設值,這裏的內容也是很是豐富的,不過本文不會展開說了,感興趣的讀者請自行研究
pvs = ibp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName);
if (pvs == null) {
return;
}
}
}
}
if (needsDepCheck) {
checkDependencies(beanName, mbd, filteredPds, pvs);
}
}
// 設置 bean 實例的屬性值
applyPropertyValues(beanName, mbd, bw, pvs);
}
複製代碼
initializeBean
屬性注入完成後,這一步其實就是處理各類回調了。
protected Object initializeBean(final String beanName, final Object bean, RootBeanDefinition mbd) {
if (System.getSecurityManager() != null) {
AccessController.doPrivileged(new PrivilegedAction<Object>() {
@Override
public Object run() {
invokeAwareMethods(beanName, bean);
return null;
}
}, getAccessControlContext());
}
else {
// 若是 bean 實現了 BeanNameAware、BeanClassLoaderAware 或 BeanFactoryAware 接口,回調
invokeAwareMethods(beanName, bean);
}
Object wrappedBean = bean;
if (mbd == null || !mbd.isSynthetic()) {
// BeanPostProcessor 的 postProcessBeforeInitialization 回調
wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
}
try {
// 處理 bean 中定義的 init-method,
// 或者若是 bean 實現了 InitializingBean 接口,調用 afterPropertiesSet() 方法
invokeInitMethods(beanName, wrappedBean, mbd);
}
catch (Throwable ex) {
throw new BeanCreationException(
(mbd != null ? mbd.getResourceDescription() : null),
beanName, "Invocation of init method failed", ex);
}
if (mbd == null || !mbd.isSynthetic()) {
// BeanPostProcessor 的 postProcessAfterInitialization 回調
wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
}
return wrappedBean;
}
複製代碼
你們發現沒有,BeanPostProcessor 的兩個回調都發生在這邊,只不過中間處理了 init-method,是否是和讀者原來的認知有點不同了?
首先咱們來看一下官方demo中給出的Dubbo啓動代碼:
public static void main(String[] args) throws Exception {
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext(new String[]{"META-INF/spring/dubbo-demo-provider.xml"});
context.start();
System.in.read(); // press any key to exit
}
複製代碼
再看一下配置文件:
<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:dubbo="http://dubbo.apache.org/schema/dubbo" xmlns="http://www.springframework.org/schema/beans" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.3.xsd http://dubbo.apache.org/schema/dubbo http://dubbo.apache.org/schema/dubbo/dubbo.xsd">
<!-- provider's application name, used for tracing dependency relationship -->
<dubbo:application name="demo-provider"/>
<!-- use multicast registry center to export service -->
<dubbo:registry address="zookeeper://47.107.231.174:2181"/>
<!-- use dubbo protocol to export service on port 20880 -->
<dubbo:protocol name="dubbo" port="20880"/>
<!-- service implementation, as same as regular local bean -->
<bean id="demoService" class="org.apache.dubbo.demo.provider.DemoServiceImpl"/>
<!-- declare the service interface to be exported -->
<dubbo:service interface="org.apache.dubbo.demo.DemoService" ref="demoService"/>
</beans>
複製代碼
能夠看到Dubbo啓動的代碼很簡單,只有三行,經過構建ClassPathXmlApplicationContext來啓動Dubbo。那麼Dubbo是如何在ClassPathXmlApplicationContext構建過程當中實現本身的相關邏輯的呢?
在Dubbo的官方文檔中是這樣寫的:
基於 dubbo.jar 內的
META-INF/spring.handlers
配置,Spring 在遇到 dubbo 名稱空間時,會回調DubboNamespaceHandler
。全部 dubbo 的標籤,都統一用
DubboBeanDefinitionParser
進行解析,基於一對一屬性映射,將 XML 標籤解析爲 Bean 對象。
這裏提到的spring.handlers配置以下:
http\://dubbo.apache.org/schema/dubbo=org.apache.dubbo.config.spring.schema.DubboNamespaceHandler
http\://code.alibabatech.com/schema/dubbo=org.apache.dubbo.config.spring.schema.DubboNamespaceHandler
複製代碼
這裏的兩個配置對應了Dubbo從阿里開源到捐贈apache的過程。
咱們來看一下Spring中是如何解析Dubbo的配置文件的:
這是在啓動Dubbo過程當中解析文件的調用鏈路
能夠看到開始啓動以後
執行ClassPathXmlApplicationContext的構造方法,在構造方法中調用refresh構造新的ApplicationContext對象,在這裏會加載BeanDefiniton。也就是說會加載咱們在Dubbo的配置文件中的相關配置。
在執行解析對應的Element對象時,會進入BeanDefinitionParserDelegate.class的parseCustomElement方法:
public BeanDefinition parseCustomElement(Element ele, BeanDefinition containingBd) {
String namespaceUri = this.getNamespaceURI(ele);//首先得到對應的namespaceUri,這裏對應的namaspaceUri是http://dubbo.apche.org/schema/dubbo
NamespaceHandler handler = this.readerContext.getNamespaceHandlerResolver().resolve(namespaceUri);//根據namespaceUri獲取對應的Handler
if (handler == null) {
this.error("Unable to locate Spring NamespaceHandler for XML schema namespace [" + namespaceUri + "]", ele);
return null;
} else {
return handler.parse(ele, new ParserContext(this.readerContext, this, containingBd));//handler執行相應的解析邏輯,最後跳轉到DubboBeanDefinitionParser執行parse方法。
}
}
複製代碼
DefaultNamespaceHandlerResolver.class類:
//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by Fernflower decompiler)
//
package org.springframework.beans.factory.xml;
import java.io.IOException;
import java.util.Map;
import java.util.Properties;
import java.util.concurrent.ConcurrentHashMap;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.FatalBeanException;
import org.springframework.core.io.support.PropertiesLoaderUtils;
import org.springframework.util.Assert;
import org.springframework.util.ClassUtils;
import org.springframework.util.CollectionUtils;
public class DefaultNamespaceHandlerResolver implements NamespaceHandlerResolver {
public static final String DEFAULT_HANDLER_MAPPINGS_LOCATION = "META-INF/spring.handlers";//默認的handler配置文件地址
protected final Log logger;
private final ClassLoader classLoader;
private final String handlerMappingsLocation;
private volatile Map<String, Object> handlerMappings;//namespaceUri和解析器實例的映射關係
public DefaultNamespaceHandlerResolver() {
this((ClassLoader)null, "META-INF/spring.handlers");
}
public DefaultNamespaceHandlerResolver(ClassLoader classLoader) {
this(classLoader, "META-INF/spring.handlers");
}
public DefaultNamespaceHandlerResolver(ClassLoader classLoader, String handlerMappingsLocation) {
this.logger = LogFactory.getLog(this.getClass());
Assert.notNull(handlerMappingsLocation, "Handler mappings location must not be null");
this.classLoader = classLoader != null ? classLoader : ClassUtils.getDefaultClassLoader();
this.handlerMappingsLocation = handlerMappingsLocation;
}
public NamespaceHandler resolve(String namespaceUri) {
Map<String, Object> handlerMappings = this.getHandlerMappings();
Object handlerOrClassName = handlerMappings.get(namespaceUri);
if (handlerOrClassName == null) {
return null;
} else if (handlerOrClassName instanceof NamespaceHandler) {
return (NamespaceHandler)handlerOrClassName;
} else {
String className = (String)handlerOrClassName;
try {
Class<?> handlerClass = ClassUtils.forName(className, this.classLoader);
if (!NamespaceHandler.class.isAssignableFrom(handlerClass)) {
throw new FatalBeanException("Class [" + className + "] for namespace [" + namespaceUri + "] does not implement the [" + NamespaceHandler.class.getName() + "] interface");
} else {
NamespaceHandler namespaceHandler = (NamespaceHandler)BeanUtils.instantiateClass(handlerClass);//建立對應Handler的實例
namespaceHandler.init();//建立以後調用init方法
handlerMappings.put(namespaceUri, namespaceHandler);//添加到對應map中
return namespaceHandler;
}
} catch (ClassNotFoundException var7) {
throw new FatalBeanException("NamespaceHandler class [" + className + "] for namespace [" + namespaceUri + "] not found", var7);
} catch (LinkageError var8) {
throw new FatalBeanException("Invalid NamespaceHandler class [" + className + "] for namespace [" + namespaceUri + "]: problem with handler class file or dependent class", var8);
}
}
}
//當須要得到對應的namespaceUri和handler的映射關係時,使用雙重檢查鎖來構造handlerMapping。
private Map<String, Object> getHandlerMappings() {
if (this.handlerMappings == null) {
synchronized(this) {
if (this.handlerMappings == null) {
try {
Properties mappings = PropertiesLoaderUtils.loadAllProperties(this.handlerMappingsLocation, this.classLoader);
if (this.logger.isDebugEnabled()) {
this.logger.debug("Loaded NamespaceHandler mappings: " + mappings);
}
Map<String, Object> handlerMappings = new ConcurrentHashMap(mappings.size());
CollectionUtils.mergePropertiesIntoMap(mappings, handlerMappings);
this.handlerMappings = handlerMappings;
} catch (IOException var5) {
throw new IllegalStateException("Unable to load NamespaceHandler mappings from location [" + this.handlerMappingsLocation + "]", var5);
}
}
}
}
return this.handlerMappings;
}
public String toString() {
return "NamespaceHandlerResolver using mappings " + this.getHandlerMappings();
}
}
複製代碼
從上面的類中咱們瞭解到handler和namespaceUri的對應關係默認是從META-INF/spring.handlers文件中讀取,這就是爲何咱們只須要在META-INF/spring.handlers配置對應的解析器,spring就能自動的使用相應的解析去解析對應的名稱空間下的Element對象。
從上面能夠看到建立了對應的Handler實例以後,會調用該handler的init方法。
DubboNamespaceHandler.java的init方法以下:
@Override
public void init() {
registerBeanDefinitionParser("application", new DubboBeanDefinitionParser(ApplicationConfig.class, true));
registerBeanDefinitionParser("module", new DubboBeanDefinitionParser(ModuleConfig.class, true));
registerBeanDefinitionParser("registry", new DubboBeanDefinitionParser(RegistryConfig.class, true));
registerBeanDefinitionParser("monitor", new DubboBeanDefinitionParser(MonitorConfig.class, true));
registerBeanDefinitionParser("provider", new DubboBeanDefinitionParser(ProviderConfig.class, true));
registerBeanDefinitionParser("consumer", new DubboBeanDefinitionParser(ConsumerConfig.class, true));
registerBeanDefinitionParser("protocol", new DubboBeanDefinitionParser(ProtocolConfig.class, true));
registerBeanDefinitionParser("service", new DubboBeanDefinitionParser(ServiceBean.class, true));
registerBeanDefinitionParser("reference", new DubboBeanDefinitionParser(ReferenceBean.class, false));
registerBeanDefinitionParser("annotation", new AnnotationBeanDefinitionParser());
}
複製代碼
在init方法中,對dubbo中不一樣的實體註冊了不一樣的解析器,並指定不一樣的名稱解析成不一樣的實體對象。若是後續還須要什麼新的實體添加,只須要在這個地方添加對應的解析器就能夠。
return handler.parse(ele, new ParserContext(this.readerContext, this, containingBd)):這裏會執行DubboBeanDefinitionParser中的parser方法:
private static BeanDefinition parse(Element element, ParserContext parserContext, Class<?> beanClass, boolean required) {
//建立RootBeanDefinition
RootBeanDefinition beanDefinition = new RootBeanDefinition();
beanDefinition.setBeanClass(beanClass);
beanDefinition.setLazyInit(false);
//解析配置對象的id。若不存在,則進行生成
String id = element.getAttribute("id");
if ((id == null || id.length() == 0) && required) {
String generatedBeanName = element.getAttribute("name");
if (generatedBeanName == null || generatedBeanName.length() == 0) {
if (ProtocolConfig.class.equals(beanClass)) {
generatedBeanName = "dubbo";
} else {
generatedBeanName = element.getAttribute("interface");
}
}
if (generatedBeanName == null || generatedBeanName.length() == 0) {
generatedBeanName = beanClass.getName();
}
id = generatedBeanName;
//若id已存在,經過自增序列,解決重複
int counter = 2;
while (parserContext.getRegistry().containsBeanDefinition(id)) {
id = generatedBeanName + (counter++);
}
}
if (id != null && id.length() > 0) {
if (parserContext.getRegistry().containsBeanDefinition(id)) {
throw new IllegalStateException("Duplicate spring bean id " + id);
}
//添加到Spring的註冊表
parserContext.getRegistry().registerBeanDefinition(id, beanDefinition);
//設置Bean的'id'屬性值
beanDefinition.getPropertyValues().addPropertyValue("id", id);
}
//處理<dubbo:protocol/>特殊狀況
if (ProtocolConfig.class.equals(beanClass)) {
for (String name : parserContext.getRegistry().getBeanDefinitionNames()) {
BeanDefinition definition = parserContext.getRegistry().getBeanDefinition(name);
PropertyValue property = definition.getPropertyValues().getPropertyValue("protocol");
if (property != null) {
Object value = property.getValue();
if (value instanceof ProtocolConfig && id.equals(((ProtocolConfig) value).getName())) {
definition.getPropertyValues().addPropertyValue("protocol", new RuntimeBeanReference(id));
}
}
}
//處理<dubbo:service/>的class的屬性
} else if (ServiceBean.class.equals(beanClass)) {
String className = element.getAttribute("class");
if (className != null && className.length() > 0) {
RootBeanDefinition classDefinition = new RootBeanDefinition();
classDefinition.setBeanClass(ReflectUtils.forName(className));
classDefinition.setLazyInit(false);
parseProperties(element.getChildNodes(), classDefinition);
beanDefinition.getPropertyValues().addPropertyValue("ref", new BeanDefinitionHolder(classDefinition, id + "Impl"));
}
//解析<dubbo:provider/>的內嵌子元素<dubbo:service/>
} else if (ProviderConfig.class.equals(beanClass)) {
parseNested(element, parserContext, ServiceBean.class, true, "service", "provider", id, beanDefinition);
//解析<dubbo:consumer/>的內嵌子元素<dubbo:reference>
} else if (ConsumerConfig.class.equals(beanClass)) {
parseNested(element, parserContext, ReferenceBean.class, false, "reference", "consumer", id, beanDefinition);
}
Set<String> props = new HashSet<String>();
ManagedMap parameters = null;
//循環Bean對象的setting方法,將屬性賦值到Bean對象
for (Method setter : beanClass.getMethods()) {
String name = setter.getName();
//判斷是不是set方法
if (name.length() > 3 && name.startsWith("set")
&& Modifier.isPublic(setter.getModifiers())
&& setter.getParameterTypes().length == 1) {
Class<?> type = setter.getParameterTypes()[0];
//添加'props'
String property = StringUtils.camelToSplitName(name.substring(3, 4).toLowerCase() + name.substring(4), "-");
props.add(property);
Method getter = null;
//getting&&public&&屬性值類型統一
try {
getter = beanClass.getMethod("get" + name.substring(3), new Class<?>[0]);
} catch (NoSuchMethodException e) {
try {
getter = beanClass.getMethod("is" + name.substring(3), new Class<?>[0]);
} catch (NoSuchMethodException e2) {
}
}
if (getter == null
|| !Modifier.isPublic(getter.getModifiers())
|| !type.equals(getter.getReturnType())) {
continue;
}
//解析'<dubbo:parameters/>'
if ("parameters".equals(property)) {
parameters = parseParameters(element.getChildNodes(), beanDefinition);
//解析<dubbo:method>
} else if ("methods".equals(property)) {
parseMethods(id, element.getChildNodes(), beanDefinition, parserContext);
//解析'<dubbo:argument>'
} else if ("arguments".equals(property)) {
parseArguments(id, element.getChildNodes(), beanDefinition, parserContext);
} else {
String value = element.getAttribute(property);
if (value != null) {
value = value.trim();
if (value.length() > 0) {
//不想註冊到註冊中心的狀況
if ("registry".equals(property) && RegistryConfig.NO_AVAILABLE.equalsIgnoreCase(value)) {
RegistryConfig registryConfig = new RegistryConfig();
registryConfig.setAddress(RegistryConfig.NO_AVAILABLE);
beanDefinition.getPropertyValues().addPropertyValue(property, registryConfig);
} else if ("registry".equals(property) && value.indexOf(',') != -1) {
//多註冊中心的狀況
parseMultiRef("registries", value, beanDefinition, parserContext);
} else if ("provider".equals(property) && value.indexOf(',') != -1) {
//多服務提供者的狀況
parseMultiRef("providers", value, beanDefinition, parserContext);
} else if ("protocol".equals(property) && value.indexOf(',') != -1) {
//多協議的狀況
parseMultiRef("protocols", value, beanDefinition, parserContext);
} else {
Object reference;
//處理屬性爲基本屬性的狀況
if (isPrimitive(type)) {
//兼容性處理
if ("async".equals(property) && "false".equals(value)
|| "timeout".equals(property) && "0".equals(value)
|| "delay".equals(property) && "0".equals(value)
|| "version".equals(property) && "0.0.0".equals(value)
|| "stat".equals(property) && "-1".equals(value)
|| "reliable".equals(property) && "false".equals(value)) {
// backward compatibility for the default value in old version's xsd
value = null;
}
reference = value;
//處理在'<dubbo:provider/>'或者<dubbo:service/>上定義了'protocol'屬性的兼容性
} else if ("protocol".equals(property)
&& ExtensionLoader.getExtensionLoader(Protocol.class).hasExtension(value)
&& (!parserContext.getRegistry().containsBeanDefinition(value)//存在該註冊表的實現
|| !ProtocolConfig.class.getName().equals(parserContext.getRegistry().getBeanDefinition(value).getBeanClassName()))) {
//目前,<dubbo:provider protocol=""/>推薦獨立成<dubbo:protocol/>
if ("dubbo:provider".equals(element.getTagName())) {
logger.warn("Recommended replace <dubbo:provider protocol=\"" + value + "\" ... /> to <dubbo:protocol name=\"" + value + "\" ... />");
}
// backward compatibility
ProtocolConfig protocol = new ProtocolConfig();
protocol.setName(value);
reference = protocol;
//處理onreturn屬性
} else if ("onreturn".equals(property)) {
//按照'.'拆分
int index = value.lastIndexOf(".");
String returnRef = value.substring(0, index);
String returnMethod = value.substring(index + 1);
//建立RuntimeBeanReference,指向回調對象
reference = new RuntimeBeanReference(returnRef);
//設置'onreturnMethod'到BeanDefinition的屬性值
beanDefinition.getPropertyValues().addPropertyValue("onreturnMethod", returnMethod);
//處理onthrow屬性
} else if ("onthrow".equals(property)) {
//按照'.'拆分
int index = value.lastIndexOf(".");
String throwRef = value.substring(0, index);
String throwMethod = value.substring(index + 1);
//建立RuntimeBeanReference指向回調對象
reference = new RuntimeBeanReference(throwRef);
//設置’onthrowMethod‘到BeanDefinition的屬性值
beanDefinition.getPropertyValues().addPropertyValue("onthrowMethod", throwMethod);
} else if ("oninvoke".equals(property)) {
int index = value.lastIndexOf(".");
String invokeRef = value.substring(0, index);
String invokeRefMethod = value.substring(index + 1);
reference = new RuntimeBeanReference(invokeRef);
beanDefinition.getPropertyValues().addPropertyValue("oninvokeMethod", invokeRefMethod);
} else {
//指向Service的bean對象,必須是單例
if ("ref".equals(property) && parserContext.getRegistry().containsBeanDefinition(value)) {
BeanDefinition refBean = parserContext.getRegistry().getBeanDefinition(value);
if (!refBean.isSingleton()) {
throw new IllegalStateException("The exported service ref " + value + " must be singleton! Please set the " + value + " bean scope to singleton, eg: <bean id=\"" + value + "\" scope=\"singleton\" ...>");
}
}
//建立RuntimeBeanReference,指向service的Bean對象
reference = new RuntimeBeanReference(value);
}
//設置BeanDefinition的屬性值
beanDefinition.getPropertyValues().addPropertyValue(property, reference);
}
}
}
}
}
}
//將XML元素,未在上面遍歷到的屬性添加到'parameters'集合中。
NamedNodeMap attributes = element.getAttributes();
int len = attributes.getLength();
for (int i = 0; i < len; i++) {
Node node = attributes.item(i);
String name = node.getLocalName();
if (!props.contains(name)) {
if (parameters == null) {
parameters = new ManagedMap();
}
String value = node.getNodeValue();
parameters.put(name, new TypedStringValue(value, String.class));
}
}
if (parameters != null) {
beanDefinition.getPropertyValues().addPropertyValue("parameters", parameters);
}
return beanDefinition;
}
複製代碼
這裏Dubbo的配置文件解析就告一段落。
最後就是如何實如今Dubbo啓動的時候講服務註冊到註冊中心上去,這裏就須要用到前面解析的對象。在前面咱們提到DubboBeanDefinitionParser會將service解析爲ServiceBean對象。
咱們先看看ServiceBean類的實現:
/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */
package org.apache.dubbo.config.spring;
import org.apache.dubbo.config.ApplicationConfig;
import org.apache.dubbo.config.ModuleConfig;
import org.apache.dubbo.config.MonitorConfig;
import org.apache.dubbo.config.ProtocolConfig;
import org.apache.dubbo.config.ProviderConfig;
import org.apache.dubbo.config.RegistryConfig;
import org.apache.dubbo.config.ServiceConfig;
import org.apache.dubbo.config.annotation.Service;
import org.apache.dubbo.config.spring.extension.SpringExtensionFactory;
import org.springframework.aop.support.AopUtils;
import org.springframework.beans.factory.BeanFactoryUtils;
import org.springframework.beans.factory.BeanNameAware;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.ApplicationListener;
import org.springframework.context.event.ContextRefreshedEvent;
import org.springframework.context.support.AbstractApplicationContext;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
/** * ServiceFactoryBean * * @export */
public class ServiceBean<T> extends ServiceConfig<T> implements InitializingBean, DisposableBean, ApplicationContextAware, ApplicationListener<ContextRefreshedEvent>, BeanNameAware {
private static final long serialVersionUID = 213195494150089726L;
private final transient Service service;
private transient ApplicationContext applicationContext;
private transient String beanName;
private transient boolean supportedApplicationListener;
public ServiceBean() {
super();
this.service = null;
}
public ServiceBean(Service service) {
super(service);
this.service = service;
}
@Override
public void setApplicationContext(ApplicationContext applicationContext) {
this.applicationContext = applicationContext;
SpringExtensionFactory.addApplicationContext(applicationContext);
try {
Method method = applicationContext.getClass().getMethod("addApplicationListener", ApplicationListener.class); // backward compatibility to spring 2.0.1
method.invoke(applicationContext, this);
supportedApplicationListener = true;
} catch (Throwable t) {
if (applicationContext instanceof AbstractApplicationContext) {
try {
Method method = AbstractApplicationContext.class.getDeclaredMethod("addListener", ApplicationListener.class); // backward compatibility to spring 2.0.1
if (!method.isAccessible()) {
method.setAccessible(true);
}
method.invoke(applicationContext, this);
supportedApplicationListener = true;
} catch (Throwable t2) {
}
}
}
}
@Override
public void setBeanName(String name) {
this.beanName = name;
}
/** * Gets associated {@link Service} * * @return associated {@link Service} */
public Service getService() {
return service;
}
@Override
public void onApplicationEvent(ContextRefreshedEvent event) {
if (isDelay() && !isExported() && !isUnexported()) {
if (logger.isInfoEnabled()) {
logger.info("The service ready on spring started. service: " + getInterface());
}
export();
}
}
private boolean isDelay() {
Integer delay = getDelay();
ProviderConfig provider = getProvider();
if (delay == null && provider != null) {
delay = provider.getDelay();
}
return supportedApplicationListener && (delay == null || delay == -1);
}
@Override
@SuppressWarnings({"unchecked", "deprecation"})
public void afterPropertiesSet() throws Exception {
if (getProvider() == null) {
Map<String, ProviderConfig> providerConfigMap = applicationContext == null ? null : BeanFactoryUtils.beansOfTypeIncludingAncestors(applicationContext, ProviderConfig.class, false, false);
if (providerConfigMap != null && providerConfigMap.size() > 0) {
Map<String, ProtocolConfig> protocolConfigMap = applicationContext == null ? null : BeanFactoryUtils.beansOfTypeIncludingAncestors(applicationContext, ProtocolConfig.class, false, false);
if ((protocolConfigMap == null || protocolConfigMap.size() == 0)
&& providerConfigMap.size() > 1) { // backward compatibility
List<ProviderConfig> providerConfigs = new ArrayList<ProviderConfig>();
for (ProviderConfig config : providerConfigMap.values()) {
if (config.isDefault() != null && config.isDefault()) {
providerConfigs.add(config);
}
}
if (!providerConfigs.isEmpty()) {
setProviders(providerConfigs);
}
} else {
ProviderConfig providerConfig = null;
for (ProviderConfig config : providerConfigMap.values()) {
if (config.isDefault() == null || config.isDefault()) {
if (providerConfig != null) {
throw new IllegalStateException("Duplicate provider configs: " + providerConfig + " and " + config);
}
providerConfig = config;
}
}
if (providerConfig != null) {
setProvider(providerConfig);
}
}
}
}
if (getApplication() == null
&& (getProvider() == null || getProvider().getApplication() == null)) {
Map<String, ApplicationConfig> applicationConfigMap = applicationContext == null ? null : BeanFactoryUtils.beansOfTypeIncludingAncestors(applicationContext, ApplicationConfig.class, false, false);
if (applicationConfigMap != null && applicationConfigMap.size() > 0) {
ApplicationConfig applicationConfig = null;
for (ApplicationConfig config : applicationConfigMap.values()) {
if (config.isDefault() == null || config.isDefault()) {
if (applicationConfig != null) {
throw new IllegalStateException("Duplicate application configs: " + applicationConfig + " and " + config);
}
applicationConfig = config;
}
}
if (applicationConfig != null) {
setApplication(applicationConfig);
}
}
}
if (getModule() == null
&& (getProvider() == null || getProvider().getModule() == null)) {
Map<String, ModuleConfig> moduleConfigMap = applicationContext == null ? null : BeanFactoryUtils.beansOfTypeIncludingAncestors(applicationContext, ModuleConfig.class, false, false);
if (moduleConfigMap != null && moduleConfigMap.size() > 0) {
ModuleConfig moduleConfig = null;
for (ModuleConfig config : moduleConfigMap.values()) {
if (config.isDefault() == null || config.isDefault()) {
if (moduleConfig != null) {
throw new IllegalStateException("Duplicate module configs: " + moduleConfig + " and " + config);
}
moduleConfig = config;
}
}
if (moduleConfig != null) {
setModule(moduleConfig);
}
}
}
if ((getRegistries() == null || getRegistries().isEmpty())
&& (getProvider() == null || getProvider().getRegistries() == null || getProvider().getRegistries().isEmpty())
&& (getApplication() == null || getApplication().getRegistries() == null || getApplication().getRegistries().isEmpty())) {
Map<String, RegistryConfig> registryConfigMap = applicationContext == null ? null : BeanFactoryUtils.beansOfTypeIncludingAncestors(applicationContext, RegistryConfig.class, false, false);
if (registryConfigMap != null && registryConfigMap.size() > 0) {
List<RegistryConfig> registryConfigs = new ArrayList<RegistryConfig>();
for (RegistryConfig config : registryConfigMap.values()) {
if (config.isDefault() == null || config.isDefault()) {
registryConfigs.add(config);
}
}
if (!registryConfigs.isEmpty()) {
super.setRegistries(registryConfigs);
}
}
}
if (getMonitor() == null
&& (getProvider() == null || getProvider().getMonitor() == null)
&& (getApplication() == null || getApplication().getMonitor() == null)) {
Map<String, MonitorConfig> monitorConfigMap = applicationContext == null ? null : BeanFactoryUtils.beansOfTypeIncludingAncestors(applicationContext, MonitorConfig.class, false, false);
if (monitorConfigMap != null && monitorConfigMap.size() > 0) {
MonitorConfig monitorConfig = null;
for (MonitorConfig config : monitorConfigMap.values()) {
if (config.isDefault() == null || config.isDefault()) {
if (monitorConfig != null) {
throw new IllegalStateException("Duplicate monitor configs: " + monitorConfig + " and " + config);
}
monitorConfig = config;
}
}
if (monitorConfig != null) {
setMonitor(monitorConfig);
}
}
}
if ((getProtocols() == null || getProtocols().isEmpty())
&& (getProvider() == null || getProvider().getProtocols() == null || getProvider().getProtocols().isEmpty())) {
Map<String, ProtocolConfig> protocolConfigMap = applicationContext == null ? null : BeanFactoryUtils.beansOfTypeIncludingAncestors(applicationContext, ProtocolConfig.class, false, false);
if (protocolConfigMap != null && protocolConfigMap.size() > 0) {
List<ProtocolConfig> protocolConfigs = new ArrayList<ProtocolConfig>();
for (ProtocolConfig config : protocolConfigMap.values()) {
if (config.isDefault() == null || config.isDefault()) {
protocolConfigs.add(config);
}
}
if (!protocolConfigs.isEmpty()) {
super.setProtocols(protocolConfigs);
}
}
}
if (getPath() == null || getPath().length() == 0) {
if (beanName != null && beanName.length() > 0
&& getInterface() != null && getInterface().length() > 0
&& beanName.startsWith(getInterface())) {
setPath(beanName);
}
}
if (!isDelay()) {
export();
}
}
@Override
public void destroy() throws Exception {
// This will only be called for singleton scope bean, and expected to be called by spring shutdown hook when BeanFactory/ApplicationContext destroys.
// We will guarantee dubbo related resources being released with dubbo shutdown hook.
//unexport();
}
// merged from dubbox
@Override
protected Class getServiceClass(T ref) {
if (AopUtils.isAopProxy(ref)) {
return AopUtils.getTargetClass(ref);
}
return super.getServiceClass(ref);
}
}
複製代碼
能夠看到ServiceBean繼承了ServiceConfig類,實現了InitializingBean, DisposableBean, ApplicationContextAware, ApplicationListener, BeanNameAware。
InitializingBean
只包括afterPropertiesSet()方法,繼承該接口的類,在初始化bean的時候會執行該方法。在構造方法以後調用。
DisposableBean
DisposableBean也是一個接口,提供了一個惟一的方法destory()。在Bean生命週期結束前調用destory()方法作一些收尾工做.
init-method destory-method
@PostConstruct 和 @PreDestroy
Constructor >> @Autowired >> @PostConstruct
ApplicationContextAware
Spring容器會檢測容器中的全部Bean,若是發現某個Bean實現了ApplicationContextAware接口,Spring容器會在建立該Bean以後,自動調用該Bean的setApplicationContextAware()方法,調用該方法時,會將容器自己做爲參數傳給該方法
ApplicationListener
當Spring容器初始化完成以後,會發佈一個ContextRefreshedEvent事件,實現ApplicationListener接口的類,會調用*onApplicationEvent(E event)*方法。
BeanNameAware
public void setBeanName(String beanName) {
this.beanName = beanName;
}
得到本身的名字
BeanFactoryAware
讓Bean獲取配置他們的BeanFactory的引用。
在Spring註冊完成以後會調用finishRefresh方法,在該方法中會調用實現了ApplicationListenner類的onApplicationEvent方法。
public void onApplicationEvent(ContextRefreshedEvent event) {
if (isDelay() && !isExported() && !isUnexported()) {
if (logger.isInfoEnabled()) {
logger.info("The service ready on spring started. service: " + getInterface());
}
export();
}
}
複製代碼
ServiceBean的OnApplicationEvent方法如上,能夠看到在該方法中調用了export實現了服務的註冊。
再看一看ReferenceBean的實現:
public class ReferenceBean<T> extends ReferenceConfig<T> implements FactoryBean, ApplicationContextAware, InitializingBean, DisposableBean {
private static final long serialVersionUID = 213195494150089726L;
private transient ApplicationContext applicationContext;
public ReferenceBean() {
super();
}
public ReferenceBean(Reference reference) {
super(reference);
}
@Override
public void setApplicationContext(ApplicationContext applicationContext) {
this.applicationContext = applicationContext;
SpringExtensionFactory.addApplicationContext(applicationContext);
}
@Override
public Object getObject() {
return get();
}
@Override
public Class<?> getObjectType() {
return getInterfaceClass();
}
@Override
@Parameter(excluded = true)
public boolean isSingleton() {
return true;
}
@Override
@SuppressWarnings({"unchecked"})
public void afterPropertiesSet() throws Exception {
if (getConsumer() == null) {
Map<String, ConsumerConfig> consumerConfigMap = applicationContext == null ? null : BeanFactoryUtils.beansOfTypeIncludingAncestors(applicationContext, ConsumerConfig.class, false, false);
if (consumerConfigMap != null && consumerConfigMap.size() > 0) {
ConsumerConfig consumerConfig = null;
for (ConsumerConfig config : consumerConfigMap.values()) {
if (config.isDefault() == null || config.isDefault()) {
if (consumerConfig != null) {
throw new IllegalStateException("Duplicate consumer configs: " + consumerConfig + " and " + config);
}
consumerConfig = config;
}
}
if (consumerConfig != null) {
setConsumer(consumerConfig);
}
}
}
if (getApplication() == null
&& (getConsumer() == null || getConsumer().getApplication() == null)) {
Map<String, ApplicationConfig> applicationConfigMap = applicationContext == null ? null : BeanFactoryUtils.beansOfTypeIncludingAncestors(applicationContext, ApplicationConfig.class, false, false);
if (applicationConfigMap != null && applicationConfigMap.size() > 0) {
ApplicationConfig applicationConfig = null;
for (ApplicationConfig config : applicationConfigMap.values()) {
if (config.isDefault() == null || config.isDefault()) {
if (applicationConfig != null) {
throw new IllegalStateException("Duplicate application configs: " + applicationConfig + " and " + config);
}
applicationConfig = config;
}
}
if (applicationConfig != null) {
setApplication(applicationConfig);
}
}
}
if (getModule() == null
&& (getConsumer() == null || getConsumer().getModule() == null)) {
Map<String, ModuleConfig> moduleConfigMap = applicationContext == null ? null : BeanFactoryUtils.beansOfTypeIncludingAncestors(applicationContext, ModuleConfig.class, false, false);
if (moduleConfigMap != null && moduleConfigMap.size() > 0) {
ModuleConfig moduleConfig = null;
for (ModuleConfig config : moduleConfigMap.values()) {
if (config.isDefault() == null || config.isDefault()) {
if (moduleConfig != null) {
throw new IllegalStateException("Duplicate module configs: " + moduleConfig + " and " + config);
}
moduleConfig = config;
}
}
if (moduleConfig != null) {
setModule(moduleConfig);
}
}
}
if ((getRegistries() == null || getRegistries().isEmpty())
&& (getConsumer() == null || getConsumer().getRegistries() == null || getConsumer().getRegistries().isEmpty())
&& (getApplication() == null || getApplication().getRegistries() == null || getApplication().getRegistries().isEmpty())) {
Map<String, RegistryConfig> registryConfigMap = applicationContext == null ? null : BeanFactoryUtils.beansOfTypeIncludingAncestors(applicationContext, RegistryConfig.class, false, false);
if (registryConfigMap != null && registryConfigMap.size() > 0) {
List<RegistryConfig> registryConfigs = new ArrayList<>();
for (RegistryConfig config : registryConfigMap.values()) {
if (config.isDefault() == null || config.isDefault()) {
registryConfigs.add(config);
}
}
if (!registryConfigs.isEmpty()) {
super.setRegistries(registryConfigs);
}
}
}
if (getMonitor() == null
&& (getConsumer() == null || getConsumer().getMonitor() == null)
&& (getApplication() == null || getApplication().getMonitor() == null)) {
Map<String, MonitorConfig> monitorConfigMap = applicationContext == null ? null : BeanFactoryUtils.beansOfTypeIncludingAncestors(applicationContext, MonitorConfig.class, false, false);
if (monitorConfigMap != null && monitorConfigMap.size() > 0) {
MonitorConfig monitorConfig = null;
for (MonitorConfig config : monitorConfigMap.values()) {
if (config.isDefault() == null || config.isDefault()) {
if (monitorConfig != null) {
throw new IllegalStateException("Duplicate monitor configs: " + monitorConfig + " and " + config);
}
monitorConfig = config;
}
}
if (monitorConfig != null) {
setMonitor(monitorConfig);
}
}
}
Boolean b = isInit();
if (b == null && getConsumer() != null) {
b = getConsumer().isInit();
}
if (b != null && b) {
getObject();
}
}
@Override
public void destroy() {
// do nothing
}
}
複製代碼
在ReferenceBean中是經過FactoryBean來實現消費服務去註冊中心拉取相應的服務,創建對應的proxy的。