• Spring-IOC学习-01 IOC重要的几个接口定义


    IOC容器

    IoC容器:的两个核心功能是(1)完成了完成对象的创建和(2)bean依赖的管理注入......

    spring ioc 容器抽象的的几个主要接口

    Resource            //资源文件的抽象,xml 、 properties ...
    BeanDefinition         //bean的抽象定义 (bean的一些基本信息是否是 抽象、单例、懒加载、作用域...)基本信息
    BeanDefinitionReader      //不同的资源文件的bean的解析 
    BeanFactory           //bean工厂的顶层抽象定义了几个基础的方法 getBean() contanisBean() .... 
    ApplicationContext       //应用程序上下文

    1: Resource 接口

    实现类:ClasspathResource、   解析classpath下的资源文件
        URLResource、      解析url网络资源文件namespace
        FileSystemResource、  解析系统资源文件

    Spring 提供了一些org.springframework.core.io.Resource接口的实现,可以帮助我们快速获取Resource信息。
    1. URLResource
      封装了java.net.URL:通过URL可以获得的对象。 
        Resource resource = new UrlResource("file:/D:/java/src/bean.xml");
      Resource resource = new UrlResource("http://127.0.0.1:8080/index.html");
    Resource resource = new UrlResource(new URI("http://127.0.0.1:8080/index.html"));  
    2.  FileSystemResource
    处理java.io.File 本地资源文件
    Resource resource = new FileSystemResource("file:C:ean.xml");
    3. ClassPathResource
      获取classpath下面的Resource
    Resource resource = new ClassPathResource("com/resource/bean.xml");
    Resource接口的一些常用方法:

       2:BeanDefinition 接口 (描述一个bean对象的基本数据结构

    几个重要的实现
      BeanDefinitionParserDelegate //解析配置文件
          org.springframework.beans.factory.xml.
    BeanDefinitionParserDelegate;
                            parseBeanDefinitionElement()...多个重载方法实现bean的定义
      public class ChildBeanDefinition extends AbstractBeanDefinition
    public class RootBeanDefinition extends AbstractBeanDefinition 、
    public class GenericBeanDefinition extends AbstractBeanDefinition 、
    RootBeanDefinition、ChildBeanDefinition、GenericBeanDefinition均继承了AbstractBeanDefiniton,
        
    BeanDefinition对象是配置文件中<bean>元素标签在容器中内部表示形式。
        <bean>元素标签拥有class、scope、lazy-init等配置属性。
        BeanDefinition则提供了相应的beanClass、scope、lazyInit属性。
        BeanDefinition和<bean>中的属性是一一对应的。  
        其中RootBeanDefinition是最常用的实现类、它对应一般性的<bean>元素标签,
        GenericBeanDefinition是自2.5以后新加入的bean文件配置属性定义类,是一站式服务类。
        
    在配置文件中可以定义父<bean>和子<bean>,父<bean>用RootBeanDefinition表示,而子<bean>用ChildBeanDefiniton表示,而
        没有父<bean>的<bean>就使用RootBeanDefinition表示。AbstractBeanDefinition对两者共同的类信息进行抽象。

        Spring通过BeanDefinition将配置文件中的<bean>配置信息转换为容器的内部表示,并将这些BeanDefiniton注册到BeanDefinitonRegistry中。
        Spring容器的BeanDefinitionRegistry就像是Spring配置信息的内存数据库,主要是以map的形式保存,后续操作直接从BeanDefinitionRegistry中读取配置信息。
        一般情况下,BeanDefinition只在容器启动时加载并解析,除非容器刷新或重启,这些信息不会发生变化。
        如果用户有特殊的需求,也可以通过编程的方式在运行期调整BeanDefinition的定义。

    创建最终的BeanDefinition主要包括两个步骤:
      1)利用BeanDefinitionReader对配置信息Resource进行读取,通过XML解析器解析配置信息的DOM对象,简单地为每个<bean>生成对应的BeanDefinition对象。
        但是这里生成的BeanDefinition可能是半成品,因为在配置文件中,我们可能通过占位符变量引用外部属性文件的属性,这些占位符变量在这一步还没有被解析出来。

      2)利用容器中注册的BeanFactoryPostProcessor对半成品的BeanDefinition进行加工处理,
        将以占位符表示的配置解析为最终的实际值,这样半成品的BeanDefinition就为成品的BeanDefinition。

       3:BeanDefinitionReader 接口将配置信息转换程BeanDefinition

    BeanDefinitionReader将外部资源对象描述的bean定义统一转化为统一的内部数据结构BeanDefinition

    主要实现类:
      XmlBeanDefinitionReader
    用来读取xml描述配置的bean对象。
    PropertiesBeanDefinitionReader、
    用来解析 ×.properties文件描述配置的bean对象。
    最后都会 registerBeanDefinitions(...) 注册解析到的bean对象到map

     4:BeanFactory  接口 (bean的工厂)

    主要方法
    protected
    Object doGetBean(final String name, final Class requiredType, final Object[] args, boolean typeCheckOnly)throws BeansException { //bean name处理,去除FactoryBean前缀等 final String beanName = transformedBeanName(name); Object bean = null; //先从singleton缓存中查看是否已经实例化过该Bean,根据是否有缓存分为两个分支分别处理 Object sharedInstance = getSingleton(beanName); if (sharedInstance != null && args == null) { // 分支一,若缓存中获取到了并且该BeanDefinition信息表明该bean是singleton的,直接将获取到的缓存Bean //(有可能是半成品)交给getObjectForBeanInstance处理 //调用getObjectForBeanInstance处理 bean = getObjectForBeanInstance(sharedInstance, name, beanName, null); }else { // 分支二:没有缓存,则需要从头实例化该bean // We're assumably within a circular reference. if (isPrototypeCurrentlyInCreation(beanName)) { throw new BeanCurrentlyInCreationException(beanName);} // 检查BeanDefinition是否在当前工厂或父工厂 BeanFactory parentBeanFactory = getParentBeanFactory(); if (parentBeanFactory != null && !containsBeanDefinition(beanName)) { // Not found -> check parent. String nameToLookup = originalBeanName(name); if (args != null) { // 父工厂getBean return parentBeanFactory.getBean(nameToLookup, args); } else { // No args -> delegate to standard getBean method. return parentBeanFactory.getBean(nameToLookup, requiredType); } } //将bean加入“正在创建”的集合,完成后会remove,对应afterSingletonCreation/afterPrototypeCreation方法 if (!typeCheckOnly) { markBeanAsCreated(beanName); } final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName); checkMergedBeanDefinition(mbd, beanName, args); // 解决依赖关系,将依赖的bean提前实例化 String[] dependsOn = mbd.getDependsOn(); if (dependsOn != null) { for (int i = 0; i < dependsOn.length; i++) { String dependsOnBean = dependsOn[i]; getBean(dependsOnBean); registerDependentBean(dependsOnBean, beanName); } } // 这里又需要根据bean的类型分为三种情况:singleton、prototype、request/session if (mbd.isSingleton()) { //通过自定义ObjectFactory实例化Bean,此结果可能是半成品(是FactoryBean等) sharedInstance = getSingleton(beanName, new ObjectFactory() { public Object getObject() throws BeansException { try { //真正实例化装配的逻辑在createBean方法中 return createBean(beanName, mbd, args); } catch (BeansException ex) { //显式地删除实例从单缓存:它可能已经把那里  
                 //热切的创建过程,允许循环引用的决议。  
                 //删除任何bean,得到一个临时bean的引用。
    destroySingleton(beanName); throw ex; } } }); //上一步半成品的Bean交给getObjectForBeanInstance方法处理 bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd); } else if (mbd.isPrototype()) { // It's a prototype -> create a new instance. Object prototypeInstance = null; try { beforePrototypeCreation(beanName); //真正实例化装配的逻辑在createBean方法中 prototypeInstance = createBean(beanName, mbd, args); } finally { afterPrototypeCreation(beanName); } //上一步半成品的Bean交给getObjectForBeanInstance方法处理 bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd); } else { //request、session 的bean String scopeName = mbd.getScope(); final Scope scope = (Scope) this.scopes.get(scopeName); if (scope == null) { throw new IllegalStateException("No Scope registered for scope '" + scopeName + "'"); } try { Object scopedInstance = scope.get(beanName, new ObjectFactory() { public Object getObject() throws BeansException { beforePrototypeCreation(beanName); try { //真正实例化装配的逻辑在createBean方法中 return createBean(beanName, mbd, args); } finally { afterPrototypeCreation(beanName); } } }); //上一步半成品的Bean交给getObjectForBeanInstance方法处理 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); } } } // Check if required type matches the type of the actual bean instance. if (requiredType != null && bean != null && !requiredType.isAssignableFrom(bean.getClass())) { throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass()); } return bean; }

    创建bean的步骤:
      检查Bean缓存,已经有缓存的Bean对象(有可能是半成品)则交给getObjectForBeanInstance方法处理、  
      否则先根据Bean的生命周期类型分别实例化,每种情况大致都分两步,
        第一步都交给createBean方法生产一个半成品的bean对象,
        然后同样是将半成品的bean交给getObjectForBeanInstance方法

    ps:为什么createBean方法创建完的bean是半成品,该半成品交给getObjectForBeanInstance()方法后执行了什么操作?
    5:ApplicationContext 接口

    public interface ApplicationContext extends EnvironmentCapable,

                              ListableBeanFactory,      //beanFactory

                              HierarchicalBeanFactory,     //beanFactory
                              MessageSource,               //处理消息的基本接口 可以实现国际化....

                              ApplicationEventPublisher,   //事件监听

                              ResourcePatternResolver {    //资源处理

    主要实现类

      ClasspathXmlApplicationContext,

      FileSystemXmlApplicationContext,

      WebApplicationContext  Web上下文容器 (ServletContext)

      //初始化过程 ClasspathXmlApplicationContext为例

    1.把配置xml文件转换成resource。resource的转换是先通过ResourcePatternResolver来解析可识别格式的配置文件的路径

    (如"classpath*:"等),如果没有指定格式,默认会按照类路径的资源来处理。
    2.利用XmlBeanDefinitionReader完成对xml的解析,将xml Resource里定义的bean对象转换成统一的BeanDefinition。
    3.将BeanDefinition注册到BeanFactory,完成对BeanFactory的初始化。BeanFactory里将会维护一个BeanDefinition的Map。

    最后在调用 getBean的时候会执行

     public void refresh() throws BeansException, IllegalStateException {  

          ...

          ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory(); //创建BeanFactory  

          //会实例化一个XmlBeanDefinitionReader来解析Resource文件。

          ...

    .... }太长了不翻译了

    参考文档:

      1:http://www.neversaydie.cc/spring-ioc-introduce/

      其它参考文章稍后贴出...

  • 相关阅读:
    [HNOI2014]江南乐
    烦人的数学作业(数位dp)
    http2.0请求springboot接口
    01背包动态规划
    坑点总结
    [机房测试] 堆石子
    [机房测试] 出租车
    [机房测试] 下棋
    [机房测试] number
    [CSP-S2019] 树的重心
  • 原文地址:https://www.cnblogs.com/javafengyi/p/3526187.html
Copyright © 2020-2023  润新知