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

来源:互联网 发布:淘宝几块钱的东西包邮 编辑:程序博客网 时间:2024/06/05 18:54

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);
下篇讲。
















0 0
原创粉丝点击