程序员

spring源码学习 - xml方式bean的解析注册过程

2017-01-02  本文已影响569人  ouyangan
为什么开始看spring的源码
怎样高效的看源码
spring容器核心类结构图,方便我们理清思路,主要参考自书籍<<spring源码深度解析 >>
spring容器核心类结构图
下面正式开始源码bug
  1. 创建一个简单的javaBean. 下面debug过程尽量只针对该bean的初始化过程进行跟踪,以免陷入源码细节出不来...
public class TestBean {
  private String name;

  public TestBean() {
  }

  public TestBean(String name) {
      this.name = name;
  }

  public String getName() {
      return name;
  }

  public void setName(String name) {
      this.name = name;
  }
}
  1. spring.xml定义
    <bean id="testBean" class="com.hunt.debug.TestBean">
        <property name="name" value="spring"/>
    </bean>
  1. 利用spring集成单元测试
@RunWith(SpringJUnit4ClassRunner.class)
@WebAppConfiguration(value = "classpath:src/main/webapp")
@ContextConfiguration({"classpath:spring.xml", "classpath:spring/spring-mvc.xml"})
@Transactional
public class DebugSpring {
    private static final Logger log = LoggerFactory.getLogger(DebugSpring.class);
    @Test
    public void testLoad() throws IOException {
        Resource resource = new ClassPathResource("spring.xml");
        BeanFactory xmlBeanFactory = new XmlBeanFactory(resource);
        TestBean testBean = xmlBeanFactory.getBean("testBean", TestBean.class);
        log.debug("test bean name is :{}", testBean.getName());
    }
}
  1. 开始debug

  2. 这里内部真正调用的是第二个构造器


    XmlBeanFactory类结构图
  3. 初始化入口:this.reader.loadBeanDefinitions(resource);

  4. 实际上是private final XmlBeanDefinitionReader reader这个对象负责spring容器的初始化,包括:xml配置文件载入,验证,解析,bean的注册

    XmlBeanDefinitionReader类结构图
  5. 继续进入loadBeanDefinitions(Resource resource)

  6. 进入到的是XmlBeanDefinitionReader中的loadBeanDefinitions(EncodedResource encodedResource):

    Paste_Image.png
  7. 继续进入XmlBeanDefinitionReader中的doLoadBeanDefinitions(InputSource inputSource, Resource resource)`:

    Paste_Image.png
  8. 继续进入XmlBeanDefinitionReader中的registerBeanDefinitions(Document doc, Resource resource):

    Paste_Image.png
  9. 准备数据,进入registerBeanDefinitions(Document doc, XmlReaderContext readerContext):

    Paste_Image.png
  10. 开始进入解析流程doRegisterBeanDefinitions(Element root):

    Paste_Image.png
  11. 终于做好了所有的准备,按照命名空间类别进行解析,解析规则是如果是<beans></beans>则按照默认方式否则按照自定义解析方式...跟进parseBeanDefinitions(root, this.delegate);:

    Paste_Image.png
    Paste_Image.png
  12. 按照标签规则进行解析


    Paste_Image.png
  13. 组装BeanDefinitionHolder并在容器中进行注册 ,为什么需要对容器对象进行包装呢,因为容器对容器和别名是分两个属性进行维护的.

    Paste_Image.png
  14. 组装BeanDefinitionHolder过程

  15. 创建容器数据对象过程,设置数据对象的属性


    Paste_Image.png
  16. 来看下容器对象中的数据对象到底是什么样子的:


  17. 回到processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate),继续最后一步: 向容器中进行注册!!!

    Paste_Image.png
  18. 最后一步,向容器注册是在DefaultListableBeanFactory中的registerBeanDefinition(String beanName, BeanDefinition beanDefinition)进行实现的


  19. 到这里完成了bean向容器的注册,我们可以看下beanDefinitionMap容器已经有了testBean,到这里我们定义的testBean整个初始化过程就结束了

    Paste_Image.png
参考资料
上一篇下一篇

猜你喜欢

热点阅读