IOC 启动时序
含义
IOC 即控制反转,可以理解为,将jvm中的对象,由程序员去控制声明周期,转为由容器去控制对象的声明周期。所以,在谈到 IOC时,都会说IOC容器。
bean 和 对象的区分
在spring的框架内,对象 + 受容器管理 = bean 。 所以,在Spring的框架内谈论的bean,准确地说,是受IOC容器管理地对象(这个对象可以是单例的,也可以是普通的)。
所以,学习 IOC的启动时序,就要搞清楚,IOC容器是怎么去管理bean,再结合启动的流程代码,就可以知道程序设计的目的。
BeanFactory :管理bean的工厂
BeanDefinition : 定义所有bean本身需要有的基本信息,比如元数据,字段属性,注入方式等
BeanPostProcessor : 对生成的 Bean 进行处理
IOC容器 BeanFactory
子类结构
先通过BeanFactory的源码看看,这个总接口定义了哪些功能
public interface BeanFactory {
//对FactoryBean的转义定义,因为如果使用bean的名字检索FactoryBean得到的对象是工厂生成的对象,
//如果需要得到工厂本身,需要转义
String FACTORY_BEAN_PREFIX = "&";
//根据bean的名字,获取在IOC容器中得到bean实例
Object getBean(String name) throws BeansException;
//根据bean的名字和Class类型来得到bean实例,增加了类型安全验证机制。
Object getBean(String name, Class requiredType) throws BeansException;
//提供对bean的检索,看看是否在IOC容器有这个名字的bean
boolean containsBean(String name);
//根据bean名字得到bean实例,并同时判断这个bean是不是单例
boolean isSingleton(String name) throws NoSuchBeanDefinitionException;
//得到bean实例的Class类型
Class getType(String name) throws NoSuchBeanDefinitionException;
//得到bean的别名,如果根据别名检索,那么其原名也会被检索出来
String[] getAliases(String name);
//判断给出的 bean name 是否满足
boolean isTypeMatch(String name, ResolvableType typeToMatch) throws NoSuchBeanDefinitionException;
//判断指定的 的 bean name 和 类型是否匹配,spring使用这个接口,而不是用 instanceof 来进行判断,且判断的对象是 spring中的 bean实例,这个很常用
boolean isTypeMatch(String name, Class<?> typeToMatch) throws NoSuchBeanDefinitionException;
}
- 这个接口定义了如何获取到容器里面的bean,而工厂自身如何实例化,工厂如何获得这些bean,由子类自己去实现.
- SimpleJndiBeanFactory:支持jndi,2.5添加,允许
- AutowireCapableBeanFactory:定义了bean的装配规则接口。
- HierarchicalBeanFactory:支持层次结构,可以配置parentBeanFactory,ConfigurableListableBeanFactory实现了HierarchicalBeanFactory,提供了可配置功能。
- ListableBeanFactory:支持枚举
具体的实现,可以通过查看源码获得其设计意义.但总体来说,可以这么理解,
这三个接口( )共同定义了 Bean 的集合 (list) 、Bean 之间的关系 (parent) 、以及 Bean 行为 (wire).
ApplicationContext
ApplicationContext应用上下文,它作为容器的高级形态而存在,除了BeanFactory的基本功能,还提供了更多丰富的功能,常用的有ClassPathXmlApplicationContext、FileSystemXmlApplicationContext、XmlWebApplicationContext。
bean的解析可以通过 xml 去定义,例如常用的spring 项目中使用 xml 中的 <bean id="">标签定义.也可以通过注解,配包扫描进行bean解析.
web项目的IOC初始化流程
1.)Resource定位;指对BeanDefinition的资源定位过程。通俗地讲,就是找到定义Javabean信息的XML文件,并将其封装成Resource对象。
2.)BeanDefinition的载入;把用户定义好的Javabean表示为IoC容器内部的数据结构,这个容器内部的数据结构就是BeanDefinition。
3.)向IoC容器注册这些BeanDefinition。
AbstractApplicationContext#reFresh() 方法
在Spring项目启动中,会调用到refresh( ) 方法
@Override
public void refresh() throws BeansException, IllegalStateException {
synchronized (this.startupShutdownMonitor) {
// Prepare this context for refreshing.
/**
* 设置启动时间,设计容器激活标志(active=true)
* 初始化 properties 资源
* 验证必须存在的properties(validateRequiredProperties)
* 初始earlyApplicationEnvents.用于收集已经产生的ApplicationEnvents.
*/
prepareRefresh();
// Tell the subclass to refresh the internal bean factory.
/**
* 调用子类的refeshBeanFactory(),SpringBoot中采用默认的实现,
* 设置BeanFactory的SerializationId,设置refreshed标志为true。
* 获取BeanFactory
* XmlWebApplicationContext ,AnnotationConfigApplicationContext 会在这一步加载BeanDefinition
*/
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
// Prepare the bean factory for use in this context.
/**
* 为接下来 context 上下文使用 beanFactory 做一些准备
* 为BeanFactory 做些标准的设置
*
* 为内部的BeanFactory设置类加载器
*
* 设置表达式解析器,属性编辑器。
*
* 注册BeanPostProcessor(ApplicationContextAwareProcessor,ApplicationListenerDetector),
*
* ApplicationContextAwareProcessor:对Spring 中各种Aware接口的支持,在初始化Bean前,调用Bean实现的Aware接口方法。
* ApplicationListenerDetector:用于收集实现了ApplicationListener接口的Bean
* 注册指定的依赖类型和对应的value,
*
* 例如:beanFactory.registerResolvableDependency(ResourceLoader.class, this);那么在类中自动注入ResourceLoader类型的对象,就会拿到当前IOC容器。
* 注入一些其它信息的bean,比如environment、systemProperties等
*/
prepareBeanFactory(beanFactory);
try {
// Allows post-processing of the bean factory in context subclasses.
/**
* 用于子类BeanFactory 完成标准的初始化之后修改BeanFactory。
* 不同容器根据自己的需求重写 postProcessBeanFactory 方法,来添加特殊的后置处理器,
*/
postProcessBeanFactory(beanFactory);
// Invoke factory processors registered as beans in the context.
/**
* 实例化并且执行所有已经注册到BeanFactory中的 BeanFactoryPostProcessor。支持按照Order排序
*/
invokeBeanFactoryPostProcessors(beanFactory);
// Register bean processors that intercept bean creation.
/**
* 注册所有拦截bean创建的bean处理器
* todo 这里没搞懂
*/
registerBeanPostProcessors(beanFactory);
// Initialize message source for this context.
/**
* 初始化一些国际化的属性
*/
initMessageSource();
// Initialize event multicaster for this context.
/**
* 在容器中初始化Application事件广播器。
*/
initApplicationEventMulticaster();
// Initialize other special beans in specific context subclasses.
/**
* 子类可以使用 onRefresh 方法,实例化一些自己需要的特定的beans
*/
onRefresh();
// Check for listener beans and register them.
/**
* 将所有的 ApplicationListener 实现类注册 到 ApplicationEventMulticaster中,觉得是观察者模式。
* 把已经产生的事件广播出去。
*/
registerListeners();
// Instantiate all remaining (non-lazy-init) singletons./**
/**
* 实列化所有 非懒加载的 类。
*/
finishBeanFactoryInitialization(beanFactory);
// Last step: publish corresponding event.
/**
* 完成容器的初始化过程,发布相应事件。
* 启动容器的声明周期处理器。管理容器声明周期。
* 发布 ContextRefreshedEvent事件。
* 启动内嵌的Servlet容器。
* 发布容器启动事件。
*/
finishRefresh();
}
catch (BeansException ex) {
if (logger.isWarnEnabled()) {
logger.warn("Exception encountered during context initialization - " +
"cancelling refresh attempt: " + ex);
}
// Destroy already created singletons to avoid dangling resources.
destroyBeans();
// Reset 'active' flag.
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();
}
}
}
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
这行代码表示获得一个BeanFactory,进入方法里面,可以看到有一个reFreshBeanFactory,然后return getBeanFactory方法
protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
refreshBeanFactory();
return getBeanFactory();
}
//refreshBeanFactory这个方法是一个抽象方法,委托给了子类去实现
protected abstract void refreshBeanFactory() throws BeansException, IllegalStateException;
查看其子类实现 AbstractRefreshableApplicationContext#refreshBeanFactory()
@Override
protected final void refreshBeanFactory() throws BeansException {
if (hasBeanFactory()) {
//销毁beans
destroyBeans();
//关闭bean工厂
closeBeanFactory();
}
try {
// new 一个 DefaultListableBeanFactory,这个beanFactory 会设置parentFactory
DefaultListableBeanFactory beanFactory = createBeanFactory();
//设置 factory id
beanFactory.setSerializationId(getId());
/**
* 定制化beanFactory
* 设置两个属性:
* 1. 是否允许覆盖同名称的不同定义的对象
* 2. 是否允许bean之间存在循环依赖
*/
customizeBeanFactory(beanFactory);
//初始化DocumentReader,并进行XML文件读取和解析
loadBeanDefinitions(beanFactory);
//设置 锁点
synchronized (this.beanFactoryMonitor) {
this.beanFactory = beanFactory;
}
}
catch (IOException ex) {
throw new ApplicationContextException("I/O error parsing bean definition source for " + getDisplayName(), ex);
}
}
查看 AbstractRefreshableApplicationContext#createBeanFactory( ),返回了一个DefaultListableBeanFactory
protected DefaultListableBeanFactory createBeanFactory() {
return new DefaultListableBeanFactory(getInternalParentBeanFactory());
}
AbstractRefreshableApplicationContext#customizeBeanFactory 方法
protected void customizeBeanFactory(DefaultListableBeanFactory beanFactory) { if (this.allowBeanDefinitionOverriding != null) { beanFactory.setAllowBeanDefinitionOverriding(this.allowBeanDefinitionOverriding); } if (this.allowCircularReferences != null) { beanFactory.setAllowCircularReferences(this.allowCircularReferences); }}
AbstractRefreshableApplicationContext#loadBeanDefinitions( )
初始化DocumentReader,并进行XML文件读取和解析,由子类实现
protected abstract void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) throws BeansException, IOException;
至此,bean工厂的实例化已经完成,但整个初始化在AbstractApplicationContext#refreshBeanFactory()完成后,就会返回一个初始化好的bean工厂,接下来的代码在AbstractApplicationContext#refresh 代码中,会对bean工厂进行上下文,bean后置处理器,用户自定义bean后置处理器,默认bean注册等一系列操作。
比如:
protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory) {
// Tell the internal bean factory to use the context's class loader etc.
/**
* 为bean工厂加入当前上下文的类加载器
* 设置表达式解析器
* 设置资源文件解析器
*/
beanFactory.setBeanClassLoader(getClassLoader());
beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver(beanFactory.getBeanClassLoader()));
beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this, getEnvironment()));
// Configure the bean factory with context callbacks.
/**
* 为bean工厂添加后置处理器 ApplicationContextAwareProcessor:对Spring 中各种Aware接口的支持,
* 在初始化Bean前,调用Bean实现的Aware接口方法
* 为bean工厂设置 某些 class 不需要加入到 bean 中(因为这些bean可能已经被提前加入)
*/
beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));
beanFactory.ignoreDependencyInterface(EnvironmentAware.class);
beanFactory.ignoreDependencyInterface(EmbeddedValueResolverAware.class);
beanFactory.ignoreDependencyInterface(ResourceLoaderAware.class);
beanFactory.ignoreDependencyInterface(ApplicationEventPublisherAware.class);
beanFactory.ignoreDependencyInterface(MessageSourceAware.class);
beanFactory.ignoreDependencyInterface(ApplicationContextAware.class);
// BeanFactory interface not registered as resolvable type in a plain factory.
// MessageSource registered (and found for autowiring) as a bean.
/**
* 为 bean工厂注册一些特别的用于依赖的bean,比如,在类中需要自动注入ResourceLoader类型的对象,就会拿到当前IOC容器,
*/
beanFactory.registerResolvableDependency(BeanFactory.class, beanFactory);
beanFactory.registerResolvableDependency(ResourceLoader.class, this);
beanFactory.registerResolvableDependency(ApplicationEventPublisher.class, this);
beanFactory.registerResolvableDependency(ApplicationContext.class, this);
// Register early post-processor for detecting inner beans as ApplicationListeners.
/**
* 为bean工厂添加后置处理器 ApplicationListenerDetector:
* 用于收集实现了ApplicationListener接口的Bean
*/
beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(this));
// Detect a LoadTimeWeaver and prepare for weaving, if found.
if (beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {
beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));
// Set a temporary ClassLoader for type matching.
beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));
}
// Register default environment beans.
if (!beanFactory.containsLocalBean(ENVIRONMENT_BEAN_NAME)) {
beanFactory.registerSingleton(ENVIRONMENT_BEAN_NAME, getEnvironment());
}
if (!beanFactory.containsLocalBean(SYSTEM_PROPERTIES_BEAN_NAME)) {
beanFactory.registerSingleton(SYSTEM_PROPERTIES_BEAN_NAME, getEnvironment().getSystemProperties());
}
if (!beanFactory.containsLocalBean(SYSTEM_ENVIRONMENT_BEAN_NAME)) {
beanFactory.registerSingleton(SYSTEM_ENVIRONMENT_BEAN_NAME, getEnvironment().getSystemEnvironment());
}
}
但总体来说,都是对bean工厂进一步增强和丰富。直到 AbstractApplicationContext#refresh完成,那么,bean工厂就初始化完成了,IOC容器的初始化也完成了。