注意,看完这篇文章需要很长很长很长时间。。。
本文会分析Spring的IOC模块的整体流程,分析过程需要使用一个简单的demo工程来启动Spring,demo工程我以备好,需要的童鞋自行在下方链接下载:
<figure ><table><tr> <td ><pre><span >1</span><br></pre></td> <td ><pre><span >https:<span >//gi</span>thub.com<span >/shiyujun/</span>spring-framework</span><br></pre></td> </tr></table></figure>本文源码分析基于Spring5.0.0,所以pom文件中引入5.0的依赖
<figure ><table><tr> <td ><pre><span >1</span><br><span >2</span><br><span >3</span><br><span >4</span><br><span >5</span><br><span >6</span><br><span >7</span><br></pre></td> <td ><pre><span ><span ><<span >dependencies</span>></span></span><br><span > <span ><<span >dependency</span>></span></span><br><span > <span ><<span >groupId</span>></span>org.springframework<span ></<span >groupId</span>></span></span><br><span > <span ><<span >artifactId</span>></span>spring-context<span ></<span >artifactId</span>></span></span><br><span > <span ><<span >version</span>></span>5.0.0.RELEASE<span ></<span >version</span>></span></span><br><span > <span ></<span >dependency</span>></span></span><br><span ><span ></<span >dependencies</span>></span></span><br></pre></td> </tr></table></figure>然后写一个简单的接口和实现类
<figure ><table><tr> <td ><pre><span >1</span><br><span >2</span><br><span >3</span><br><span >4</span><br><span >5</span><br><span >6</span><br><span >7</span><br><span >8</span><br><span >9</span><br></pre></td> <td ><pre><span ><span >public</span> <span ><span >interface</span> <span >IOCService</span> </span>{</span><br><span > <span >public</span> <span >String</span> hollo();</span><br><span >}</span><br><span ></span><br><span ><span >public</span> <span ><span >class</span> <span >IOCServiceImpl</span> <span ><span >implements</span> <span >IOCService</span></span> </span>{</span><br><span > <span >public</span> <span >String</span> hollo() {</span><br><span > <span >return</span> <span >"Hello,IOC"</span>;</span><br><span > }</span><br><span >}</span><br></pre></td> </tr></table></figure>新建一个application-ioc.xml
<figure ><table><tr> <td ><pre><span >1</span><br><span >2</span><br><span >3</span><br><span >4</span><br><span >5</span><br><span >6</span><br><span >7</span><br></pre></td> <td ><pre><span ><span ><span ><?</span>xml version=<span >"1.0"</span> encoding=<span >"UTF-8"</span> <span >?></span></span></span><br><span ><span ><<span >beans</span> <span >xmlns:xsi</span>=<span >"http://www.w3.org/2001/XMLSchema-instance"</span></span></span><br><span ><span > <span >xmlns</span>=<span >"http://www.springframework.org/schema/beans"</span></span></span><br><span ><span > <span >xsi:schemaLocation</span>=<span >"http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"</span> <span >default-autowire</span>=<span >"byName"</span>></span></span><br><span ></span><br><span > <span ><<span >bean</span> <span >id</span>=<span >"iocservice"</span> <span >class</span>=<span >"cn.shiyujun.service.impl.IOCServiceImpl"</span>/></span></span><br><span ><span ></<span >beans</span>></span></span><br></pre></td> </tr></table></figure>启动Spring
<figure ><table><tr> <td ><pre><span >1</span><br><span >2</span><br><span >3</span><br><span >4</span><br><span >5</span><br><span >6</span><br><span >7</span><br></pre></td> <td ><pre><span ><span >public</span> <span >class</span> <span >IOCDemo</span> {</span><br><span > <span ><span >public</span> <span >static</span> <span >void</span> <span >main</span> (<span >String args[]</span>)</span>{</span><br><span > ApplicationContext context = <span >new</span> ClassPathXmlApplicationContext(<span >"classpath:application-ioc.xml"</span>);</span><br><span > IOCService iocService=context.getBean(IOCService.class);</span><br><span > System.<span >out</span>.println(iocService.hollo());</span><br><span > }</span><br><span >}</span><br></pre></td> </tr></table></figure>上方一个简单的demo工程相信各位童鞋在刚刚学习Spring的时候就已经玩的特别6了。我就不详细的说明了,直接开始看源码吧
在文章开始的demo工程中,我选择使用了一个xml文件来配置了接口和实现类之间的关系,然后使用了ClassPathXmlApplicationContext这个类来加载这个配置文件。现在我们就先来看一下这个类到底是个什么东东
首先看一下继承关系图(只保留了跟本文相关的,省略了很多其他的继承关系)
可以看到左下角的就是我们今天的主角ClassPathXmlApplicationContext、然后它的旁边是一个同门师兄弟FileSystemXmlApplicationContext。看名字就可以知道它们哥俩都是通过加载配置文件来启动Spring的,只不过一个是从程序内加载一个是从系统内加载。
除了这两个还有一个类AnnotationConfigApplicationContext比较值得我们关注,这个类是用来处理注解式编程的。
而最上边的ApplicationContext则是大名鼎鼎的Spring核心上下文了
看一下这个类的源代码
<figure ><table><tr> <td ><pre><span >1</span><br><span >2</span><br><span >3</span><br><span >4</span><br><span >5</span><br><span >6</span><br><span >7</span><br><span >8</span><br><span >9</span><br><span >10</span><br><span >11</span><br><span >12</span><br><span >13</span><br><span >14</span><br><span >15</span><br><span >16</span><br><span >17</span><br><span >18</span><br><span >19</span><br><span >20</span><br><span >21</span><br></pre></td> <td ><pre><span >public <span ><span >class</span> <span >ClassPathXmlApplicationContext</span> <span >extends</span> <span >AbstractXmlApplicationContext</span> </span>{</span><br><span > <span >//配置文件数组</span></span><br><span > <span >private</span> <span >Resource</span>[] configResources;</span><br><span ></span><br><span > <span >// 指定ApplicationContext的父容器</span></span><br><span > public <span >ClassPathXmlApplicationContext</span>(<span >ApplicationContext</span> parent) {</span><br><span > <span >super</span>(parent);</span><br><span > }</span><br><span > </span><br><span > public <span >ClassPathXmlApplicationContext</span>(<span >String</span>[] configLocations, boolean refresh, <span >ApplicationContext</span> parent)</span><br><span > <span >throws</span> <span >BeansException</span> {</span><br><span ></span><br><span > <span >super</span>(parent);</span><br><span > <span >// 根据提供的路径,处理成配置文件数组(以分号、逗号、空格、tab、换行符分割)</span></span><br><span > setConfigLocations(configLocations);</span><br><span > </span><br><span > <span >if</span> (refresh) {</span><br><span > refresh(); </span><br><span > }</span><br><span > }</span><br><span >}</span><br></pre></td> </tr></table></figure>可以看到整体来看源码比较简单,只有setConfigLocations
和refresh
两个方法没有看到具体的实现。但是如果你因为这个而小巧了Spring那可就大错特错了,setConfigLocations
只是一个开胃小菜,refresh
才是我们本文的重点
setConfigLocations
setConfigLocations
方法的主要工作有两个:创建环境对象ConfigurableEnvironment和处理ClassPathXmlApplicationContext传入的字符串中的占位符
跟着setConfigLocations
方法一直往下走
这里getEnironment()
就涉及到了创建环境变量相关的操作了
看一下ConfigurableEnvironment
这个接口的继承图(1张没能截全,两张一块看)
这个接口比较重要的就是两部分内容了,一个是设置Spring的环境就是我们经常用的spring.profile配置。另外就是系统资源Property
接着看createEnvironment()
方法,发现它返回了一个StandardEnvironment
类,而这个类中的customizePropertySources
方法就会往资源列表中添加Java进程中的变量和系统的环境变量
再次回到 resolvePath
方法后跟进通过上方获取的ConfigurableEnvironment
接口的resolveRequiredPlaceholders
方法,终点就是下方的这个方法。这个方法主要就是处理所有使用${}方式的占位符
配置文件名称解析完毕后,就到了最关键的一步refresh方法。这个方法,接下来会用超级长的篇幅来解析这个方法
先看一下这个方法里大致内容
<figure ><table><tr> <td ><pre><span >1</span><br><span >2</span><br><span >3</span><br><span >4</span><br><span >5</span><br><span >6</span><br><span >7</span><br><span >8</span><br><span >9</span><br><span >10</span><br><span >11</span><br><span >12</span><br><span >13</span><br><span >14</span><br><span >15</span><br><span >16</span><br><span >17</span><br><span >18</span><br><span >19</span><br><span >20</span><br><span >21</span><br><span >22</span><br><span >23</span><br><span >24</span><br><span >25</span><br><span >26</span><br><span >27</span><br><span >28</span><br><span >29</span><br><span >30</span><br><span >31</span><br><span >32</span><br><span >33</span><br><span >34</span><br><span >35</span><br><span >36</span><br><span >37</span><br><span >38</span><br><span >39</span><br><span >40</span><br><span >41</span><br><span >42</span><br><span >43</span><br><span >44</span><br><span >45</span><br><span >46</span><br><span >47</span><br><span >48</span><br><span >49</span><br><span >50</span><br><span >51</span><br><span >52</span><br><span >53</span><br><span >54</span><br><span >55</span><br><span >56</span><br><span >57</span><br><span >58</span><br><span >59</span><br><span >60</span><br><span >61</span><br><span >62</span><br><span >63</span><br></pre></td> <td ><pre><span ><span >public</span> <span ><span >void</span> <span >refresh</span><span >()</span> <span >throws</span> BeansException, IllegalStateException </span>{</span><br><span > <span >synchronized</span> (<span >this</span>.startupShutdownMonitor) {</span><br><span > <span >// Prepare this context for refreshing.</span></span><br><span > prepareRefresh();</span><br><span ></span><br><span > <span >// Tell the subclass to refresh the internal bean factory.</span></span><br><span > ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();</span><br><span ></span><br><span > <span >// Prepare the bean factory for use in this context.</span></span><br><span > prepareBeanFactory(beanFactory);</span><br><span ></span><br><span > <span >try</span> {</span><br><span > <span >// Allows post-processing of the bean factory in context subclasses.</span></span><br><span > postProcessBeanFactory(beanFactory);</span><br><span ></span><br><span > <span >// Invoke factory processors registered as beans in the context.</span></span><br><span > invokeBeanFactoryPostProcessors(beanFactory);</span><br><span ></span><br><span > <span >// Register bean processors that intercept bean creation.</span></span><br><span > registerBeanPostProcessors(beanFactory);</span><br><span ></span><br><span > <span >// Initialize message source for this context.</span></span><br><span > initMessageSource();</span><br><span ></span><br><span > <span >// Initialize event multicaster for this context.</span></span><br><span > initApplicationEventMulticaster();</span><br><span ></span><br><span > <span >// Initialize other special beans in specific context subclasses.</span></span><br><span > onRefresh();</span><br><span ></span><br><span > <span >// Check for listener beans and register them.</span></span><br><span > registerListeners();</span><br><span ></span><br><span > <span >// Instantiate all remaining (non-lazy-init) singletons.</span></span><br><span > finishBeanFactoryInitialization(beanFactory);</span><br><span ></span><br><span > <span >// Last step: publish corresponding event.</span></span><br><span > finishRefresh();</span><br><span > }</span><br><span ></span><br><span > <span >catch</span> (BeansException ex) {</span><br><span > <span >if</span> (logger.isWarnEnabled()) {</span><br><span > logger.warn(<span >"Exception encountered during context initialization - "</span> +</span><br><span > <span >"cancelling refresh attempt: "</span> + ex);</span><br><span > }</span><br><span ></span><br><span > <span >// Destroy already created singletons to avoid dangling resources.</span></span><br><span > destroyBeans();</span><br><span ></span><br><span > <span >// Reset 'active' flag.</span></span><br><span > cancelRefresh(ex);</span><br><span ></span><br><span > <span >// Propagate exception to caller.</span></span><br><span > <span >throw</span> ex;</span><br><span > }</span><br><span ></span><br><span > <span >finally</span> {</span><br><span > <span >// Reset common introspection caches in Spring's core, since we</span></span><br><span > <span >// might not ever need metadata for singleton beans anymore...</span></span><br><span > resetCommonCaches();</span><br><span > }</span><br><span > }</span><br><span > }</span><br></pre></td> </tr></table></figure>是不是看着有点懵,不要着急,一行一行往下看,不研究明白誓不罢休
synchronized
为了避免refresh()
还没结束,再次发起启动或者销毁容器引起的冲突
prepareRefresh()
做一些准备工作,记录容器的启动时间、标记“已启动”状态、检查环境变量等
<figure ><table><tr> <td ><pre><span >1</span><br><span >2</span><br><span >3</span><br><span >4</span><br><span >5</span><br><span >6</span><br><span >7</span><br><span >8</span><br><span >9</span><br><span >10</span><br><span >11</span><br><span >12</span><br><span >13</span><br><span >14</span><br><span >15</span><br><span >16</span><br><span >17</span><br></pre></td> <td ><pre><span ><span >protected</span> void prepareRefresh() {</span><br><span > <span >this</span>.startupDate = System.currentTimeMillis();</span><br><span > <span >this</span>.closed.<span >set</span>(<span >false</span>);</span><br><span > <span >this</span>.active.<span >set</span>(<span >true</span>);</span><br><span ></span><br><span > <span >if</span> (logger.isInfoEnabled()) {</span><br><span > logger.info(<span >"Refreshing "</span> + <span >this</span>);</span><br><span > }</span><br><span ></span><br><span > <span >// 初始化加载配置文件方法,并没有具体实现,一个留给用户的扩展点</span></span><br><span > initPropertySources();</span><br><span ></span><br><span > <span >// 检查环境变量</span></span><br><span > getEnvironment().validateRequiredProperties();</span><br><span ></span><br><span > <span >this</span>.earlyApplicationEvents = new LinkedHashSet<>();</span><br><span > }</span><br></pre></td> </tr></table></figure>其中检查环境变量的核心方法为,简单来说就是如果存在环境变量的value为空的时候就抛异常,然后停止启动Spring
<figure ><table><tr> <td ><pre><span >1</span><br><span >2</span><br><span >3</span><br><span >4</span><br><span >5</span><br><span >6</span><br><span >7</span><br><span >8</span><br><span >9</span><br><span >10</span><br><span >11</span><br></pre></td> <td ><pre><span ><span >public</span> <span >void</span> validateRequiredProperties() {</span><br><span > MissingRequiredPropertiesException ex = <span >new</span> MissingRequiredPropertiesException();</span><br><span > <span >for</span> (<span >String</span> <span >key</span> : <span >this</span>.requiredProperties) {</span><br><span > <span >if</span> (<span >this</span>.getProperty(<span >key</span>) == <span >null</span>) {</span><br><span > ex.addMissingRequiredProperty(<span >key</span>);</span><br><span > }</span><br><span > }</span><br><span > <span >if</span> (!ex.getMissingRequiredProperties().isEmpty()) {</span><br><span > <span >throw</span> ex;</span><br><span > }</span><br><span > }</span><br></pre></td> </tr></table></figure>基于这个特性我们可以做一些扩展,提前在集合requiredProperties
中放入我们这个项目必须存在的一些环境变量。假说我们的生产环境数据库地址、用户名和密码都是使用环境变量的方式注入进去来代替测试环境的配置,那么就可以在这里添加这个校验,在程序刚启动的时候就能发现问题
obtainFreshBeanFactory()
乍一看这个方法也没几行代码,但是这个方法负责了BeanFactory的初始化、Bean的加载和注册等事件
<figure ><table><tr> <td ><pre><span >1</span><br><span >2</span><br><span >3</span><br><span >4</span><br><span >5</span><br><span >6</span><br><span >7</span><br><span >8</span><br><span >9</span><br><span >10</span><br><span >11</span><br><span >12</span><br></pre></td> <td ><pre><span ></span><br><span ><span ><span >protected</span> ConfigurableListableBeanFactory <span >obtainFreshBeanFactory</span><span >()</span> </span>{</span><br><span > <span >// 核心</span></span><br><span > refreshBeanFactory();</span><br><span ></span><br><span > <span >// 返回刚刚创建的 BeanFactory</span></span><br><span > ConfigurableListableBeanFactory beanFactory = getBeanFactory();</span><br><span > <span >if</span> (logger.isDebugEnabled()) {</span><br><span > logger.debug(<span >"Bean factory for "</span> + getDisplayName() + <span >": "</span> + beanFactory);</span><br><span > }</span><br><span > <span >return</span> beanFactory;</span><br><span >}</span><br></pre></td> </tr></table></figure>先看refreshBeanFactory()
这里一开始就实例化了一个DefaultListableBeanFactory,先看一下这个类的继承关系
可以看到这个哥们的背景相当大,所有关于容器的接口、抽象类他都继承了。再看他的方法
这方法简直多的吓人,妥妥的Spring家族超级富二代。看他的方法名称相信就可以猜出他大部分的功能了
在看loadBeanDefinitions()
这个方法之前,就必须了解一个东西了。那就是:BeanDefinition
我们知道BeanFactory是一个Bean容器,而BeanDefinition就是Bean的一种形式(它里面包含了Bean指向的类、是否单例、是否懒加载、Bean的依赖关系等相关的属性)。BeanFactory中就是保存的BeanDefinition。
看BeanDefinition的接口定义
<figure ><table><tr> <td ><pre><span >1</span><br><span >2</span><br><span >3</span><br><span >4</span><br><span >5</span><br><span >6</span><br><span >7</span><br><span >8</span><br><span >9</span><br><span >10</span><br><span >11</span><br><span >12</span><br><span >13</span><br><span >14</span><br><span >15</span><br><span >16</span><br><span >17</span><br><span >18</span><br><span >19</span><br><span >20</span><br><span >21</span><br><span >22</span><br><span >23</span><br><span >24</span><br><span >25</span><br><span >26</span><br><span >27</span><br><span >28</span><br><span >29</span><br><span >30</span><br><span >31</span><br><span >32</span><br><span >33</span><br><span >34</span><br><span >35</span><br><span >36</span><br><span >37</span><br><span >38</span><br><span >39</span><br><span >40</span><br><span >41</span><br><span >42</span><br><span >43</span><br><span >44</span><br><span >45</span><br><span >46</span><br><span >47</span><br><span >48</span><br><span >49</span><br><span >50</span><br><span >51</span><br><span >52</span><br><span >53</span><br><span >54</span><br><span >55</span><br><span >56</span><br><span >57</span><br><span >58</span><br><span >59</span><br><span >60</span><br><span >61</span><br><span >62</span><br><span >63</span><br><span >64</span><br><span >65</span><br><span >66</span><br><span >67</span><br><span >68</span><br><span >69</span><br><span >70</span><br><span >71</span><br><span >72</span><br><span >73</span><br><span >74</span><br><span >75</span><br><span >76</span><br><span >77</span><br><span >78</span><br></pre></td> <td ><pre><span ></span><br><span ><span >public</span> <span ><span >interface</span> <span >BeanDefinition</span> <span >extends</span> <span >AttributeAccessor</span>, <span >BeanMetadataElement</span> </span>{</span><br><span ></span><br><span > <span >// Bean的生命周期,默认只提供sington和prototype两种,在WebApplicationContext中还会有request, session, globalSession, application, websocket 等</span></span><br><span > String SCOPE_SINGLETON = ConfigurableBeanFactory.SCOPE_SINGLETON;</span><br><span > String SCOPE_PROTOTYPE = ConfigurableBeanFactory.SCOPE_PROTOTYPE;</span><br><span ></span><br><span > </span><br><span > <span >// 设置父Bean</span></span><br><span > <span ><span >void</span> <span >setParentName</span><span >(String parentName)</span></span>;</span><br><span ></span><br><span > <span >// 获取父Bean</span></span><br><span > <span >String <span >getParentName</span><span >()</span></span>;</span><br><span ></span><br><span > <span >// 设置Bean的类名称</span></span><br><span > <span ><span >void</span> <span >setBeanClassName</span><span >(String beanClassName)</span></span>;</span><br><span ></span><br><span > <span >// 获取Bean的类名称</span></span><br><span > <span >String <span >getBeanClassName</span><span >()</span></span>;</span><br><span ></span><br><span ></span><br><span > <span >// 设置bean的scope</span></span><br><span > <span ><span >void</span> <span >setScope</span><span >(String scope)</span></span>;</span><br><span ></span><br><span > <span >String <span >getScope</span><span >()</span></span>;</span><br><span ></span><br><span > <span >// 设置是否懒加载</span></span><br><span > <span ><span >void</span> <span >setLazyInit</span><span >(<span >boolean</span> lazyInit)</span></span>;</span><br><span ></span><br><span > <span ><span >boolean</span> <span >isLazyInit</span><span >()</span></span>;</span><br><span ></span><br><span > <span >// 设置该Bean依赖的所有Bean</span></span><br><span > <span ><span >void</span> <span >setDependsOn</span><span >(String... dependsOn)</span></span>;</span><br><span ></span><br><span > <span >// 返回该Bean的所有依赖</span></span><br><span > String[] getDependsOn();</span><br><span ></span><br><span > <span >// 设置该Bean是否可以注入到其他Bean中</span></span><br><span > <span ><span >void</span> <span >setAutowireCandidate</span><span >(<span >boolean</span> autowireCandidate)</span></span>;</span><br><span ></span><br><span > <span >// 该Bean是否可以注入到其他Bean中</span></span><br><span > <span ><span >boolean</span> <span >isAutowireCandidate</span><span >()</span></span>;</span><br><span ></span><br><span > <span >// 同一接口的多个实现,如果不指定名字的话,Spring会优先选择设置primary为true的bean</span></span><br><span > <span ><span >void</span> <span >setPrimary</span><span >(<span >boolean</span> primary)</span></span>;</span><br><span ></span><br><span > <span >// 是否是primary的</span></span><br><span > <span ><span >boolean</span> <span >isPrimary</span><span >()</span></span>;</span><br><span ></span><br><span > <span >// 指定工厂名称</span></span><br><span > <span ><span >void</span> <span >setFactoryBeanName</span><span >(String factoryBeanName)</span></span>;</span><br><span > <span >// 获取工厂名称</span></span><br><span > <span >String <span >getFactoryBeanName</span><span >()</span></span>;</span><br><span > <span >// 指定工厂类中的工厂方法名称</span></span><br><span > <span ><span >void</span> <span >setFactoryMethodName</span><span >(String factoryMethodName)</span></span>;</span><br><span > <span >// 获取工厂类中的工厂方法名称</span></span><br><span > <span >String <span >getFactoryMethodName</span><span >()</span></span>;</span><br><span ></span><br><span > <span >// 构造器参数</span></span><br><span > <span >ConstructorArgumentValues <span >getConstructorArgumentValues</span><span >()</span></span>;</span><br><span ></span><br><span > <span >// Bean 中的属性值,后面给 bean 注入属性值的时候会说到</span></span><br><span > <span >MutablePropertyValues <span >getPropertyValues</span><span >()</span></span>;</span><br><span ></span><br><span > <span >// 是否 singleton</span></span><br><span > <span ><span >boolean</span> <span >isSingleton</span><span >()</span></span>;</span><br><span ></span><br><span > <span >// 是否 prototype</span></span><br><span > <span ><span >boolean</span> <span >isPrototype</span><span >()</span></span>;</span><br><span ></span><br><span > <span >// 如果这个 Bean 是被设置为 abstract,那么不能实例化,常用于作为 父bean 用于继承</span></span><br><span > <span ><span >boolean</span> <span >isAbstract</span><span >()</span></span>;</span><br><span ></span><br><span > <span ><span >int</span> <span >getRole</span><span >()</span></span>;</span><br><span > <span >String <span >getDescription</span><span >()</span></span>;</span><br><span > <span >String <span >getResourceDescription</span><span >()</span></span>;</span><br><span > <span >BeanDefinition <span >getOriginatingBeanDefinition</span><span >()</span></span>;</span><br><span >}</span><br></pre></td> </tr></table></figure>现在可以看loadBeanDefinitions()
方法了,这个方法会根据配置,加载各个 Bean,然后放到 BeanFactory 中
第一个if是看有没有系统指定的配置文件,如果没有的话就走第二个if加载我们最开始传入的classpath:application-ioc.xml
离解析越来越近了
这里先小小的看一下Spring中的设计模式,我们跟着loadBeanDefinitions()
方法往下走,最终会进入类XmlBeanDefinitionReader,这是因为我们这里要解析的配置文件是XML。如果我们使用Java类配置或者是Groovy的话就是另外的类了。看一下这个类继承图:
接着看
<figure ><table><tr> <td ><pre><span >1</span><br><span >2</span><br><span >3</span><br><span >4</span><br><span >5</span><br><span >6</span><br><span >7</span><br><span >8</span><br><span >9</span><br><span >10</span><br><span >11</span><br><span >12</span><br><span >13</span><br><span >14</span><br><span >15</span><br><span >16</span><br><span >17</span><br><span >18</span><br><span >19</span><br><span >20</span><br><span >21</span><br><span >22</span><br><span >23</span><br><span >24</span><br><span >25</span><br><span >26</span><br><span >27</span><br><span >28</span><br><span >29</span><br><span >30</span><br><span >31</span><br><span >32</span><br><span >33</span><br><span >34</span><br><span >35</span><br><span >36</span><br><span >37</span><br><span >38</span><br><span >39</span><br><span >40</span><br><span >41</span><br></pre></td> <td ><pre><span ><span ><span >public</span> <span >int</span> <span >loadBeanDefinitions</span>(<span >EncodedResource encodedResource</span>) throws BeanDefinitionStoreException </span>{</span><br><span > Assert.notNull(encodedResource, <span >"EncodedResource must not be null"</span>);</span><br><span > <span >if</span> (logger.isInfoEnabled()) {</span><br><span > logger.info(<span >"Loading XML bean definitions from "</span> + encodedResource.getResource());</span><br><span > }</span><br><span ></span><br><span > Set<EncodedResource> currentResources = <span >this</span>.resourcesCurrentlyBeingLoaded.<span >get</span>();</span><br><span > <span >if</span> (currentResources == <span >null</span>) {</span><br><span > currentResources = <span >new</span> HashSet<>(<span >4</span>);</span><br><span > <span >this</span>.resourcesCurrentlyBeingLoaded.<span >set</span>(currentResources);</span><br><span > }</span><br><span > <span >if</span> (!currentResources.<span >add</span>(encodedResource)) {</span><br><span > <span >throw</span> <span >new</span> BeanDefinitionStoreException(</span><br><span > <span >"Detected cyclic loading of "</span> + encodedResource + <span >" - check your import definitions!"</span>);</span><br><span > }</span><br><span > <span >try</span> {</span><br><span > <span >//获取文件流</span></span><br><span > InputStream inputStream = encodedResource.getResource().getInputStream();</span><br><span > <span >try</span> {</span><br><span > InputSource inputSource = <span >new</span> InputSource(inputStream);</span><br><span > <span >if</span> (encodedResource.getEncoding() != <span >null</span>) {</span><br><span > inputSource.setEncoding(encodedResource.getEncoding());</span><br><span > }</span><br><span > <span >//加载</span></span><br><span > <span >return</span> doLoadBeanDefinitions(inputSource, encodedResource.getResource());</span><br><span > }</span><br><span > <span >finally</span> {</span><br><span > inputStream.close();</span><br><span > }</span><br><span > }</span><br><span > <span >catch</span> (IOException ex) {</span><br><span > <span >throw</span> <span >new</span> BeanDefinitionStoreException(</span><br><span > <span >"IOException parsing XML document from "</span> + encodedResource.getResource(), ex);</span><br><span > }</span><br><span > <span >finally</span> {</span><br><span > currentResources.<span >remove</span>(encodedResource);</span><br><span > <span >if</span> (currentResources.isEmpty()) {</span><br><span > <span >this</span>.resourcesCurrentlyBeingLoaded.<span >remove</span>();</span><br><span > }</span><br><span > }</span><br><span > }</span><br></pre></td> </tr></table></figure>下面是分为两步
<figure ><table><tr> <td ><pre><span >1</span><br><span >2</span><br><span >3</span><br><span >4</span><br><span >5</span><br><span >6</span><br><span >7</span><br><span >8</span><br><span >9</span><br><span >10</span><br><span >11</span><br><span >12</span><br><span >13</span><br><span >14</span><br><span >15</span><br><span >16</span><br><span >17</span><br><span >18</span><br><span >19</span><br><span >20</span><br><span >21</span><br><span >22</span><br><span >23</span><br><span >24</span><br><span >25</span><br><span >26</span><br><span >27</span><br><span >28</span><br><span >29</span><br><span >30</span><br><span >31</span><br><span >32</span><br></pre></td> <td ><pre><span ><span >protected</span> <span >int</span> doLoadBeanDefinitions(InputSource inputSource, Resource resource)</span><br><span > <span >throws</span> BeanDefinitionStoreException {</span><br><span > <span >try</span> {</span><br><span > <span >//将 xml 文件转换为 Document 对象</span></span><br><span > Document doc = doLoadDocument(inputSource, resource);</span><br><span > <span >//根据Document对象注册Bean</span></span><br><span > <span ><span >return</span> <span >registerBeanDefinitions</span><span >(doc, resource)</span></span>;</span><br><span > }</span><br><span > <span >catch</span> (BeanDefinitionStoreException ex) {</span><br><span > <span >throw</span> ex;</span><br><span > }</span><br><span > <span >catch</span> (SAXParseException ex) {</span><br><span > <span >throw</span> <span >new</span> XmlBeanDefinitionStoreException(resource.getDescription(),</span><br><span > <span >"Line "</span> + ex.getLineNumber() + <span >" in XML document from "</span> + resource + <span >" is invalid"</span>, ex);</span><br><span > }</span><br><span > <span >catch</span> (SAXException ex) {</span><br><span > <span >throw</span> <span >new</span> XmlBeanDefinitionStoreException(resource.getDescription(),</span><br><span > <span >"XML document from "</span> + resource + <span >" is invalid"</span>, ex);</span><br><span > }</span><br><span > <span >catch</span> (ParserConfigurationException ex) {</span><br><span > <span >throw</span> <span >new</span> BeanDefinitionStoreException(resource.getDescription(),</span><br><span > <span >"Parser configuration exception parsing XML from "</span> + resource, ex);</span><br><span > }</span><br><span > <span >catch</span> (IOException ex) {</span><br><span > <span >throw</span> <span >new</span> BeanDefinitionStoreException(resource.getDescription(),</span><br><span > <span >"IOException parsing XML document from "</span> + resource, ex);</span><br><span > }</span><br><span > <span >catch</span> (Throwable ex) {</span><br><span > <span >throw</span> <span >new</span> BeanDefinitionStoreException(resource.getDescription(),</span><br><span > <span >"Unexpected exception parsing XML document from "</span> + resource, ex);</span><br><span > }</span><br><span > }</span><br></pre></td> </tr></table></figure>文件转换就不详细展开了,接着往下看
preProcessXml和postProcessXml着两个办法是留给我们实现DefaultBeanDefinitionDocumentReader方法后自定义实现的
接下来,看核心解析方法 parseBeanDefinitions()
接着往下看这些标签的处理方式
简单看一下<bean> 标签的处理方式</bean>
<figure ><table><tr> <td ><pre><span >1</span><br><span >2</span><br><span >3</span><br><span >4</span><br><span >5</span><br><span >6</span><br><span >7</span><br><span >8</span><br><span >9</span><br><span >10</span><br><span >11</span><br><span >12</span><br><span >13</span><br><span >14</span><br><span >15</span><br><span >16</span><br><span >17</span><br></pre></td> <td ><pre><span ><span ><span >protected</span> <span >void</span> <span >processBeanDefinition</span>(<span >Element ele, BeanDefinitionParserDelegate <span >delegate</span></span>) </span>{</span><br><span > <span >//创建BeanDefinition</span></span><br><span > BeanDefinitionHolder bdHolder = <span >delegate</span>.parseBeanDefinitionElement(ele);</span><br><span > <span >if</span> (bdHolder != <span >null</span>) {</span><br><span > bdHolder = <span >delegate</span>.decorateBeanDefinitionIfRequired(ele, bdHolder);</span><br><span > <span >try</span> {</span><br><span > <span >// Register the final decorated instance.</span></span><br><span > BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, getReaderContext().getRegistry());</span><br><span > }</span><br><span > <span >catch</span> (BeanDefinitionStoreException ex) {</span><br><span > getReaderContext().error(<span >"Failed to register bean definition with name '"</span> +</span><br><span > bdHolder.getBeanName() + <span >"'"</span>, ele, ex);</span><br><span > }</span><br><span > <span >// Send registration event.</span></span><br><span > getReaderContext().fireComponentRegistered(<span >new</span> BeanComponentDefinition(bdHolder));</span><br><span > }</span><br><span > }</span><br></pre></td> </tr></table></figure>先从第一行往下看
<figure ><table><tr> <td ><pre><span >1</span><br><span >2</span><br><span >3</span><br><span >4</span><br><span >5</span><br><span >6</span><br><span >7</span><br><span >8</span><br><span >9</span><br><span >10</span><br><span >11</span><br><span >12</span><br><span >13</span><br><span >14</span><br><span >15</span><br><span >16</span><br><span >17</span><br><span >18</span><br><span >19</span><br><span >20</span><br><span >21</span><br><span >22</span><br><span >23</span><br><span >24</span><br><span >25</span><br><span >26</span><br><span >27</span><br><span >28</span><br><span >29</span><br><span >30</span><br><span >31</span><br><span >32</span><br><span >33</span><br><span >34</span><br><span >35</span><br><span >36</span><br><span >37</span><br><span >38</span><br><span >39</span><br><span >40</span><br><span >41</span><br><span >42</span><br><span >43</span><br><span >44</span><br><span >45</span><br><span >46</span><br><span >47</span><br><span >48</span><br><span >49</span><br><span >50</span><br><span >51</span><br><span >52</span><br><span >53</span><br><span >54</span><br><span >55</span><br><span >56</span><br><span >57</span><br><span >58</span><br><span >59</span><br><span >60</span><br><span >61</span><br><span >62</span><br><span >63</span><br><span >64</span><br><span >65</span><br><span >66</span><br><span >67</span><br><span >68</span><br><span >69</span><br><span >70</span><br><span >71</span><br><span >72</span><br></pre></td> <td ><pre><span ></span><br><span ><span >public</span> <span >BeanDefinitionHolder </span>parseBeanDefinitionElement(Element ele) {</span><br><span > return parseBeanDefinitionElement(ele, null)<span >;</span></span><br><span >}</span><br><span ></span><br><span ><span >public</span> <span >BeanDefinitionHolder </span>parseBeanDefinitionElement(Element ele, <span >BeanDefinition </span>containingBean) {</span><br><span > <span >String </span>id = ele.getAttribute(ID_ATTRIBUTE)<span >;</span></span><br><span > <span >String </span>nameAttr = ele.getAttribute(NAME_ATTRIBUTE)<span >;</span></span><br><span ></span><br><span > List<<span >String> </span>aliases = new ArrayList<<span >String>();</span></span><br><span ><span ></span></span><br><span ><span > </span> // 将 name 属性的定义按照 “逗号、分号、空格” 切分,形成一个 别名列表数组,</span><br><span > <span >if</span> (<span >StringUtils.hasLength(nameAttr)) </span>{</span><br><span > <span >String[] </span>nameArr = <span >StringUtils.tokenizeToStringArray(nameAttr, </span><span >MULTI_VALUE_ATTRIBUTE_DELIMITERS);</span></span><br><span ><span > </span> aliases.<span >addAll(Arrays.asList(nameArr));</span></span><br><span ><span > </span> }</span><br><span ></span><br><span > <span >String </span><span >beanName </span>= id<span >;</span></span><br><span > // 如果没有指定id, 那么用别名列表的第一个名字作为<span >beanName</span></span><br><span ><span > </span> <span >if</span> (!<span >StringUtils.hasText(beanName) </span>&& !aliases.isEmpty()) {</span><br><span > <span >beanName </span>= aliases.remove(<span >0</span>)<span >;</span></span><br><span > <span >if</span> (logger.isDebugEnabled()) {</span><br><span > logger.debug(<span >"No XML 'id' specified - using '"</span> + <span >beanName </span>+</span><br><span > <span >"' as bean name and "</span> + aliases + <span >" as aliases"</span>)<span >;</span></span><br><span > }</span><br><span > }</span><br><span ></span><br><span > <span >if</span> (containingBean == null) {</span><br><span > checkNameUniqueness(<span >beanName, </span>aliases, ele)<span >;</span></span><br><span > }</span><br><span ></span><br><span > // 根据 <<span >bean </span>...>...</<span >bean> </span>中的配置创建 <span >BeanDefinition,然后把配置中的信息都设置到实例中,</span></span><br><span ><span > </span> // 这行执行完毕,一个 <span >BeanDefinition </span>实例就出来了。等下接着往下看</span><br><span > AbstractBeanDefinition <span >beanDefinition </span>= parseBeanDefinitionElement(ele, <span >beanName, </span>containingBean)<span >;</span></span><br><span ></span><br><span > // <<span >bean </span>/> 标签完成</span><br><span > <span >if</span> (<span >beanDefinition </span>!= null) {</span><br><span > // 如果没有设置 id 和 name,那么此时的 <span >beanName </span>就会为 null</span><br><span > <span >if</span> (!<span >StringUtils.hasText(beanName)) </span>{</span><br><span > try {</span><br><span > <span >if</span> (containingBean != null) {</span><br><span > <span >beanName </span>= <span >BeanDefinitionReaderUtils.generateBeanName(</span></span><br><span ><span > </span> <span >beanDefinition, </span>this.readerContext.getRegistry(), true)<span >;</span></span><br><span > }</span><br><span > <span >else</span> {</span><br><span > <span >beanName </span>= this.readerContext.generateBeanName(<span >beanDefinition);</span></span><br><span ><span ></span></span><br><span ><span > </span> <span >String </span><span >beanClassName </span>= <span >beanDefinition.getBeanClassName();</span></span><br><span ><span > </span> <span >if</span> (<span >beanClassName </span>!= null &&</span><br><span > <span >beanName.startsWith(beanClassName) </span>&& <span >beanName.length() </span>> <span >beanClassName.length() </span>&&</span><br><span > !this.readerContext.getRegistry().<span >isBeanNameInUse(beanClassName)) </span>{</span><br><span > // 把 <span >beanClassName </span>设置为 <span >Bean </span>的别名</span><br><span > aliases.<span >add(beanClassName);</span></span><br><span ><span > </span> }</span><br><span > }</span><br><span > <span >if</span> (logger.isDebugEnabled()) {</span><br><span > logger.debug(<span >"Neither XML 'id' nor 'name' specified - "</span> +</span><br><span > <span >"using generated bean name ["</span> + <span >beanName </span>+ <span >"]"</span>)<span >;</span></span><br><span > }</span><br><span > }</span><br><span > catch (Exception ex) {</span><br><span > error(ex.getMessage(), ele)<span >;</span></span><br><span > return null<span >;</span></span><br><span > }</span><br><span > }</span><br><span > <span >String[] </span>aliasesArray = <span >StringUtils.toStringArray(aliases);</span></span><br><span ><span > </span> // 返回 <span >BeanDefinitionHolder</span></span><br><span ><span > </span> return new <span >BeanDefinitionHolder(beanDefinition, </span><span >beanName, </span>aliasesArray)<span >;</span></span><br><span > }</span><br><span ></span><br><span > return null<span >;</span></span><br><span >}</span><br></pre></td> </tr></table></figure>接着是最重要的地方,如何根据配置创建 BeanDefinition 实例
<figure ><table><tr> <td ><pre><span >1</span><br><span >2</span><br><span >3</span><br><span >4</span><br><span >5</span><br><span >6</span><br><span >7</span><br><span >8</span><br><span >9</span><br><span >10</span><br><span >11</span><br><span >12</span><br><span >13</span><br><span >14</span><br><span >15</span><br><span >16</span><br><span >17</span><br><span >18</span><br><span >19</span><br><span >20</span><br><span >21</span><br><span >22</span><br><span >23</span><br><span >24</span><br><span >25</span><br><span >26</span><br><span >27</span><br><span >28</span><br><span >29</span><br><span >30</span><br><span >31</span><br><span >32</span><br><span >33</span><br><span >34</span><br><span >35</span><br><span >36</span><br><span >37</span><br><span >38</span><br><span >39</span><br><span >40</span><br><span >41</span><br><span >42</span><br><span >43</span><br><span >44</span><br><span >45</span><br><span >46</span><br><span >47</span><br><span >48</span><br><span >49</span><br><span >50</span><br><span >51</span><br><span >52</span><br><span >53</span><br><span >54</span><br><span >55</span><br><span >56</span><br><span >57</span><br><span >58</span><br><span >59</span><br><span >60</span><br><span >61</span><br></pre></td> <td ><pre><span ></span><br><span ><span >public</span> AbstractBeanDefinition parseBeanDefinitionElement(</span><br><span > Element ele, <span >String</span> beanName, BeanDefinition containingBean) {</span><br><span ></span><br><span > <span >this</span>.parseState.push(<span >new</span> BeanEntry(beanName));</span><br><span ></span><br><span > <span >String</span> className = <span >null</span>;</span><br><span > <span >if</span> (ele.hasAttribute(CLASS_ATTRIBUTE)) {</span><br><span > className = ele.getAttribute(CLASS_ATTRIBUTE).<span >trim</span>();</span><br><span > }</span><br><span ></span><br><span > <span >try</span> {</span><br><span > <span >String</span> parent = <span >null</span>;</span><br><span > <span >if</span> (ele.hasAttribute(PARENT_ATTRIBUTE)) {</span><br><span > parent = ele.getAttribute(PARENT_ATTRIBUTE);</span><br><span > }</span><br><span > <span >// 创建 BeanDefinition,然后设置类信息</span></span><br><span > AbstractBeanDefinition bd = createBeanDefinition(className, parent);</span><br><span ></span><br><span > <span >// 设置 BeanDefinition 的一堆属性,这些属性定义在 AbstractBeanDefinition 中</span></span><br><span > parseBeanDefinitionAttributes(ele, beanName, containingBean, bd);</span><br><span > bd.setDescription(DomUtils.getChildElementValueByTagName(ele, DESCRIPTION_ELEMENT));</span><br><span ></span><br><span > <span >/**</span></span><br><span ><span > * 下面的一堆是解析 <bean>......</bean> 内部的子元素,</span></span><br><span ><span > * 解析出来以后的信息都放到 bd 的属性中</span></span><br><span ><span > */</span></span><br><span ></span><br><span > <span >// 解析 <meta /></span></span><br><span > parseMetaElements(ele, bd);</span><br><span > <span >// 解析 <lookup-method /></span></span><br><span > parseLookupOverrideSubElements(ele, bd.getMethodOverrides());</span><br><span > <span >// 解析 <replaced-method /></span></span><br><span > parseReplacedMethodSubElements(ele, bd.getMethodOverrides());</span><br><span > <span >// 解析 <constructor-arg /></span></span><br><span > parseConstructorArgElements(ele, bd);</span><br><span > <span >// 解析 <property /></span></span><br><span > parsePropertyElements(ele, bd);</span><br><span > <span >// 解析 <qualifier /></span></span><br><span > parseQualifierElements(ele, bd);</span><br><span ></span><br><span > bd.setResource(<span >this</span>.readerContext.getResource());</span><br><span > bd.setSource(extractSource(ele));</span><br><span ></span><br><span > <span >return</span> bd;</span><br><span > }</span><br><span > <span >catch</span> (ClassNotFoundException ex) {</span><br><span > error(<span >"Bean class ["</span> + className + <span >"] not found"</span>, ele, ex);</span><br><span > }</span><br><span > <span >catch</span> (NoClassDefFoundError err) {</span><br><span > error(<span >"Class that bean class ["</span> + className + <span >"] depends on not found"</span>, ele, err);</span><br><span > }</span><br><span > <span >catch</span> (Throwable ex) {</span><br><span > error(<span >"Unexpected failure during bean definition parsing"</span>, ele, ex);</span><br><span > }</span><br><span > <span >finally</span> {</span><br><span > <span >this</span>.parseState.pop();</span><br><span > }</span><br><span ></span><br><span > <span >return</span> <span >null</span>;</span><br><span >}</span><br></pre></td> </tr></table></figure>终于终于这么长时间把这个BeanDefinition搞出来了,太不容易了!!!
接着回到刚才的代码
<figure ><table><tr> <td ><pre><span >1</span><br><span >2</span><br><span >3</span><br><span >4</span><br><span >5</span><br><span >6</span><br><span >7</span><br><span >8</span><br><span >9</span><br><span >10</span><br><span >11</span><br><span >12</span><br><span >13</span><br><span >14</span><br><span >15</span><br><span >16</span><br><span >17</span><br><span >18</span><br><span >19</span><br></pre></td> <td ><pre><span ></span><br><span ><span ><span >protected</span> <span >void</span> <span >processBeanDefinition</span>(<span >Element ele, BeanDefinitionParserDelegate <span >delegate</span></span>) </span>{</span><br><span > <span >// 上面说的一堆</span></span><br><span > BeanDefinitionHolder bdHolder = <span >delegate</span>.parseBeanDefinitionElement(ele);</span><br><span > <span >if</span> (bdHolder != <span >null</span>) {</span><br><span > <span >// 如果有自定义属性的话,进行相应的解析</span></span><br><span > bdHolder = <span >delegate</span>.decorateBeanDefinitionIfRequired(ele, bdHolder);</span><br><span > <span >try</span> {</span><br><span > <span >// 注册Bean</span></span><br><span > BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, getReaderContext().getRegistry());</span><br><span > }</span><br><span > <span >catch</span> (BeanDefinitionStoreException ex) {</span><br><span > getReaderContext().error(<span >"Failed to register bean definition with name '"</span> +</span><br><span > bdHolder.getBeanName() + <span >"'"</span>, ele, ex);</span><br><span > }</span><br><span > <span >// 注册完成后,发送事件</span></span><br><span > getReaderContext().fireComponentRegistered(<span >new</span> BeanComponentDefinition(bdHolder));</span><br><span > }</span><br><span >}</span><br></pre></td> </tr></table></figure>这次看注册bean的实现
<figure ><table><tr> <td ><pre><span >1</span><br><span >2</span><br><span >3</span><br><span >4</span><br><span >5</span><br><span >6</span><br><span >7</span><br><span >8</span><br><span >9</span><br><span >10</span><br><span >11</span><br><span >12</span><br><span >13</span><br><span >14</span><br><span >15</span><br><span >16</span><br><span >17</span><br></pre></td> <td ><pre><span ></span><br><span ><span >public</span> static void registerBeanDefinition(</span><br><span > <span >BeanDefinitionHolder </span>definitionHolder, <span >BeanDefinitionRegistry </span>registry)</span><br><span > throws <span >BeanDefinitionStoreException </span>{</span><br><span ></span><br><span > <span >String </span><span >beanName </span>= definitionHolder.getBeanName()<span >;</span></span><br><span > // 注册这个 <span >Bean</span></span><br><span ><span > </span> registry.registerBeanDefinition(<span >beanName, </span>definitionHolder.getBeanDefinition())<span >;</span></span><br><span ></span><br><span > // 如果配置有别名的话,也要根据别名全部注册一遍</span><br><span > <span >String[] </span>aliases = definitionHolder.getAliases()<span >;</span></span><br><span > <span >if</span> (aliases != null) {</span><br><span > for (<span >String </span><span >alias</span> : aliases) {</span><br><span > registry.registerAlias(<span >beanName, </span><span >alias</span>)<span >;</span></span><br><span > }</span><br><span > }</span><br><span >}</span><br></pre></td> </tr></table></figure>又是一个长方法。。。
<figure ><table><tr> <td ><pre><span >1</span><br><span >2</span><br><span >3</span><br><span >4</span><br><span >5</span><br><span >6</span><br><span >7</span><br><span >8</span><br><span >9</span><br><span >10</span><br><span >11</span><br><span >12</span><br><span >13</span><br><span >14</span><br><span >15</span><br><span >16</span><br><span >17</span><br><span >18</span><br><span >19</span><br><span >20</span><br><span >21</span><br><span >22</span><br><span >23</span><br><span >24</span><br><span >25</span><br><span >26</span><br><span >27</span><br><span >28</span><br><span >29</span><br><span >30</span><br><span >31</span><br><span >32</span><br><span >33</span><br><span >34</span><br><span >35</span><br><span >36</span><br><span >37</span><br><span >38</span><br><span >39</span><br><span >40</span><br><span >41</span><br><span >42</span><br><span >43</span><br><span >44</span><br><span >45</span><br><span >46</span><br><span >47</span><br><span >48</span><br><span >49</span><br><span >50</span><br><span >51</span><br><span >52</span><br><span >53</span><br><span >54</span><br><span >55</span><br><span >56</span><br><span >57</span><br><span >58</span><br><span >59</span><br><span >60</span><br><span >61</span><br><span >62</span><br><span >63</span><br><span >64</span><br><span >65</span><br><span >66</span><br><span >67</span><br><span >68</span><br><span >69</span><br><span >70</span><br><span >71</span><br><span >72</span><br><span >73</span><br><span >74</span><br><span >75</span><br><span >76</span><br><span >77</span><br><span >78</span><br><span >79</span><br><span >80</span><br><span >81</span><br><span >82</span><br><span >83</span><br><span >84</span><br><span >85</span><br><span >86</span><br><span >87</span><br><span >88</span><br><span >89</span><br><span >90</span><br></pre></td> <td ><pre><span ><span >@Override</span></span><br><span ><span >public</span> void registerBeanDefinition(<span >String </span><span >beanName, </span><span >BeanDefinition </span><span >beanDefinition)</span></span><br><span ><span > </span> throws <span >BeanDefinitionStoreException </span>{</span><br><span ></span><br><span > <span >Assert</span>.hasText(<span >beanName, </span><span >"Bean name must not be empty"</span>)<span >;</span></span><br><span > <span >Assert</span>.notNull(<span >beanDefinition, </span><span >"BeanDefinition must not be null"</span>)<span >;</span></span><br><span ></span><br><span > <span >if</span> (<span >beanDefinition </span>instanceof AbstractBeanDefinition) {</span><br><span > try {</span><br><span > ((AbstractBeanDefinition) <span >beanDefinition).validate();</span></span><br><span ><span > </span> }</span><br><span > catch (<span >BeanDefinitionValidationException </span>ex) {</span><br><span > throw new <span >BeanDefinitionStoreException(...);</span></span><br><span ><span > </span> }</span><br><span > }</span><br><span ></span><br><span > <span >BeanDefinition </span>oldBeanDefinition<span >;</span></span><br><span ></span><br><span > // 所有的 <span >Bean </span>注册后都会被放入到这个<span >beanDefinitionMap </span>中,查看是否已存在这个<span >bean</span></span><br><span ><span > </span> oldBeanDefinition = this.<span >beanDefinitionMap.get(beanName);</span></span><br><span ><span ></span></span><br><span ><span > </span> // 处理重复名称的 <span >Bean </span>定义的情况</span><br><span > <span >if</span> (oldBeanDefinition != null) {</span><br><span > <span >if</span> (!isAllowBeanDefinitionOverriding()) {</span><br><span > // 如果不允许覆盖的话,抛异常</span><br><span > throw new <span >BeanDefinitionStoreException(beanDefinition.getResourceDescription(), </span><span >beanName,</span></span><br><span ><span > </span> <span >"Cannot register bean definition ["</span> + <span >beanDefinition </span>+ <span >"] for bean '"</span> + <span >beanName </span>+</span><br><span > <span >"': There is already ["</span> + oldBeanDefinition + <span >"] bound."</span>)<span >;</span></span><br><span > }</span><br><span > <span >else</span> <span >if</span> (oldBeanDefinition.getRole() < <span >beanDefinition.getRole()) </span>{</span><br><span > // 用框架定义的 <span >Bean </span>覆盖用户自定义的 <span >Bean </span></span><br><span > <span >if</span> (this.logger.isWarnEnabled()) {</span><br><span > this.logger.warn(<span >"Overriding user-defined bean definition for bean '"</span> + <span >beanName </span>+</span><br><span > <span >"' with a framework-generated bean definition: replacing ["</span> +</span><br><span > oldBeanDefinition + <span >"] with ["</span> + <span >beanDefinition </span>+ <span >"]"</span>)<span >;</span></span><br><span > }</span><br><span > }</span><br><span > <span >else</span> <span >if</span> (!<span >beanDefinition.equals(oldBeanDefinition)) </span>{</span><br><span > // 用新的 <span >Bean </span>覆盖旧的 <span >Bean</span></span><br><span ><span > </span> <span >if</span> (this.logger.isWarnEnabled()) {</span><br><span > this.logger.warn(<span >"Overriding user-defined bean definition for bean '"</span> + <span >beanName </span>+</span><br><span > <span >"' with a framework-generated bean definition: replacing ["</span> +</span><br><span > oldBeanDefinition + <span >"] with ["</span> + <span >beanDefinition </span>+ <span >"]"</span>)<span >;</span></span><br><span > }</span><br><span > }</span><br><span > <span >else</span> {</span><br><span > // log...用同等的 <span >Bean </span>覆盖旧的 <span >Bean</span></span><br><span ><span > </span> <span >if</span> (this.logger.isInfoEnabled()) {</span><br><span > this.logger.info(<span >"Overriding bean definition for bean '"</span> + <span >beanName </span>+</span><br><span > <span >"' with a different definition: replacing ["</span> + oldBeanDefinition +</span><br><span > <span >"] with ["</span> + <span >beanDefinition </span>+ <span >"]"</span>)<span >;</span></span><br><span > }</span><br><span > }</span><br><span > // 覆盖</span><br><span > this.<span >beanDefinitionMap.put(beanName, </span><span >beanDefinition);</span></span><br><span ><span > </span> }</span><br><span > <span >else</span> {</span><br><span > // 判断是否已经有其他的 <span >Bean </span>开始初始化了.注意,<span >"注册Bean"</span> 这个动作结束,<span >Bean </span>依然还没有初始化 在 Spring 容器启动的最后,会 预初始化 所有的 singleton <span >beans</span></span><br><span ><span > </span> <span >if</span> (hasBeanCreationStarted()) {</span><br><span > // Cannot modify startup-time collection elements anymore (for stable <span >iteration)</span></span><br><span ><span > </span> synchronized (this.<span >beanDefinitionMap) </span>{</span><br><span > this.<span >beanDefinitionMap.put(beanName, </span><span >beanDefinition);</span></span><br><span ><span > </span> List<<span >String> </span>updatedDefinitions = new ArrayList<<span >String>(this.beanDefinitionNames.size() </span>+ <span >1</span>)<span >;</span></span><br><span > updatedDefinitions.<span >addAll(this.beanDefinitionNames);</span></span><br><span ><span > </span> updatedDefinitions.<span >add(beanName);</span></span><br><span ><span > </span> this.<span >beanDefinitionNames </span>= updatedDefinitions<span >;</span></span><br><span > <span >if</span> (this.manualSingletonNames.contains(<span >beanName)) </span>{</span><br><span > Set<<span >String> </span>updatedSingletons = new LinkedHashSet<<span >String>(this.manualSingletonNames);</span></span><br><span ><span > </span> updatedSingletons.remove(<span >beanName);</span></span><br><span ><span > </span> this.manualSingletonNames = updatedSingletons<span >;</span></span><br><span > }</span><br><span > }</span><br><span > }</span><br><span > <span >else</span> {</span><br><span > </span><br><span ></span><br><span > // 将 <span >BeanDefinition </span>放到这个 <span >map</span> 中,这个 <span >map</span> 保存了所有的 <span >BeanDefinition</span></span><br><span ><span > </span> this.<span >beanDefinitionMap.put(beanName, </span><span >beanDefinition);</span></span><br><span ><span > </span> // 这是个 ArrayList,所以会按照 <span >bean </span>配置的顺序保存每一个注册的 <span >Bean </span>的名字</span><br><span > this.<span >beanDefinitionNames.add(beanName);</span></span><br><span ><span > </span> // 这是个 LinkedHashSet,代表的是手动注册的 singleton <span >bean,</span></span><br><span ><span > </span> this.manualSingletonNames.remove(<span >beanName);</span></span><br><span ><span > </span> }</span><br><span > this.frozenBeanDefinitionNames = null<span >;</span></span><br><span > }</span><br><span ></span><br><span > <span >if</span> (oldBeanDefinition != null <span >||</span> containsSingleton(<span >beanName)) </span>{</span><br><span > resetBeanDefinition(<span >beanName);</span></span><br><span ><span > </span> }</span><br><span >}</span><br></pre></td> </tr></table></figure>到这里已经初始化了 Bean 容器,<bean>的配置也相应的转换为了一个个BeanDefinition,然后注册了所有的BeanDefinition到beanDefinitionMap</bean>
prepareBeanFactory()
现在回到最开始的refresh()
方法prepareBeanFactory()
这个方法主要会设置BeanFactory的类加载器、添加几个 BeanPostProcessor、手动注册几个特殊的bean
继续撸代码
<figure ><table><tr> <td ><pre><span >1</span><br><span >2</span><br><span >3</span><br><span >4</span><br><span >5</span><br><span >6</span><br><span >7</span><br><span >8</span><br><span >9</span><br><span >10</span><br><span >11</span><br><span >12</span><br><span >13</span><br><span >14</span><br><span >15</span><br><span >16</span><br><span >17</span><br><span >18</span><br><span >19</span><br><span >20</span><br><span >21</span><br><span >22</span><br><span >23</span><br><span >24</span><br><span >25</span><br><span >26</span><br><span >27</span><br><span >28</span><br><span >29</span><br><span >30</span><br><span >31</span><br><span >32</span><br><span >33</span><br><span >34</span><br><span >35</span><br><span >36</span><br><span >37</span><br><span >38</span><br><span >39</span><br><span >40</span><br><span >41</span><br><span >42</span><br><span >43</span><br><span >44</span><br><span >45</span><br><span >46</span><br><span >47</span><br><span >48</span><br><span >49</span><br><span >50</span><br><span >51</span><br><span >52</span><br><span >53</span><br><span >54</span><br></pre></td> <td ><pre><span ></span><br><span ><span >protected</span> void prepareBeanFactory(ConfigurableListableBeanFactory <span >beanFactory) </span>{</span><br><span ></span><br><span > // 设置为加载当前ApplicationContext类的类加载器</span><br><span > <span >beanFactory.setBeanClassLoader(getClassLoader());</span></span><br><span ><span ></span></span><br><span ><span > </span> // 设置 <span >BeanExpressionResolver</span></span><br><span ><span > </span> <span >beanFactory.setBeanExpressionResolver(new </span>StandardBeanExpressionResolver(<span >beanFactory.getBeanClassLoader()));</span></span><br><span ><span ></span></span><br><span ><span > </span> <span >beanFactory.addPropertyEditorRegistrar(new </span>ResourceEditorRegistrar(this, getEnvironment()))<span >;</span></span><br><span ></span><br><span > // 这里是Spring的又一个扩展点</span><br><span > //在所有实现了Aware接口的<span >bean在初始化的时候,这个 </span>processor负责回调,</span><br><span > // 这个我们很常用,如我们会为了获取 ApplicationContext 而 implement ApplicationContextAware</span><br><span > // 注意:它不仅仅回调 ApplicationContextAware,还会负责回调 EnvironmentAware、ResourceLoaderAware 等</span><br><span > <span >beanFactory.addBeanPostProcessor(new </span>ApplicationContextAwareProcessor(this))<span >;</span></span><br><span ></span><br><span > // 下面几行的意思就是,如果某个 <span >bean </span>依赖于以下几个接口的实现类,在自动装配的时候忽略它们,Spring 会通过其他方式来处理这些依赖。</span><br><span > <span >beanFactory.ignoreDependencyInterface(EnvironmentAware.class);</span></span><br><span ><span > </span> <span >beanFactory.ignoreDependencyInterface(EmbeddedValueResolverAware.class);</span></span><br><span ><span > </span> <span >beanFactory.ignoreDependencyInterface(ResourceLoaderAware.class);</span></span><br><span ><span > </span> <span >beanFactory.ignoreDependencyInterface(ApplicationEventPublisherAware.class);</span></span><br><span ><span > </span> <span >beanFactory.ignoreDependencyInterface(MessageSourceAware.class);</span></span><br><span ><span > </span> <span >beanFactory.ignoreDependencyInterface(ApplicationContextAware.class);</span></span><br><span ><span ></span></span><br><span ><span > </span> //下面几行就是为特殊的几个 <span >bean </span>赋值,如果有 <span >bean </span>依赖了以下几个,会注入这边相应的值</span><br><span > <span >beanFactory.registerResolvableDependency(BeanFactory.class, </span><span >beanFactory);</span></span><br><span ><span > </span> <span >beanFactory.registerResolvableDependency(ResourceLoader.class, </span>this)<span >;</span></span><br><span > <span >beanFactory.registerResolvableDependency(ApplicationEventPublisher.class, </span>this)<span >;</span></span><br><span > <span >beanFactory.registerResolvableDependency(ApplicationContext.class, </span>this)<span >;</span></span><br><span ></span><br><span > // 注册 事件监听器</span><br><span > <span >beanFactory.addBeanPostProcessor(new </span>ApplicationListenerDetector(this))<span >;</span></span><br><span ></span><br><span > // 如果存在<span >bean名称为loadTimeWeaver的bean则注册一个BeanPostProcessor</span></span><br><span ><span > </span> <span >if</span> (<span >beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) </span>{</span><br><span > <span >beanFactory.addBeanPostProcessor(new </span>LoadTimeWeaverAwareProcessor(<span >beanFactory));</span></span><br><span ><span > </span> // Set a temporary ClassLoader for type matching.</span><br><span > <span >beanFactory.setTempClassLoader(new </span>ContextTypeMatchClassLoader(<span >beanFactory.getBeanClassLoader()));</span></span><br><span ><span > </span> }</span><br><span ></span><br><span > // 如果没有定义 <span >"environment"</span> 这个 <span >bean,那么 </span>Spring 会 <span >"手动"</span> 注册一个</span><br><span > <span >if</span> (!<span >beanFactory.containsLocalBean(ENVIRONMENT_BEAN_NAME)) </span>{</span><br><span > <span >beanFactory.registerSingleton(ENVIRONMENT_BEAN_NAME, </span>getEnvironment())<span >;</span></span><br><span > }</span><br><span > // 如果没有定义 <span >"systemProperties"</span> 这个 <span >bean,那么 </span>Spring 会 <span >"手动"</span> 注册一个</span><br><span > <span >if</span> (!<span >beanFactory.containsLocalBean(SYSTEM_PROPERTIES_BEAN_NAME)) </span>{</span><br><span > <span >beanFactory.registerSingleton(SYSTEM_PROPERTIES_BEAN_NAME, </span>getEnvironment().getSystemProperties())<span >;</span></span><br><span > }</span><br><span > // 如果没有定义 <span >"systemEnvironment"</span> 这个 <span >bean,那么 </span>Spring 会 <span >"手动"</span> 注册一个</span><br><span > <span >if</span> (!<span >beanFactory.containsLocalBean(SYSTEM_ENVIRONMENT_BEAN_NAME)) </span>{</span><br><span > <span >beanFactory.registerSingleton(SYSTEM_ENVIRONMENT_BEAN_NAME, </span>getEnvironment().getSystemEnvironment())<span >;</span></span><br><span > }</span><br><span >}</span><br></pre></td> </tr></table></figure>postProcessBeanFactory()
这个比较简单,又是Spring的一个扩展点
如果有Bean实现了BeanFactoryPostProcessor接口,
那么在容器初始化以后,Spring 会负责调用里面的 postProcessBeanFactory 方法。具体的子类可以在这步的时候添加一些特殊的 BeanFactoryPostProcessor 的实现类或做点什么事
invokeBeanFactoryPostProcessors()
调用 BeanFactoryPostProcessor 各个实现类的 postProcessBeanFactory(factory) 方法
registerBeanPostProcessors()
又是一个扩展点
注册 BeanPostProcessor 的实现类,注意不是BeanFactoryPostProcessor
此接口有两个方法: postProcessBeforeInitialization 和 postProcessAfterInitialization
分别会在Bean初始化之前和初始化之后得到执行
initMessageSource()
初始化当前 ApplicationContext 的 MessageSource,有想了解国际化的相关知识可以深入研究一下
initApplicationEventMulticaster()
这个方法主要为初始化当前 ApplicationContext 的事件广播器
撸代码:
<figure ><table><tr> <td ><pre><span >1</span><br><span >2</span><br><span >3</span><br><span >4</span><br><span >5</span><br><span >6</span><br><span >7</span><br><span >8</span><br><span >9</span><br><span >10</span><br><span >11</span><br><span >12</span><br><span >13</span><br><span >14</span><br><span >15</span><br><span >16</span><br><span >17</span><br><span >18</span><br><span >19</span><br><span >20</span><br></pre></td> <td ><pre><span ><span >private</span> void initApplicationEventMulticaster() throws BeansException {</span><br><span > <span >//如果用户配置了自定义事件广播器,就使用用户的</span></span><br><span > <span >if</span> (containsLocalBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME )) {</span><br><span > <span >this</span>.applicationEventMulticaster = (ApplicationEventMulticaster)</span><br><span > getBean( APPLICATION_EVENT_MULTICASTER_BEAN_NAME , </span><br><span > ApplicationEventMulticaster.<span >class</span> );</span><br><span > <span >if</span> (logger.isInfoEnabled()) {</span><br><span > logger.info(<span >"Using ApplicationEventMulticaster ["</span> </span><br><span > + <span >this</span>. applicationEventMulticaster + <span >"]"</span> );</span><br><span > }</span><br><span > }<span >else</span> {</span><br><span > <span >//使用默认的时间广播器</span></span><br><span > <span >this</span>.applicationEventMulticaster = new SimpleApplicationEventMulticaster();</span><br><span > <span >if</span> (logger.isInfoEnabled()) {</span><br><span > logger.info(<span >"Unable to locate ApplicationEventMulticaster with name '"</span>+</span><br><span > APPLICATION_EVENT_MULTICASTER_BEAN_NAME +</span><br><span > <span >"': using default ["</span> + <span >this</span> .applicationEventMulticaster + <span >"]"</span>);</span><br><span > }</span><br><span > }</span><br><span > }</span><br></pre></td> </tr></table></figure>onRefresh()
又是一个扩展点,子类可以在这里来搞事情
registerListeners()
注册事件监听器
<figure ><table><tr> <td ><pre><span >1</span><br><span >2</span><br><span >3</span><br><span >4</span><br><span >5</span><br><span >6</span><br><span >7</span><br><span >8</span><br><span >9</span><br><span >10</span><br><span >11</span><br><span >12</span><br><span >13</span><br><span >14</span><br><span >15</span><br><span >16</span><br><span >17</span><br><span >18</span><br><span >19</span><br><span >20</span><br><span >21</span><br></pre></td> <td ><pre><span ><span >protected</span> <span >void</span> registerListeners() {</span><br><span > <span >//先添加手动set的一些监听器</span></span><br><span > <span >for</span> (ApplicationListener<?> listener : getApplicationListeners()) {</span><br><span > getApplicationEventMulticaster().addApplicationListener(listener);</span><br><span > }</span><br><span ></span><br><span > <span >//取到监听器的名称,设置到广播器</span></span><br><span > String[] listenerBeanNames = getBeanNamesForType(ApplicationListener.<span >class</span>, <span >true</span>, <span >false</span>);</span><br><span > <span >for</span> (String <span >listenerBeanName :</span> listenerBeanNames) {</span><br><span > getApplicationEventMulticaster().addApplicationListenerBean(listenerBeanName);</span><br><span > }</span><br><span ></span><br><span > <span >// 如果存在早期应用事件,发布</span></span><br><span > Set<ApplicationEvent> earlyEventsToProcess = <span >this</span>.earlyApplicationEvents;</span><br><span > <span >this</span>.earlyApplicationEvents = <span >null</span>;</span><br><span > <span >if</span> (earlyEventsToProcess != <span >null</span>) {</span><br><span > <span >for</span> (ApplicationEvent <span >earlyEvent :</span> earlyEventsToProcess) {</span><br><span > getApplicationEventMulticaster().multicastEvent(earlyEvent);</span><br><span > }</span><br><span > }</span><br><span > }</span><br></pre></td> </tr></table></figure>看到这里不要以为文章结束了,上方那么大的篇幅其实总结起来仅仅只介绍了Bean容器的创建过程,由于平台的字数限制所以本篇文章只能写到这里了。后续内容请看明天的下篇