使用示例
读源码先从最简单的使用示例入手,然后一层一层往下探索,下面先写一个典型的spring小例子,来看一下它的入口与使用方法:
//创建User类
public class User {
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
//定义XML文件:user.xml
//省略spring配置文件头
......
<bean name="user" class="User">
<property name="name" value="test"/>
</bean>
//使用示例:
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("user.xml");
User user = (User)applicationContext.getBean("user");
System.out.println(user.getName());
整个例子非常简单,就是创建一个User Bean,然后获得它的name,下面我们从入口
ClassPathXmlApplicationContext开始来了解Spring的启动流程。
启动流程
ClassPathXmlApplicationContext构造方法如下:
public ClassPathXmlApplicationContext(String[] configLocations, boolean refresh, ApplicationContext parent)
throws BeansException {
super(parent);
//设置xml配置文件
setConfigLocations(configLocations);
if (refresh) {
//启动
refresh();
}
}
接下来看启动核心方法refresh():
public void refresh() throws BeansException, IllegalStateException {
synchronized (this.startupShutdownMonitor) {
//主要是校验配置与参数
// Prepare this context for refreshing.
prepareRefresh();
//创建一个BeanFactory,用于创建bean
// Tell the subclass to refresh the internal bean factory.
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
//初始化beanFactory, 主要是准备创建bean时需要的环境与关系,并且会创建几个初始bean
// Prepare the bean factory for use in this context.
prepareBeanFactory(beanFactory);
try {
//允许子类设置postProcessor
//ClassPathXmlApplicationContext是spring基础的ApplicationContext,所以不需要设置特有功能的postprocessor
//像webApplicationContext则需要把servlet相关的processor设置进来,用来支撑spring mvc相关功能
// Allows post-processing of the bean factory in context subclasses.
postProcessBeanFactory(beanFactory);
//实例化processor 并注册到beanfactory中
//这里的processor主要是通过AbstractApplicationContext类addBeanFactoryPostProcessor方法设置进来的。
// Invoke factory processors registered as beans in the context.
invokeBeanFactoryPostProcessors(beanFactory);
//实例化processor 并注册到beanfactory中
//这里processor主要是spring本身自带的
// Register bean processors that intercept bean creation.
registerBeanPostProcessors(beanFactory);
//初始化message source并注册成bean,用于消息解析相关
// Initialize message source for this context.
initMessageSource();
//初始化事件广播器
// Initialize event multicaster for this context.
initApplicationEventMulticaster();
//子类刷新使用
// Initialize other special beans in specific context subclasses.
onRefresh();
//注册监听器,eventMulticaster广播之前产生的事件
// Check for listener beans and register them.
registerListeners();
//完成beanfactory初始化,确保所有单例bean完成加载,
//主要是通过getBean方法一个一个检查,为空时就创建bean
// Instantiate all remaining (non-lazy-init) singletons.
finishBeanFactoryInitialization(beanFactory);
//发布容器刷新完成事件,主要内容是定义生命周期的Bean
// 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的启动流程,因为流程涉及到的方法比较多,所以不一一分析各个方法的源码了,简单总结一下流程是这样的:
1.检查配置与参数
2.创建一个类型为
ConfigurableListableBeanFactory的beanFactory
3.初始化该beanFactory,主要是配置环境、创建一些默认bean等
4.注册postprocessor,先扩展类processor后spring基础类processor
5.注册广播与监听bean
6.完成初始化
7.注册生命周期管理的bean
其中processor作用是创建bean时允许加入自定义的修改。上面流程中最核心的是第6步,在这一步调用getBean方法,从而真正执行创建bean的工作,接下来我们看一下创建bean的过程。
创建bean
getBean方法最终后调用AbstractBeanFactory的getBean方法,如下:
public <T> T getBean(String name, Class<T> requiredType) throws BeansException {
return doGetBean(name, requiredType, null, false);
}
然后执行doGetBean:
protected <T> T doGetBean(
final String name, final Class<T> requiredType, final Object[] args, boolean typeCheckOnly)
throws BeansException {
..................
// Create bean instance.
if (mbd.isSingleton()) {
//从DefaultSingletonBeanRegistry的一级缓存中拿bean,如果不存在执行创建函数
//将创建成功后bean放入到一级缓存中。
sharedInstance = getSingleton(beanName, new ObjectFactory<Object>() {
@Override
public Object getObject() throws BeansException {
try {
//bean不存在则创建
return createBean(beanName, mbd, args);
}
catch (BeansException ex) {
// Explicitly remove instance from singleton cache: It might have been put there
// eagerly by the creation process, to allow for circular reference resolution.
// Also remove any beans that received a temporary reference to the bean.
destroySingleton(beanName);
throw ex;
}
}
});
bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
}
需要注意的是
DefaultSingletonBeanRegistry有三级缓存,getBean方法只是从第一级缓存中查找bean的成品。
接下来我们看createBean:
@Override
protected Object createBean(String beanName, RootBeanDefinition mbd, Object[] args) throws BeanCreationException {
if (logger.isDebugEnabled()) {
logger.debug("Creating instance of bean '" + beanName + "'");
}
RootBeanDefinition mbdToUse = mbd;
...............
//执行创建bean
Object beanInstance = doCreateBean(beanName, mbdToUse, args);
if (logger.isDebugEnabled()) {
logger.debug("Finished creating instance of bean '" + beanName + "'");
}
return beanInstance;
}
这样我们就进入了创建bean的核心方法doCreateBean:
protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final Object[] args)
throws BeanCreationException {
//实例化bean
// Instantiate the bean.
BeanWrapper instanceWrapper = null;
if (mbd.isSingleton()) {
instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
}
if (instanceWrapper == null) {
//实例化
instanceWrapper = createBeanInstance(beanName, mbd, args);
}
........................
//加入到三级缓存中
// Eagerly cache singletons to be able to resolve circular references
// even when triggered by lifecycle interfaces like BeanFactoryAware.
boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
isSingletonCurrentlyInCreation(beanName));
//为解决依赖问题,需要提前曝光还未创建完成的bean
if (earlySingletonExposure) {
if (logger.isDebugEnabled()) {
//这里的日志说得非常清楚,放在第三级缓存中是为了解决循环依赖问题
logger.debug("Eagerly caching bean '" + beanName +
"' to allow for resolving potential circular references");
}
//加入到三级缓存中
addSingletonFactory(beanName, new ObjectFactory<Object>() {
@Override
public Object getObject() throws BeansException {
return getEarlyBeanReference(beanName, mbd, bean);
}
});
}
//初始化:主要是设置注入的变量等
// Initialize the bean instance.
Object exposedObject = bean;
try {
//填充属性
populateBean(beanName, mbd, instanceWrapper);
if (exposedObject != null) {
//调用aware类方法,设置beanPostProcessor
exposedObject = initializeBean(beanName, exposedObject, mbd);
}
}
...............
return exposedObject;
}
这个方法有点长,我把关键的几行挑出来并用中文注释了,其实思路也挺清晰的,先创建实例再初始化最后加入到缓存中。
在doGetBean方法中,会执行getSingleton,这个方法会调用createBean,并将创建的bean加入到一级缓存中,代码如下:
public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) {
Assert.notNull(beanName, "'beanName' must not be null");
synchronized (this.singletonObjects) {
Object singletonObject = this.singletonObjects.get(beanName);
if (singletonObject == null) {
if (this.singletonsCurrentlyInDestruction) {
throw new BeanCreationNotAllowedException(beanName,
"Singleton bean creation not allowed while singletons of this factory are in destruction " +
"(Do not request a bean from a BeanFactory in a destroy method implementation!)");
}
if (logger.isDebugEnabled()) {
logger.debug("Creating shared instance of singleton bean '" + beanName + "'");
}
beforeSingletonCreation(beanName);
boolean newSingleton = false;
boolean recordSuppressedExceptions = (this.suppressedExceptions == null);
if (recordSuppressedExceptions) {
this.suppressedExceptions = new LinkedHashSet<Exception>();
}
try {
//执行创建bean操作:createBean()方法
singletonObject = singletonFactory.getObject();
newSingleton = true;
}
catch (IllegalStateException ex) {
// Has the singleton object implicitly appeared in the meantime ->
// if yes, proceed with it since the exception indicates that state.
singletonObject = this.singletonObjects.get(beanName);
if (singletonObject == null) {
throw ex;
}
}
catch (BeanCreationException ex) {
if (recordSuppressedExceptions) {
for (Exception suppressedException : this.suppressedExceptions) {
ex.addRelatedCause(suppressedException);
}
}
throw ex;
}
finally {
if (recordSuppressedExceptions) {
this.suppressedExceptions = null;
}
afterSingletonCreation(beanName);
}
if (newSingleton) {
//加入到一级缓存中
addSingleton(beanName, singletonObject);
}
}
return (singletonObject != NULL_OBJECT ? singletonObject : null);
}
}
加入缓存的代码如下:
protected void addSingleton(String beanName, Object singletonObject) {
synchronized (this.singletonObjects) {
//放入到一级缓存
this.singletonObjects.put(beanName, (singletonObject != null ? singletonObject : NULL_OBJECT));
//从三级缓存中删除
this.singletonFactories.remove(beanName);
//从二级缓存中删除
this.earlySingletonObjects.remove(beanName);
//标记该beanname已经被创建过
this.registeredSingletons.add(beanName);
}
}
上面的代码我们了解到bean的创建过程,总结如下:
getBean-> doGetBean->createBean->doCreateBean->放入一级缓存中->返回
当然这里主要是为了了解过程,所以很多细节被忽略了,包括两个重要功能:aop支持与循环依赖的解决,下一节将着重分析这两个功能的代码。
三级缓存与循环依赖
上文有提到
DefaultSingletonBeanRegistry中有三级缓存,用来保存不同创建阶段的bean, 第一级是bean实例化后存放的地方,此时还没有注入依赖关系,第二级则是将第一级缓存的bean进行增强后存放的地方,增强的主要内容是使用动态代理的方式使它支持AOP,最后把第二级的bean注入依赖关系后放入到第三级。
三级缓存如下:
1.第一级为bean成品:singletonObjects
/** Cache of singleton objects: bean name --> bean instance */
private final Map<String, Object> singletonObjects = new ConcurrentHashMap<String, Object>(256);
2.第二级:earlySingletonObjects
/** Cache of early singleton objects: bean name --> bean instance */
private final Map<String, Object> earlySingletonObjects = new HashMap<String, Object>(16);
3.第三级:singletonFactories
/** Cache of singleton factories: bean name --> ObjectFactory */
private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap<String, ObjectFactory<?>>(16);
那spring是怎么利用三级缓存来解决依赖问题的呢? 在doCreateBean方法中,spring使用createBeanInstance方法创建了一个bean实例,这个实例还未进行初始化,它会先放到第三级缓存中,然后检查依赖关系,下面继续回到doCreateBean方法中:
protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final Object[] args)
throws BeanCreationException {
.................................................
boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
isSingletonCurrentlyInCreation(beanName));
if (earlySingletonExposure) {
if (logger.isDebugEnabled()) {
//这里的日志说得非常清楚,放在第三级缓存中是为了解决循环依赖问题
logger.debug("Eagerly caching bean '" + beanName +
"' to allow for resolving potential circular references");
}
//加入到三级缓存中
addSingletonFactory(beanName, new ObjectFactory<Object>() {
@Override
public Object getObject() throws BeansException {
return getEarlyBeanReference(beanName, mbd, bean);
}
});
}
.........................................
//开始检查循环依赖
if (earlySingletonExposure) {
//从三级缓存中拿出刚刚实例化的bean
Object earlySingletonReference = getSingleton(beanName, false);
if (earlySingletonReference != null) {
if (exposedObject == bean) {
exposedObject = earlySingletonReference;
}
else if (!this.allowRawInjectionDespiteWrapping && hasDependentBean(beanName)) {
//拿出它所有依赖的bean
String[] dependentBeans = getDependentBeans(beanName);
Set<String> actualDependentBeans = new LinkedHashSet<String>(dependentBeans.length);
for (String dependentBean : dependentBeans) {
if (!removeSingletonIfCreatedForTypeCheckOnly(dependentBean)) {
actualDependentBeans.add(dependentBean);
}
}
//如果发现有依赖的bean还没有被创建就会报异常
if (!actualDependentBeans.isEmpty()) {
//其实看这里的注释就知道跟解决循环依赖有关
throw new BeanCurrentlyInCreationException(beanName,
"Bean with name '" + beanName + "' has been injected into other beans [" +
StringUtils.collectionToCommaDelimitedString(actualDependentBeans) +
"] in its raw version as part of a circular reference, but has eventually been " +
"wrapped. This means that said other beans do not use the final version of the " +
"bean. This is often the result of over-eager type matching - consider using " +
"'getBeanNamesOfType' with the 'allowEagerInit' flag turned off, for example.");
}
}
}
}
..............................................
}
看完上面代码你是不是感觉很奇怪,上面代码只有检查依赖关系,那哪里设置依赖关系呢?下面我们从deCreateBean里进入populateBean方法中:
protected void populateBean(String beanName, RootBeanDefinition mbd, BeanWrapper bw) {
PropertyValues pvs = mbd.getPropertyValues();
................
//对属性赋值,如果属性是注入的对象,则会触发设置依赖关系
applyPropertyValues(beanName, mbd, bw, pvs);
}
protected void applyPropertyValues(String beanName, BeanDefinition mbd, BeanWrapper bw, PropertyValues pvs) {
if (pvs == null || pvs.isEmpty()) {
return;
}
..................
//解析属性值,如果属性是依赖注入
Object resolvedValue = valueResolver.resolveValueIfNecessary(pv, originalValue);
................
开始解析引用
public Object resolveValueIfNecessary(Object argName, Object value) {
// We must check each value to see whether it requires a runtime reference
// to another bean to be resolved.
//通过xml注入的
if (value instanceof RuntimeBeanReference) {
RuntimeBeanReference ref = (RuntimeBeanReference) value;
//
return resolveReference(argName, ref);
}
//通过autowired注入的
else if (value instanceof RuntimeBeanNameReference) {
String refName = ((RuntimeBeanNameReference) value).getBeanName();
refName = String.valueOf(doEvaluate(refName));
if (!this.beanFactory.containsBean(refName)) {
throw new BeanDefinitionStoreException(
"Invalid bean name '" + refName + "' in bean reference for " + argName);
}
return refName;
}
................................
private Object resolveReference(Object argName, RuntimeBeanReference ref) {
try {
String refName = ref.getBeanName();
refName = String.valueOf(doEvaluate(refName));
if (ref.isToParent()) {
if (this.beanFactory.getParentBeanFactory() == null) {
throw new BeanCreationException(
this.beanDefinition.getResourceDescription(), this.beanName,
"Can't resolve reference to bean '" + refName +
"' in parent factory: no parent factory available");
}
return this.beanFactory.getParentBeanFactory().getBean(refName);
}
else {
//调用getBean来创建所依赖的bean
Object bean = this.beanFactory.getBean(refName);
this.beanFactory.registerDependentBean(refName, this.beanName);
return bean;
}
}
.....................
从上面的代码我们可以看出,createBean前会先检查它所依赖的bean,如果该bean还没有被创建就调用getBean来创建该bean,这个时候就会有一个问题了,如果两个bean相互依赖,那岂不是会死循环了?
我们来继续看看解决循环依赖死循环的关键:getSingleton方法
protected Object getSingleton(String beanName, boolean allowEarlyReference) {
//先在一级缓存中找
Object singletonObject = this.singletonObjects.get(beanName);
//如果发现bean还在创建中
if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
synchronized (this.singletonObjects) {
//从二级缓存中找
singletonObject = this.earlySingletonObjects.get(beanName);
if (singletonObject == null && allowEarlyReference) {
//从三级缓存中找
ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
if (singletonFactory != null) {
singletonObject = singletonFactory.getObject();
//从三级缓存中移动到二级缓存中
this.earlySingletonObjects.put(beanName, singletonObject);
this.singletonFactories.remove(beanName);
}
}
}
}
return (singletonObject != NULL_OBJECT ? singletonObject : null);
}
通过代码我们可以看到即使bean还在三级缓存也会拿出来,这样它就不会重复执行doCreateBean了。
简化以上逻辑如下:
- 假设A与B相互依赖
- 创建A时先实例化放入三级缓存
- 赋值时发现依赖B,调用getBean方法来创建B
- B实例化后放入三级缓存
- 赋值时发现依赖A,调用getBean方法来创建A
- 这个时候A已经存在于第三缓存了,返回A给B
- 然后完成B的创建
- 接着完成A的创建。
关注个人微信公众号:肌肉码农,回复“好友”讨论问题。