Ioc容器初始化-bean资源定位(1)构造函数super(parent)

1.IoC容器初始化:

SpringIoC容器初始化包括:Bean定义资源文件的定位、载入和注册3个基本过程。

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

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

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

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

(3).Bean定义的注册:

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

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


Spring4.1源代码包

以这个例子开始:

public class UserServiceTest {
     private ApplicationContext ctx;
     @Test
     public void testAdd() throws Exception {
            ctx = new ClassPathXmlApplicationContext("beans.xml" );
           UserService userService = (UserService)ctx.getBean("userService" );
            userService.add( new User());
     }
}

背景说明:
ApplicationContext是一个BeanFactory基础上提供了扩展的接口(BeaFactory是Spring中最基本最基础的Ioc容器)。具体对IOC容器的实现常用的有3个:
FileSystemXmlApplicationContext 从文件系统中读取定义bean的资源文件。
ClassPathXmlApplicationContext 从ClassPath的路径中读取定义bean的资源文件。
XmlWebApplicationContext 从web容器中读取定义bean的资源文件。
bean资源文件就是beans.xml文件。

bean资源文件定位的过程:
在  ctx  =  new  ClassPathXmlApplicationContext( "beans.xml"  );打断点。
1.发现直接先进入了下面的静态模块:
static{          
// Eagerly load the ContextClosedEvent class to avoid weird classloader issues     
// on application shutdown in WebLogic 8.1. (Reported by Dustin Woods.)
ContextClosedEvent.class.getName();
}

这个静态模块出现在AbstractApplicationContext中,在整个容器的创建的过程中只执行一次。
这个作用是,翻译上面的话:为了避免应用程序在weblogic8.1关闭的时候出现加载类加载异常的问题,所以较早的加载这个ContextClosedEvent事件。
现在我还不知道是做什么用的。

2.加载完成后发现进入下面的构造函数:
public ClassPathXmlApplicationContext(String configLocation ) throws BeansException {
     this(new String[] {configLocation}, true, null);
}
这个构造方法通过this()方法又调用了同类下的正真的入口方法:
public ClassPathXmlApplicationContext(String[] configLocations , boolean refresh , ApplicationContext parent )throws BeansException {
     super(parent );
     setConfigLocations(configLocations);
     if ( refresh) {
          refresh();
     }
}

这个才是真正的入口方法:
这个方法两步:
1.定位资源文件。
2.启动加载以及注册。

本篇讲定位也就是: super()和setConfigLocation(cinfigLocations)所做的事情。

1-先看super(parent) 这个parent是null在这里。
调用了父类的构造方法,发现它调用了父类AbstractRefreshableConfigApplicationContext的构造方法:
public AbstractXmlApplicationContext(ApplicationContext parent) {    
     super(parent );
}
再进入发现它又调用了 AbstractRefreshableConfigApplicationContext 的父类的构造方法,
。。。
以此类推,它分别依次调用了
AbstractXmlApplicationContext
AbstractRefreshableConfigApplicationContext
AbstractRefreshableApplicationContext
的父类方法直到
AbstractApplicationContext 为止.
我们得到这样一张在后面很有用的结构图:

除了ClassPathXmlApplicationContext 其他的父类都是抽象类。就是说通过这几个抽象类分了这几个层次,而最后实现类就只有:ClassPathXmlApplicationContext。

继续看,在AbstractApplicationContext中的构造方法是这样的:
public AbstractApplicationContext(ApplicationContext parent ) {
            this ();
           setParent( parent);
     }
也是两步:
调用自身的构造方法 this();
public AbstractApplicationContext() {      
this. resourcePatternResolver = getResourcePatternResolver();
     }

这个构造方法,通过getResourcePatternResolver来获得了一个 resourcePatternResolver, 这是一个Spring Source的加载器。
getResourcePatternResolver的方法实现是这样的:
protected ResourcePatternResolver getResourcePatternResolver() {           
     return new PathMatchingResourcePatternResolver(this);
}
直接new了一个 PathMatchingResourcePatternResolver对象,这个对象创建了spring的资源加载器。
其实上图中AbstractApplication上面继承了DefaultResourceLoader而DefaultResourceLoader实现了ResourceLoader接口,所以当前对象本身就是一个Spring资源加载器,它的getResources方法就是用于加载资源的。

PathMatchingResourcePatternResolver对象,它里面的实现是这样的:
public PathMatchingResourcePatternResolver(ResourceLoader resourceLoader) {
       Assert.notNull(resourceLoader, "ResourceLoader must not be null");
       this. resourceLoader = resourceLoader;
     }

就是把AbstractApplicationContext对象设置成一个资源加载器。赋值给
PathMatchingResourcePatternResolver 的resourceLoader属性。

到这里完成了this(),这个构造函数所做的工作,把自身AbstractApplicationContext的对象传给 PathMatchingResourcePatternResolver的resourceLoader属性,设置了容器的资源加载器。

b 然后 setParent(parent);
其实我们发现,我们一路super(parent)父类构造方法,到这里,ClassPathXmlApplicationContext 调用父类真正的构造方法就是这个setParent(parent);
而这个例子中,我们传入到parent是null,暂时先不考虑。

到这里最初方法里的super(parent)就完成了。

2-下面看 setConfigLocations( configLocations );
下篇讲。
















评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值