Spring可以轻松创建Java企业应用程序,它提供了在企业环境中使用Java语言所需的一切 。要使用Spring 必须要先构建 IOC容器,没有它Spring无法正常工作。本文将详细讲解Spring IOC 初始化机制及学习总结。
如下图所示:
定义了一个Person对象,和一个实现BeanPostProcessor接口的自定义类,本文将以此代码为基础来深入学习Spring IOC初始化流程:
//XML Bean 配置
/**
*
* test spring IOC
*
* @author [email protected]
*/
public class DemoApplication {
/**
* definite a bean with Person
*/
@Data
public static class Person {
private String email;
public Person() {
System.out.println("new Person()");
}
public void init() {
System.out.println("init() ...........");
}
}
/**
* definite a custome BeanPostprocessor with HelloBeanPostProcessor
*/
public static class HelloBeanPostProcessor implements BeanPostProcessor {
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
System.out.println("-----------------------postProcessBeforeInitialization...");
return null;
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
System.out.println("-----------------------postProcessAfterInitialization...");
return null;
}
}
/**
* test ioc init
* @param args
*/
public static void main(String[] args) {
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("classpath:applicationContext.xml");
}
}
//打印台输出结果
new Person()
-----------------------postProcessBeforeInitialization...
init() ...........
-----------------------postProcessAfterInitialization...
XML 方式配置元数据:
以 ApplicationContext 子类ClassPathXmlApplicationContext为切入点解析XML元数据
注解方式配置元数据:
以 ApplicationContext 子类 AnnotationConfigApplicationContext 为切入点解析注解元数据
不管是使用XMl 方式还是使用注解的方式配置元数据,其底层核心实现都是一样的。本章以XML配置文件形式来了解Spring Ioc容器。
首先通过 new ClassPathXmlApplicationContext 这句代码可以找到 IOC 容器初始化入口方法:
//IOC 初始化入口
@Override
public void refresh() throws BeansException,IllegalStateException {
synchronized(this.startupShutdownMonitor) {
// 开启初始化标志,为刷新做准备
prepareRefresh();
// 解析XML配置将Bean转换为Beandefinition,并刷新BeanFactory子容器
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
// 创建BeanFactory
prepareBeanFactory(beanFactory);
try {
// 注册实现了 BeanPostProcessor接口的bean
postProcessBeanFactory(beanFactory);
// 初始化和执行 BeanFactoryPostProcessor beans
invokeBeanFactoryPostProcessors(beanFactory);
// 初始化和执行 BeanPostProcessor beans
registerBeanPostProcessors(beanFactory);
// Initialize message source for this context.
initMessageSource();
// Initialize event multicaster for this context.
initApplicationEventMulticaster();
// 刷新由子类实现的方法
onRefresh();
// Check for listener beans and register them.
registerListeners();
// 初始化 non-lazy-init单例bean,并完成 beanFactory初始化
finishBeanFactoryInitialization(beanFactory);
// Last step: publish corresponding event.
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();
}
}
}
上图展示了Spring IOC 初始化过程中要执行的所有流程,总的来说ApplicationContext必须要完成一下几件事:
构建BeanFactory过程主要体现在refresh()方法前三行代码:
prepareRefresh();
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
prepareBeanFactory(beanFactory);
prepareRefresh()主要设置容器开始标识、准备需要的配置信息
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory() 这行代码比较关键,因为它做了足够多的事情:
prepareBeanFactory() : 配置 BeanFacotey上下文配置信息
经过上面三个方法的执行后,此时IOC容器可以获取到用户配置的Bean、生成BeanFactory雏形。
“ 注册感兴趣的事件” 这个过程中,比较重要的是以下几个方法:
postProcessBeanFactory(beanFactory);
invokeBeanFactoryPostProcessors(beanFactory);
registerBeanPostProcessors(beanFactory);
为什么这几个方法比较重要呢?
因为这几个方法完成了 Bean 生命周期 (init、destroy) 、BeanPostProccessor、Aware接口注入 这一系列过程
spring为开发人员提供了足够的扩展点
比如:
Bean 生命周期 (init、destroy)
BeanPostProccessor
Aware接口注入
经过对上面三个方法Debug,找到了核心调用方法 :
AbstractAutowireCapableBeanFactory中的 initializeBean 方法:该方法会对目标Bean进行包装
protected Object initializeBean(final String beanName, final Object bean, @Nullable RootBeanDefinition mbd) {
if (System.getSecurityManager() != null) {
AccessController.doPrivileged((PrivilegedAction < Object > )() - >{
invokeAwareMethods(beanName, bean);
return null;
},
getAccessControlContext());
} else {
//执行实现Aware接口注入逻辑
invokeAwareMethods(beanName, bean);
}
Object wrappedBean = bean;
if (mbd == null || !mbd.isSynthetic()) {
//执行 自定义 BeanPostProcessor 的 postProcessBeforeInitialization 方法
wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
}
try {
//执行 Bean 的init方法
invokeInitMethods(beanName, wrappedBean, mbd);
} catch(Throwable ex) {
throw new BeanCreationException((mbd != null ? mbd.getResourceDescription() : null), beanName, "Invocation of init method failed", ex);
}
if (mbd == null || !mbd.isSynthetic()) {
//执行 自定义 BeanPostProcessor 的 postProcessAfterInitialization方法
wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
}
return wrappedBean;
}
//这也解释了打印台为什么会打印出下面的语句
new Person()
-----------------------postProcessBeforeInitialization...
init() ...........
-----------------------postProcessAfterInitialization...
“创建 Bean实例对象” 这个过程主要集中在 finishBeanFactoryInitialization(beanFactory) 方法中。
finishBeanFactoryInitialization 中的 beanFactory.preInstantiateSingletons(); 会真正的进行 Bean 实例化:
@Override public void preInstantiateSingletons() throws BeansException {
if (logger.isDebugEnabled()) {
logger.debug("Pre-instantiating singletons in " + this);
}
// Iterate over a copy to allow for init methods which in turn register new bean definitions.
// While this may not be part of the regular factory bootstrap, it does otherwise work fine.
List < String > beanNames = new ArrayList < >(this.beanDefinitionNames);
// Trigger initialization of all non-lazy singleton beans...
for (String beanName: beanNames) {
RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
if (isFactoryBean(beanName)) {
Object bean = getBean(FACTORY_BEAN_PREFIX + beanName);
if (bean instanceof FactoryBean) {
final FactoryBean < ?>factory = (FactoryBean < ?>) bean;
boolean isEagerInit;
if (System.getSecurityManager() != null && factory instanceof SmartFactoryBean) {
isEagerInit = AccessController.doPrivileged((PrivilegedAction < Boolean > )((SmartFactoryBean < ?>) factory) : :isEagerInit, getAccessControlContext());
} else {
isEagerInit = (factory instanceof SmartFactoryBean && ((SmartFactoryBean < ?>) factory).isEagerInit());
}
if (isEagerInit) {
getBean(beanName);
}
}
} else {
getBean(beanName);
}
}
}
// Trigger post-initialization callback for all applicable beans...
for (String beanName: beanNames) {
Object singletonInstance = getSingleton(beanName);
if (singletonInstance instanceof SmartInitializingSingleton) {
final SmartInitializingSingleton smartSingleton = (SmartInitializingSingleton) singletonInstance;
if (System.getSecurityManager() != null) {
AccessController.doPrivileged((PrivilegedAction < Object > )() - >{
smartSingleton.afterSingletonsInstantiated();
return null;
},
getAccessControlContext());
} else {
smartSingleton.afterSingletonsInstantiated();
}
}
}
}
这一步方法结束之后,基本上就完成了 IOC 的初始化。
上述内容如有不妥之处,还请读者指出,共同探讨,共同进步!
@author : [email protected]