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/

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

原文地址:https://www.cnblogs.com/javafengyi/p/3526187.html