Spring IoC容器的初始化包括 BeanDefinition的Resource定位、载入和注册 这三个基本的过程。IoC容器的初始化过程不包含Bean依赖注入的实现。Bean依赖的注入一般会发生在第一次通过getBean向容器索取Bean的时候。
先看以下代码:
ApplicationContext context = new ClassPathXmlApplicationContext("ioc.xml");
Car car = (Car) context.getBean("car");
System.out.println(car.getBrand());
以上是我们常用的加载IoC容器,并获得Bean的代码。直接进入ClassPathXmlApplicationContext的构造方法,它实际调用的构造方法为:
public ClassPathXmlApplicationContext(String[] configLocations, boolean refresh, ApplicationContext parent) throws BeansException { super(parent); setConfigLocations(configLocations); if (refresh) { refresh(); //调用容器的refresh,载入BeanDefinitionde的入口。 } }
调用super(parent)方法为容器设置好Bean资源加载器,该方法最终会调用到AbstractApplicationContext的无参构造方法,这里会默认设置解析路径的模式为Ant-style。
setConfigLocations(configLocations)设置Bean定义资源文件的定位路径。AbstractRefreshableConfigApplicationContext中的setConfigLocation(String location)说明了多个资源文件路径之间可以是用” ,
; /t/n”分隔。setConfigLocations(String… locations)说明了它还接受字符串数组。
接下来看下最重要的refresh()方法。
@Override public void refresh() throws BeansException, IllegalStateException { synchronized (this.startupShutdownMonitor) { //调用容器准备刷新的方法,获取容器的当时时间,同时给容器设置同步标识 prepareRefresh(); // 通知子类启动refreshBeanFactory()的调用 ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory(); //为BeanFactory配置容器特性,例如类加载器、事件处理器等 prepareBeanFactory(beanFactory); try { //为子类设置BeanFactory的后置处理器 postProcessBeanFactory(beanFactory); //调用BeanFactoryPostProcessor,这些后置处理器都是在Bean定义中向容器定义的 invokeBeanFactoryPostProcessors(beanFactory); // 注册Bean的后置处理器,在Bean创建过程中调用 registerBeanPostProcessors(beanFactory); // 对上下文的消息源进行初始化 initMessageSource(); // 初始化上下文的事件机制 initApplicationEventMulticaster(); // 初始化其他特殊的Bean onRefresh(); // 检查监听Bean,并且将这些Bean向容器中注册 registerListeners(); // 实例化所有的(non-lazy-init) 单例 finishBeanFactoryInitialization(beanFactory); // 最后一步:发布容器事件,结束refresh过程 finishRefresh(); } catch (BeansException ex) { if (logger.isWarnEnabled()) { logger.warn("Exception encountered during context initialization - " + "cancelling refresh attempt: " + ex); } /销毁已经创建的单态Bean destroyBeans(); // 重置'active'状态 cancelRefresh(ex); // Propagate exception to caller. throw ex; } finally { // Reset common introspection caches in Spring's core, since we // might not ever need metadata for singleton beans anymore... resetCommonCaches(); } } }