欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

spring 源码分析--IOC容器初始化一

程序员文章站 2022-03-02 16:27:19
...

说明:文章按照函数调用的方式一层一层推进,函数结束点击“返回”可以返回至函数调用的地方,另外在函数前有数字1.1。。表示函数的层次关系,由于函数之间的调用关系很复杂,需要忒别注意层次。下面就开始:

IOC容器初始化

 

一、  

1、  应用程序使用 spring 加载 bean 使用语句:

FileSystemXmlApplicationContext

con = new FileSystemXmlApplicationContext (String configLocation);      

FileSystemXmlApplicationContext 包括一系列重载的构造方法。最后都会调用下面的方法:

===================================================================

/**

* 这里是 IoC 容器的初始化过程,其初始化过程的大致步骤由类

* AbstractApplicationContext 来定义

*/

public FileSystemXmlApplicationContext(String[] configLocations, boolean refresh, ApplicationContext parent)

           throws BeansException {

/**

* 调用父类构造函数,最终到类 AbstractApplicationContext 中执行下面代码:

* this.parent = parent;

*/

    super (parent);

    setConfigLocations(configLocations);

    if (refresh) {

/**

* 这里是 IoC 容器的初始化过程,其初始化过程的大致步骤由类

* AbstractApplicationContext 来定义

*/

       refresh();

    }

}

函数执行 ok, 整个容器的初始化就结束了。

 

 

过程描述:

1.1 setConfigLocations(configLocations); 方法定义在类:

AbstractRefreshableConfigApplicationContext 由类图可知,

FileSystemXmlApplicationContext 间接继承至:

AbstractRefreshableConfigApplicationContext setConfigLocations 方法如下:

===================================================================

public void setConfigLocations(String[] locations) {

if (locations != null ) {

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

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

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

/**

* 该方法调用 SystemPropertyUtils.resolvePlaceholders(path) ;对 path 中的占位 符进行

*   替换, eg path 路径中含有 ${user.dir} ,则将替换为: System.getProperty(user.dir);

*/

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

        }

} else {

        this . configLocations = null ;

   }

}

  ===================================================================

1)        代码中 configLocations AbstractRefreshableConfigApplicationContext 类中 string[] 类型的字段。至此应用程序传入路径保存在 AbstractRefreshableConfigApplicationContext

返回

 

 

1.2 refresh(); 方法定义在类: AbstractApplicationContext ,由类图可知:

FileSystemXmlApplicationContext 间接继承至: AbstractApplicationContext

refresh() 方法如下:

===================================================================

public void refresh() throws BeansException, IllegalStateException {

synchronized ( this . startupShutdownMonitor ) {

/** refresh 做准备 ;*/

    prepareRefresh();

/**

* 这里需要子类来协助完成资源位置定义 ,bean 载入和向 IOC 容器注册的过程

*/

Conf igurableListableBeanFactory beanFactory = obtainFreshBeanFactory() ;

// 为当前上下文准备 bean 工厂;

    prep areBeanFactory(beanFactory);

try {

       // 允许在子类中对 bean 工厂做准备后的处理;

postProcessBeanFactory(beanFactory);

// 调用 bean 工厂处理上下文 bean 的注册 ;

       invokeBeanFactoryPostProcessors(beanFactory);

       // 注册 bean 创建拦截器的处理。

       registerBeanPostProcessors(beanFactory);

// 初始化上下文的资源;

       initMessageSource();

// 初始化上下文事件的 multicaster ( 多点播送;多路广播;多点传送 ).

initApplicationEventMulticaster();

// Initialize other special beans in specific context subclasses.

       onRefresh();

// Check for listener beans and register them.

       registerListeners();

// Instantiate all remaining( 其余 ) (non-lazy-init ) singletons.

       finishBeanFactoryInitialization(beanFactory);

// Last step: publish corresponding event. 发布相应的事件

       finishRefresh();

    } catch (BeansException ex) {

       // Destroy already created singletons to avoid dangling resources.

       beanFactory.destroySingletons();

       // Reset 'active' flag.

       cancelRefresh(ex);

// Propagate exception to caller.

       throw ex;

       }

    }

}

 

 

 

  过程描述:

1.2.1     prepareRefresh(): 为刷新准备上下文环境。主要设置开始时间和设置 active 标志。

 

方法如下:

===================================================================

protected void prepareRefresh() {

this . startupDate = System.currentTimeMillis ();

        synchronized ( this . activeMonitor ) {

        this . active = true ;     

}

if ( logger .isInfoEnabled()) {

        logger .info ( "Refreshing " + this );

}

}

====================================================================

返回

 

 

 

1.2.2      obtainFreshBeanFactory() :让子类刷新内部 bean 工厂。方法如下:

===================================================================

/**

* 关闭前面所有 bean 工厂,为新的上下文环境初始化一个新的 bean 工厂。这里需要子类来

* 协助完成资源位置定义 ,bean 载入和向 IOC 容器注册的过程

*/

protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {

refreshBeanFactory();

Config urableListableBeanFactory beanFactory = getBeanFactory();

if ( logger .isInfoEnabled()) {

logger .info( "Bean factory for application context [" + getId() + "]: " +ObjectUtils.identityToString (beanFactory));

}

if ( logger .isDebugEnabled()) {

logger .debug(beanFactory.getBeanDefinitionCount() + " beans defined in " + this );

}

return beanFactory;

}

====================================================================

返回

 

 

  1.2.2.1  refreshBeanFactory() 该方法为抽象方法。要求子类必须实现这个方法来执行实际的配置装。在 AbstractApplicationContext 的直接子类:

AbstractRefreshableApplicationContext 中有实现。方法声明为 final ,不允许子类重写方法,方法如下:

====================================================================

protected final void refreshBeanFactory() throws BeansException {

/**

* 判断上下文是否还拥有 bean 工厂。 return (this.beanFactory != null);

*/

if (hasBeanFactory()) {

/**

* 清除当前上下文的所有 bean ,默认的实现为:清除当前上下文的所有缓存的单例 bean ,默认

* 的实现在父类: AbstractApplicationContext

*/

destroyBeans();

// 关闭 bean 工厂,代码: this.beanFactory = null;

closeBeanFactory();

}

try {

// 创建一个 bean 工厂

    DefaultListableBeanFactory beanFactory = createBeanFactory() ;

/**  制定 bean 工厂,即设置 bean 工厂的属性值,即:

*beanFactory.setAllowBeanDefinitionOverriding(this.allowBeanDefinit

*onOverriding.booleanValue());

*beanFactory.setAllowCircularReferences(this.allowCircularReference

*s.booleanValue());

*/

customizeBeanFactory(beanFactory);

/**

* 给给定的 bean 工厂装载的 bean 定义,通常是通过委托给一个或多个 * BeanDefinitionReader ,在 AbstractRefreshableApplicationContext 类定义为抽 * 象函数,在

*AbstractXmlApplicationContext 中定义了具体的实现。

*/

    loadBeanDefinitions(beanFactory);

    synchronized ( this . beanFactoryMonitor ) {

       this . beanFactory = beanFactory;

        }

    } catch (IOException ex) {

       throw new ApplicationContextException(

"I/O error parsing XML document for application context [" + getDisplayName() + "]" , ex);

}

====================================================================

返回

 

 

 

本站支持 pay for your wishes

相关标签: IOC Spring Bean

上一篇: spring 源码分析--IOC容器初始化二

下一篇: