spring技术内幕2-IOC定位Bean定义资源

1、IoC容器初始化:

Spring的IoC容器初始化包括:Bean定义资源文件的定位、载入、注册三个过程。

(1)Bean定义资源文件的定位

Bean定义资源文件定位由ResourceLoader通过统一的Resource接口来完成,Resource接口将各种形式的Bean定义资源文件封装成统一的、IoC容器可以进行载入操作的对象。

(2)Bean定义资源文件的载入

Bean定义资源文件载入的过程是将Bean定义资源文件中配置的Bean转换成IoC容器中所管理Bean的数据结构形式。Spring IoC中管理的Bean的数据结构是BeanDefinition,BeanDefinition是POJO对象在IoC容器中的抽象。

(3)Bean定义资源文件的注册

通过调用BeanDefinitionRegistry接口把从Bean定义资源文件中解析的Bean向IoC容器进行注册,在IoC容器内部,是通过一个HashMap来存储这些Bean对象数据的。

需要注意的是:IoC容器和上下文初始化一般不包含Bean依赖注入的实现。一般而言,依赖注入发生在第一次通过getBean方法向容器获取Bean时。但是,如果IoC容器预实例化配置的lazyinit属性,即某个Bean设置了lazyinit属性,则该Bean的依赖注入在IoC容器初始化时就预先完成了。

2、Bean定义资源文件的定位过程

ApplicationContext是一个在BeanFactory基础上进行了扩展的接口,具体的Ioc容器实现常用的有:FileSystemXmlApplicationContext(从文件系统中读入Bean定义资源文件)、ClassPathXmlApplicationContext(从Classpath类路径中读入Bean定义资源文件)和XmlWebApplicationContext(从Web容器如Tomcat等中读入Bean定义资源文件)。

3、FileSystemXmlApplicationContext的初始化过程

FileSystemXmlApplicationContext的源码如下:

public class FileSystemXmlApplicationContext extends AbstractXmlApplicationContext  {

   public FileSystemXmlApplicationContext(){

    }

   public FileSystemXmlApplicationContext(ApplicationContext parent){

         super(parent);

    }

   //configLocation是Bean定义资源文件路径

   public FileSystemXmlApplicationContext(Stirng configLocation) throws BeansException {

    this(new String[] {configLocation},true,null);

    }

    //可以传入多个Bean定义资源文件路径

    public FileSystemXmlApplicationContext(String ... configLocations) throws BeansException {

    this(configLocations,true,null);

    }

    public FileSystemXmlApplicationContext(String[] configLocations,ApplicationContext parent) throws BeansException {

    this(configLocations,true,parent);

    }

    public FileSystemXmlApplicationContext(Stirng[] configLocations,boolean,refresh) throws BeansException {

    this(configLocations,refresh,null);

    }

    //FileSystemXmlApplicationContext IoC容器进行初始化的入口构造函数

    public FileSystemXmlApplicationContext(Stirng[] configLocations,boolean refresh,ApplicationContext parent) throws BeansException {

    super(parent);

    //调用父类AbstractRefreshableConfigApplicationContext的方法,设置Bean定义资源文件,完成IoC容器Bean定义资源文件的定位

    setConfigLocations(configLocations);

    if(refresh){

    //调用父类AbstractApplicationContext的refresh()函数启动载入Bean定义的过程,是IoC容器载入Bean定义的入口

    refresh();

    }

}

//该方法覆盖父类DefaultResourceLoader的方法,通过Bean定义资源文件路径封装得到IoC容器要读入的定位Bean定义的资源

 @Override

  protected Resource getResourceByPath(String path){

   if(path != null && path.startsWith("/")){

   path = path.substring(1);

   }

   //其他类型的IoC容器会用到其他类型的Resource来定位Bean定义,如ClassPathResource等

   return new FileSystemResource(path);

   }

}

通过分析FileSystemXmlApplicationContext的源码可以知道,在创建FileSystemApplicationContext容器时,构造方法做以下两项重要工作:首先,调用父类容器的构造方法(super(parent)方法)为容器设置好Bean资源加载器。然后,调用父类AbstractRefreshableConfigApplicationContext的setConfigLocations(configLocations)方法设置Bean定义资源文件的定位路径。

通过追踪FileSystemXmlApplicationContext的继承体系,发现其父类的父类AbstractAppliation中初始化IoC容器所做的工作的主要源码如下:

public abstract class AbstractApplicationContext extends DefaultResourceLoader implements ConfigurableApplicationContext,DisposableBean {

  //静态初始化快,在整个容器创建过程中只执行一次

  static {

    //为了避免应用程序在weblogic8.1关闭时出现类加载异常加载问题,加载IoC容器关闭事件(ContextClosedEvent)类

     ContextClosedEvent.class.getName();

    }

    //FileSystemXmlApplicationContext调用父类构造方法调用的就是该方法

    public AbstractApplicationContext(ApplicationContext parent) {

     this.parent = parent;

     this.resourcePatternResolver = getResourcePatternResolver();

}

     //获取一个Spring Source的加载器用于读入Spring Bean定义资源文件

     protected ResourcePatternResolver getResourcePatternResolver(){

      //AbstractApplicationContext继承DefaultResourceLoader,也是一个Spring资源加载器,其getResource(String location)方法用于载入资源

      return new PathMatchingResourcePatternResolver(this);

      }

}

AbstractApplicationContext构造方法中调用PathMatchingResourcePatternResolver的构造方法创建Spring资源加载器,PathMatchingReourcePatternResolver的构造方法如下:

public PathMatchingResourcePatternResolver(ResourceLoader resourceLoader){

   Assert.notNull(resourceLoader,"ResourceLoader must not be null");

   //设置Spring的资源加载器

   this.resourceLoader = resourceLoader;

}

在设置容器的资源加载器之后,接下来FileSystemXmlApplicationContext执行setConfigLocations方法调用父类的相关方法定位Bean定义资源文件。

在对FileSystemXmlApplicationContext的源码分析中我们看到,在其入口构造函数中,通过调用其父类AbstractRefreshableConfigApplicationContext的方法进行对Bean定义资源文件进行定位,该方法的源码如下:

//处理单个资源文件路径为一个字符串的情况

public void setConfigLocation(String location){

  //多个资源文件路径之间用,;/t /n分隔,解析成数组形式

  String CONFIG_LOCATION_DELIMITERS = ",;/t/n";

   setConfigLocations(StringUtils.tokenizeToStringArray(location,CONFIG_LOCATION_DELIMITERS);

}

   //解析Bean定义资源文件的路径,处理多个资源文件字符串数组

   public void setConfigLocations(String[] locations){

   if(locations != null){

     Assert.notNullElements(locations,"Config Loations must not be null");

     this.configLocatioins = new String[locations.length];

     for(int i=0;i<locations.length;i++){

     //resolvePath为同一个类中将字符串解析为路径的方法

     this.configLocations[i] = resolvePath(locations[i].trim();

     }

  }else {

     this.configLocations = null;

  }

通过这两个方法的源码我们可以看出,我们既可以使用一个字符串来配置多个Spring Bean定义资源文件,也可以使用字符串数组,即下面的两种方式:

a、ClassPathResource res = new ClassPathResource("a.xml,b.xml,...");

多个资源文件路径可以用,;/t/n等分隔。

b、ClassPathResource res = new ClassPathResource(new String[]{"a.xml","b.xml",...});

至此,Spring IoC容器在初始化时将配置的Bean定义资源文件定位为Spring封装的Resource。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值