1、IOC(控制反转)、AOP(切面)、DI (依赖注入)是spring的核心部分

    Spring是一种设计思想的体现,发生了“主从换位”的变化。应用程序由主动的创建对象,转换称了从IOC容器里获取对象,对象的创建、解析和注册都由Spring来替用户实现,用户只管定义。

2、IoC容器的设计与实现--Bean组件与Context组件

使用Spring时,它首先替我们完成的时IOC容器的初始化,初始化的过程包括定义(BeanDefinition)、载入定义(loadBeanDefinitions,包含了解析的方法)、注册定义(registerBeanDefinitions),注册最后落实到代码中就是

private final Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<String, BeanDefinition>(256);

this.beanDefinitionMap.put(beanName, beanDefinition);

注册到map集合中, 将BeanName作为键, BeanDefinition作为值保存。接下来看具体的源码,加深IOC容器初始化的过程理解

2.1Bean组件

bean组件在Spring的org.springframework.beans包下。IOC容器的初始化就在这个包里完成的,定义、载入、注册,对于使用者来说只要完成bean的定义就可以了,其他两个由 Spring 在内部帮我们完成了,对我们来说是透明的。

bean的定义我们不多说,可以用配置文件定义bean,也可以用注解的方式,接下来我们看下Spring的做了那些操作:

2.1.2 BeanFactory概述

BeanFactory是Spring bean容器的根接口.提供获取bean,是否包含bean,是否单例与原型,获取bean类型,bean 别名的方法 。

2.1.3BeanFactory的继承关系

我们可以看到DefaultListableBeanFactory  是最终的实现类,它实现了所有的接口,它也是Spring框架里核心的类之一

2.1.4BeanDefinition概述

BeanDefinition是一个接口类,Bean 的定义主要由 BeanDefinition 实现,项目启动首先是读取bean的xml配置文件,然后解析xml文件中的各种bean的定义,将xml文件中的每一个<bean />元素分别转换解析成一个BeanDefinition对象,其中保存了从配置文件中读取到的该bean的各种信息,以后所有的操作都是对这个对象的操作。

2.1.5 BeanDefinitionReader概述

BeanDefinitionReader同样也是接口类,读取xml配置文件,解析为BeanDefinition对象过程是繁琐的,整个解析过程主要通过下图中的类完成:

2.1.6BeanDefinitionHolder概述

BeanDefinitionHolder是一个class实现类,BeanDefinitionHolder对象中持有的BeanDefinition实例的引用,还有beanName,还有bean的别名

先对这几个类有个大体的了解,接下来从源码中看它们实际的作用。

2.1.7Bean Definition从加载、解析、处理、注册到BeanFactory的过程,也就是IOC容器的初始化过程

  1. Bean Definition加载
    用配置文件的方式定义bean ,首先要做的就是读取xml文件
    public static  void main(String[] args){//直接使用BeanFactory 作为容器
          String xmlPath = "applicationContext.xml";
          BeanFactory factory = new XmlBeanFactory(new ClassPathResource(xmlPath));
          userService = (UserService) factory.getBean("userService");
          userService.add();
    }
    在XmlBeanDefinitionReader类中
    &1.loadBeanDefinitions方法从xml文件中加载beanDefinition,将Resource转化为EncodedResource对象,交给它的重载方法来做加载前的准备,实际去加载xml文件的是方法doLoadBeanDefinitions(InputSource inputSource, Resource resource),
    
    public int loadBeanDefinitions(EncodedResource encodedResource) throws BeanDefinitionStoreException{
    ....
      return doLoadBeanDefinitions(inputSource, encodedResource.getResource());
    ....
    }
    &2.doLoadBeanDefinitions方法中加载得到一个Document对象,把Document和resource交给registerBeanDefinitions完成注册
    
    protected int doLoadBeanDefinitions(InputSource inputSource, Resource resource){
    ....
      Document doc = doLoadDocument(inputSource, resource);
      return registerBeanDefinitions(doc, resource);
    ....
    }
    &3.registerBeanDefinitions(Document doc, Resource resource)方法,这里实际上是创建了一个BeanDefinitionDocumentReader对象然后让它来完成。
    
    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;
    }
    
  2. Bean Definition解析

    在DefaultBeanDefinitionDocumentReader类中
    DefaultBeanDefinitionDocumentReader 是BeanDefinitionDocumentReader的实现类,这个类来实际的解析<bean/>标签
    &1.registerBeanDefinitions()也做的前期准备,真正去解析文件的方法是doRegisterBeanDefinitions()
       
    public void registerBeanDefinitions(Document doc, XmlReaderContext readerContext) {
                  ....
                 doRegisterBeanDefinitions(root);
    }

    &2.doRegisterBeanDefinitions方法将</beans>节点下的每一个<bean/>相对应的bean definition注册。但是真正做这件事的是另一个方法 parseBeanDefinitions(root, this.delegate);
    protected void doRegisterBeanDefinitions(Element root){
         ....
         parseBeanDefinitions(root, this.delegate);
         ....
    }
    &3.<beans/>中还包含<bean/>元素,需要对bean元素进行解析,parseBeanDefinitions方法中调用来
    parseDefaultElement方法来完成对<bean/>元素的解析,具体分解析过程有processBeanDefinition(ele, delegate)方法来实现,就是对beanDefinition的处理。
  3. Bean Definition处理
      在DefaultBeanDefinitionDocumentReader类中
    &1.
    processBeanDefinition方法中将Element对象转化成了BeanDefinitionHolder对象。这个BeanDefinitionHolder对象中持有的BeanDefinition实例的引用,还有beanName,还有bean的别名。
          然后将BeanDefinitionHolder对象和特定的bean工厂作为参数交给BeanDefinitionReaderUtils类来处理来进行注册。到了实际的注册步骤啦
    protected void processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate) {
       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));
       }
    }
  4. Bean Definition注册
    在BeanDefinitionReaderUtils类中

    public static void registerBeanDefinition(
          BeanDefinitionHolder definitionHolder, BeanDefinitionRegistry registry)
          throws BeanDefinitionStoreException {

       // Register bean definition under primary name.
       String beanName = definitionHolder.getBeanName();
       registry.registerBeanDefinition(beanName, definitionHolder.getBeanDefinition());

       // Register aliases for bean name, if any.
       String[] aliases = definitionHolder.getAliases();
       if (aliases != null) {
          for (String alias : aliases) {
             registry.registerAlias(beanName, alias);
          }
       }
    }

    DefaultListableBeanFactory类中,在这个方法中,将BeanDefinition 注册到了ConcurrentHashMap对象中了。注册完成

 

 

 

参考:

https://my.oschina.net/liyurong/blog/1929996

Logo

权威|前沿|技术|干货|国内首个API全生命周期开发者社区

更多推荐