准备
Person实例
@Data
public class Person {
private String name;
private int age;
}
xml bean配置
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">
<bean id="person" class="com.gcdd1993.spring.framework.base.domain.Person"/>
</beans>
入口
AbstractApplicationContext applicationContext = new ClassPathXmlApplicationContext("config.xml");
applicationContext.getBean("person");
使用Debug进入ClassPathXmlApplicationContext
构造函数,源码如下
public ClassPathXmlApplicationContext(String[] configLocations, boolean refresh, ApplicationContext parent)
throws BeansException {
super(parent);
setConfigLocations(configLocations);
if (refresh) {
refresh();
}
}
super(parent)
一步步向上调用父类构造函数,路径为
ClassPathXmlApplicationContext -> AbstractXmlApplicationContext -> AbstractRefreshableConfigApplicationContext -> AbstractRefreshableApplicationContext -> AbstractApplicationContext
历经整个继承体系,最终到达AbstractApplicationContext
:
public AbstractApplicationContext(ApplicationContext parent) {
this();
setParent(parent);
}
最后会设置当前ApplicationContext
的父级ApplicationContext
setConfigLocations(configLocations)
设置配置文件路径,解析的细节参照官方文档Resource一节,不是本文讨论的重点,在此略过。
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++) {
this.configLocations[i] = resolvePath(locations[i]).trim();
}
}
else {
this.configLocations = null;
}
}
refresh()
此方法是Spring容器的核心方法,源码(精简了try catch部分)如下:
public void refresh() throws BeansException, IllegalStateException {
// Prepare this context for refreshing.
prepareRefresh();
// Tell the subclass to refresh the internal bean factory.
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
// Prepare the bean factory for use in this context.
prepareBeanFactory(beanFactory);
// Allows post-processing of the bean factory in context subclasses.
postProcessBeanFactory(beanFactory);
// Invoke factory processors registered as beans in the context.
invokeBeanFactoryPostProcessors(beanFactory);
// Register bean processors that intercept bean creation.
registerBeanPostProcessors(beanFactory);
// Initialize message source for this context.
initMessageSource();
// Initialize event multicaster for this context.
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();
}
此处可以看到Spring编码方式近似于流程图的,重点部分都抽出为了单独的方法,流程清晰,易于理解。我们一步步看:
prepareRefresh()
上下文刷新前预热
protected void prepareRefresh() {
this.startupDate = System.currentTimeMillis();
this.closed.set(false);
this.active.set(true);
if (logger.isInfoEnabled()) {
logger.info("Refreshing " + this);
}
// Initialize any placeholder property sources in the context environment
initPropertySources();
// Validate that all properties marked as required are resolvable
// see ConfigurablePropertyResolver#setRequiredProperties
getEnvironment().validateRequiredProperties();
// Allow for the collection of early ApplicationEvents,
// to be published once the multicaster is available...
this.earlyApplicationEvents = new LinkedHashSet<ApplicationEvent>();
}
- 设置上下文基本信息,如startupDate(启动时刻)、closed(是否关闭)、active(是否存活)等等。
- 解析占位符资源,并验证标记为required的资源是否可用
obtainFreshBeanFactory()
初始化beanFactory(bean工厂,实际存放bean的就是它了)
protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
refreshBeanFactory();
ConfigurableListableBeanFactory beanFactory = getBeanFactory();
if (logger.isDebugEnabled()) {
logger.debug("Bean factory for " + getDisplayName() + ": " + beanFactory);
}
return beanFactory;
}
核心方法refreshBeanFactory()
protected final void refreshBeanFactory() throws BeansException {
if (hasBeanFactory()) {
destroyBeans();
closeBeanFactory();
}
try {
DefaultListableBeanFactory beanFactory = createBeanFactory();
beanFactory.setSerializationId(getId());
customizeBeanFactory(beanFactory);
loadBeanDefinitions(beanFactory);
synchronized (this.beanFactoryMonitor) {
this.beanFactory = beanFactory;
}
}
catch (IOException ex) {
throw new ApplicationContextException("I/O error parsing bean definition source for " + getDisplayName(), ex);
}
}
- createBeanFactory();
- 设置beanFactory属性
- loadBeanDefinitions(beanFactory);
loadBeanDefinitions(beanFactory)
解析bean定义,有几个bean就有几个BeanDefinition。注意,Spring并不是拿到配置就直接用反射实例化bean,而是先将bean配置解析为BeanDefinition。
BeanDefinition保存了实例化bean需要的一切信息,包括属性,依赖等。以ConcurrentHashMap<String, BeanDefinition>
保存在DefaultListableBeanFactory的beanDefinitionMap里。
prepareBeanFactory(beanFactory)
设置beanFactory的其余属性
postProcessBeanFactory(beanFactory)
空实现,给子类一个机会,自定义beanFactory后置处理器
BeanFactoryPostProcessor
定义:
public interface BeanFactoryPostProcessor {
void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException;
}
invokeBeanFactoryPostProcessors(beanFactory)
执行上一步中的beanFactory后置处理器的回调方法
void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory)
registerBeanPostProcessors(beanFactory)
注册bean后置处理器,实现bean初始化前后的自定义逻辑
BeanPostProcessor
定义:
public interface BeanPostProcessor {
// 在bean实例化前调用
Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException;
// 在bean实例化后调用
Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException;
}
initMessageSource()
注册国际化相关bean
initApplicationEventMulticaster()
初始化Spring事件发布相关bean
onRefresh()
空实现,给子类一个机会,初始化特殊bean
registerListeners()
注册监听器
finishBeanFactoryInitialization(beanFactory)
实例化所有非懒加载的bean
直到这里,才开始真正实例化bean
protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {
// 1. 实例化bean的类型转换器
if (beanFactory.containsBean(CONVERSION_SERVICE_BEAN_NAME) &&
beanFactory.isTypeMatch(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class)) {
beanFactory.setConversionService(
beanFactory.getBean(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class));
}
// 2. 实例化属性占位符解析器
if (!beanFactory.hasEmbeddedValueResolver()) {
beanFactory.addEmbeddedValueResolver(new StringValueResolver() {
@Override
public String resolveStringValue(String strVal) {
return getEnvironment().resolvePlaceholders(strVal);
}
});
}
// 3. 实例化LoadTimeWeaverAware
String[] weaverAwareNames = beanFactory.getBeanNamesForType(LoadTimeWeaverAware.class, false, false);
for (String weaverAwareName : weaverAwareNames) {
getBean(weaverAwareName);
}
// 4. 停止使用临时ClassLoader进行类型匹配
beanFactory.setTempClassLoader(null);
// 5. 禁止再修改bean定义
beanFactory.freezeConfiguration();
// 6. 实例化所有非懒加载单例bean
beanFactory.preInstantiateSingletons();
}
preInstantiateSingletons()
- 根据每一个bean定义,实例化bean
- 为每一个实现SmartInitializingSingleton的bean执行回调方法
实例化bean部分的代码:
for (String beanName : beanNames) {
// 获取bean定义
RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
// 只有不是abstract、单例且不是懒加载的bean才在这里实例化
if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
// 如果是FactoryBean
if (isFactoryBean(beanName)) {
// 先实例化实例对应的FactoryBean
final FactoryBean<?> factory = (FactoryBean<?>) getBean(FACTORY_BEAN_PREFIX + beanName);
boolean isEagerInit;
if (System.getSecurityManager() != null && factory instanceof SmartFactoryBean) {
isEagerInit = AccessController.doPrivileged(new PrivilegedAction<Boolean>() {
@Override
public Boolean run() {
return ((SmartFactoryBean<?>) factory).isEagerInit();
}
}, getAccessControlContext());
}
else {
isEagerInit = (factory instanceof SmartFactoryBean &&
((SmartFactoryBean<?>) factory).isEagerInit());
}
if (isEagerInit) {
// 使用FactoryBean的getObject()方法返回真正的实例
getBean(beanName);
}
}
else {
getBean(beanName);
}
}
}
getBean(String name)
该方法调用了一个doGetBean,doGetBean代码较长,而且有部分代码是为了解决并发场景下单例的生成,我们挑出重点的看:
- 从父BeanFactory检查是否存在该bean的定义,如果存在,委托父BeanFactory来实例化
BeanFactory parentBeanFactory = getParentBeanFactory();
if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
// Not found -> check parent.
String nameToLookup = originalBeanName(name);
if (args != null) {
// Delegation to parent with explicit args.
return (T) parentBeanFactory.getBean(nameToLookup, args);
}
else {
// No args -> delegate to standard getBean method.
return parentBeanFactory.getBean(nameToLookup, requiredType);
}
}
- 获得bean定义,如果存在依赖,先实例化每一个依赖bean,注意:不允许循环依赖
final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
checkMergedBeanDefinition(mbd, beanName, args);
// Guarantee initialization of beans that the current bean depends on.
String[] dependsOn = mbd.getDependsOn();
//如果存在依赖,先实例化每一个依赖bean
if (dependsOn != null) {
// 实例化每一个依赖bean
for (String dep : dependsOn) {
// 检查循环依赖
if (isDependent(beanName, dep)) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"Circular depends-on relationship between '" + beanName + "' and '" + dep + "'");
}
// 实例化依赖bean
registerDependentBean(dep, beanName);
try {
getBean(dep);
}
catch (NoSuchBeanDefinitionException ex) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"'" + beanName + "' depends on missing bean '" + dep + "'", ex);
}
}
}
- 实例化bean
方法调用流程:
createBean > doCreateBean > populateBean
其中doCreateBean:
- 从BeanDefinition生成BeanWrapper
- 将BeanWrapper和BeanDefinition.getPropertyValues() 传给populateBean,实例化bean
finishRefresh()
protected void finishRefresh() {
// 初始化生命周期处理器
initLifecycleProcessor();
// 刷新生命周期处理器状态 running = true
getLifecycleProcessor().onRefresh();
// 发布上下文初始化完成事件ContextRefreshedEvent
publishEvent(new ContextRefreshedEvent(this));
// 如果处于活动状态,将自己注册到LiveBeans
LiveBeansView.registerApplicationContext(this);
}
总结
Spring IoC Container时序图