入口
- SpringBoot启动过程一文中,提到在
refresh
过程里,会通过扫描解析已注入的@Configuration
类的@ComponentScan
、@Import
、@Component
、@Bean
…注册其余的BeanDefinition
; - 在
springmvc
通过web.xml
中contextConfigLocation
的值,加载并解析beans文件; - 自己创建
ClassPathXmlApplicationContext
,指定configLocation,在refresh
时,解析config文件注册BeanDefinition
;
初始化
我们的容器在refresh
通过配置载入约定的BeanDefinition
,并在之后预先初始化一部分Non-Lazy
的bean。接下来我们来看下一个bean是如何初始化的,这里会涉及到面试最常见的三级缓存以及bean的生命周期。
一个bean的载入是通过getBean
开始的,如果已在容器里,就直接返回已创建的对象,如果没有就先创建这个bean,再返回。
我们直接从AbstractBeanFactory#doGetBean
开始, 这个方法比较长,先忽略部分代码,我们从一个bean的从无到有过程分析:
public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport implements ConfigurableBeanFactory {
protected <T> T doGetBean(
String name, @Nullable Class<T> requiredType, @Nullable Object[] args, boolean typeCheckOnly)
throws BeansException {
String beanName = transformedBeanName(name);
Object bean;
// Eagerly check singleton cache for manually registered singletons.
Object sharedInstance = getSingleton(beanName);
// 如果已存在实例,返回
if (sharedInstance != null && args == null) {
...
// 考虑到该bean可能是个FactoryBean,需要获取真正的bean对象
bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
} else {
// 一些校验,以及是否从parentBeanFactory里获取该bean的判断
...
try {
RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
checkMergedBeanDefinition(mbd, beanName, args);
// 获取bean的依赖 `@DependsOn`
// 最终还是通过getBean获取依赖的bean
String[] dependsOn = mbd.getDependsOn();
if (dependsOn != null) {
for (String dep : dependsOn) {
...
}
}
// 如果当前bean是Singleton
if (mbd.isSingleton()) {
// 第二个参数是匿名FactoryBean,实现其`getObject`方法
sharedInstance = getSingleton(beanName, () -> {
try {
return createBean(beanName, mbd, args);
}
catch (BeansException ex) {
// 销毁bean
destroySingleton(beanName);
throw ex;
}
});
// 获取给定bean实例的对象
// 如果是FactoryBean,则获取bean实例本身或其创建的对象
bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
}
else if (mbd.isPrototype()) {
...
}
else {
...
}
catch (BeansException ex) {
cleanupAfterBeanCreationFailure(beanName);
throw ex;
}
}
// 类型转换
if (requiredType != null && !requiredType.isInstance(bean)) {
...
}
return (T) bean;
}
}
getInstance
在DefaultSingletonBeanRegistry
中getInstance
有3个重载,就上面的doGetBean
方法用到了2个重载:第一次getInstance
是只从容器里取(这里可以看到Spring bean的三级缓存);第二次getInstance
是先从容器里获取,如果没有的话就创建:
public class DefaultSingletonBeanRegistry extends SimpleAliasRegistry implements SingletonBeanRegistry {
@Override
@Nullable
public Object getSingleton(String beanName) {
return getSingleton(beanName, true);
}
@Nullable
protected Object getSingleton(String beanName, boolean allowEarlyReference) {
// singletonObjects里存放的是最终实例完毕的bean
Object singletonObject = this.singletonObjects.get(beanName);
// 一级缓存没有并且不在创建中(即未开始创建流程)
if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
synchronized (this.singletonObjects) {
// 从二级缓存获取对象
singletonObject = this.earlySingletonObjects.get(beanName);
// 如果不在二级缓存,就从三级缓存(存放ObjectFactory)
if (singletonObject == null && allowEarlyReference) {
ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
// 如果在三级缓存里,通过`getObject`方法获取实例
// 并放入二级缓存里
// 此时该实例并未`初始化`完毕
if (singletonFactory != null) {
singletonObject = singletonFactory.getObject();
this.earlySingletonObjects.put(beanName, singletonObject);
this.singletonFactories.remove(beanName);
}
}
}
}
return singletonObject;
}
public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) {
Assert.notNull(beanName, "Bean name 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!)");
}
...
// 将beanName添加到singletonsCurrentlyInCreation集合中
beforeSingletonCreation(beanName);
boolean newSingleton = false;
boolean recordSuppressedExceptions = (this.suppressedExceptions == null);
if (recordSuppressedExceptions) {
this.suppressedExceptions = new LinkedHashSet<>();
}
try {
// 获取对象,执行`createBean`方法
singletonObject = singletonFactory.getObject();
newSingleton = true;
}
catch (IllegalStateException ex) {
...
}
catch (BeanCreationException ex) {
...
}
finally {
if (recordSuppressedExceptions) {
this.suppressedExceptions = null;
}
// 将beanName从singletonsCurrentlyInCreation集合中移除
afterSingletonCreation(beanName);
}
if (newSingleton) {
// 将singletonObject放入singletonObjects map中
// 并将其从singletonFactories(三级缓存),从earlySingletonObjects(二级缓存)删除
addSingleton(beanName, singletonObject);
}
}
return singletonObject;
}
}
}
createBean
singletonFactory
的getObject
方法将调用到createBean
:
public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFactory
implements AutowireCapableBeanFactory {
@Override
protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
throws BeanCreationException {
RootBeanDefinition mbdToUse = mbd;
Class<?> resolvedClass = resolveBeanClass(mbd, beanName);
if (resolvedClass != null && !mbd.hasBeanClass() && mbd.getBeanClassName() != null) {
mbdToUse = new RootBeanDefinition(mbd);
mbdToUse.setBeanClass(resolvedClass);
}
try {
// 方法替换 比如init-method/replace-method
mbdToUse.prepareMethodOverrides();
}
catch (BeanDefinitionValidationException ex) {
throw new BeanDefinitionStoreException(mbdToUse.getResourceDescription(),
beanName, "Validation of method overrides failed", ex);
}
try {
// 实例前处理
// 会依次调用InstantiationAwareBeanPostProcessor的postProcessBeforeInstantiation方法
// 再调用它的postProcessAfterInitialization方法
// 这两个方法是不是感觉哪里看过,再AOP就是通过这两个方法生成的代理类
Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
if (bean != null) {
return bean;
}
}
catch (Throwable ex) {
throw new BeanCreationException(mbdToUse.getResourceDescription(), beanName,
"BeanPostProcessor before instantiation of bean failed", ex);
}
try {
// 创建bean
// 下文对`doCreateBean`详细解析
Object beanInstance = doCreateBean(beanName, mbdToUse, args);
...
return beanInstance;
}
catch (BeanCreationException | ImplicitlyAppearedSingletonException ex) {
throw ex;
}
catch (Throwable ex) {
throw new BeanCreationException(
mbdToUse.getResourceDescription(), beanName, "Unexpected exception during bean creation", ex);
}
}
protected Object doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
throws BeanCreationException {
BeanWrapper instanceWrapper = null;
if (mbd.isSingleton()) {
instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
}
if (instanceWrapper == null) {
· // 创建实例
// 使用实例化的策略:工厂方法、构造器自动装配、简单实例化
instanceWrapper = createBeanInstance(beanName, mbd, args);
}
Object bean = instanceWrapper.getWrappedInstance();
Class<?> beanType = instanceWrapper.getWrappedClass();
if (beanType != NullBean.class) {
mbd.resolvedTargetType = beanType;
}
synchronized (mbd.postProcessingLock) {
if (!mbd.postProcessed) {
try {
// 调到所有的实现了MergedBeanDefinitionPostProcessor接口的实例
// 其中有个非常关键的类:AutowiredAnnotationBeanPostProcessor
// 该类会扫描到正在实例化的bean的类里面属性和方法上面的`@Autowired`、`@Value`和`@Inject`注解
// 然后把对应的方法或者属性封装起来,最终封装成InjectionMetadata对象。
applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
}
catch (Throwable ex) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"Post-processing of merged bean definition failed", ex);
}
mbd.postProcessed = true;
}
}
// 提早暴露实例,以便能正确处理循环依赖的情况
boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
isSingletonCurrentlyInCreation(beanName));
if (earlySingletonExposure) {
...
// 将beanName及匿名singletonFactory放入`singletonFactories`(三级缓存)
// 将beanName从earlySingletonObjects移除(二级缓存)
// 将beanName添加到registeredSingletons集合中
addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
}
// 开始初始化bean
Object exposedObject = bean;
try {
// 填充bean的属性
populateBean(beanName, mbd, instanceWrapper);
// 初始化:依次执行以及bean post processor里的postProcessBeforeInitialization、init-method以及postProcessAfterInitialization
exposedObject = initializeBean(beanName, exposedObject, mbd);
}
catch (Throwable ex) {
// 异常处理
...
}
if (earlySingletonExposure) {
// 此时的bean并未放入singletonObjects集合中,所以取出来的earlySingletonReference为null
Object earlySingletonReference = getSingleton(beanName, false);
if (earlySingletonReference != null) {
...
}
}
try {
// 给当前bean注册一个DisposableBean接口(DisposableBeanAdapter)
// 包括`DestructionAwareBeanPostProcessors`、DisposableBean 接口以及自定义的`destroy-method`
registerDisposableBeanIfNecessary(beanName, bean, mbd);
}
catch (BeanDefinitionValidationException ex) {
throw new BeanCreationException(
mbd.getResourceDescription(), beanName, "Invalid destruction signature", ex);
}
return exposedObject;
}
}
循环依赖
我们看下下面这个例子:
@Component("beanA")
class A {
@Autowired
B b;
}
@Component("beanB")
class B {
@Autowired
A a;
}
从这个例子我们看到beanA依赖了beanB,而beanB又依赖于beanA。这就是我们说的循环依赖。
我们先简单想象下这两个单例bean的创建过程:当我们实例化beanA后,在设置它的属性时发现需要beanB; 于是我们就去创建beanB,实例化beanB后,在设置其属性时,发现它又需要一个class A实例;因为此时beanA尚未初始化完毕,所以还未加到容器里,于是又会去创建一个class A的实例,实例化完毕后,设置属性时发现需要一个class B实例… 如此反复,A需要B,B又需要A,这就形成了循环依赖。
那么Spring是如何解决这个问题的呢?查看上文的源码,其实已经有答案了:引入了缓存。简单得理解:当beanA实例化完成后,就加入一个缓存中,再进行初始化;当beanB需要class A时,先从缓存中取,缓存中没有的话再去重新实例化;当beanA初始化完成后再放入容器里,并删除缓存。
当然在Spring中没有那么简单粗暴,要更加完善些:Spring引入了三级缓存;
- 一级:singletonObjects,单例对象的缓存-从bean名到bean实例;
- 二级:earlySingletonObjects,缓存早期单例对象(未初始化完毕)-从bean名到bean实例;
- 三级:singletonFactories,缓存单例工厂-bean名到ObjectFactory;
我们直接看缓存的使用吧:
小结
我们定义的bean
一开始是以BeanDefinition
的形式存放在BeanFactory
里,当我们通过getBean
方法向容器获取指定bean
的时候,该bean
才会开始实例化以及初始化;
在实例化过程中,会先依次调用InstantiationAwareBeanPostProcessor
的postProcessBeforeInstantiation
与postProcessAfterInitialization
方法,方便我们对bean
的属性做一些改变,比如AOP就利用了对这两个方法对bean
进行了代理;如果没有产生合适的bean, 再选择合适的实例化方式进行实例化:工厂方法、构造器自动装配、简单实例化;
接着开始初始化:先解析bean
类里的@Autowired
、@Value
和@Inject
注解,并保存起来;接着利用提早暴露实例化好的bean
到singletonFactories
(三级缓存),解决循环依赖问题;再接着开始初始化该bean
,包括填充属性以及执行一些初始化方法;再接着按需给该bean
注册一个DisposableBean接口,在该bean
在销毁的时候执行一些特定的逻辑。
然后将完整的bean放入BeanFactory
的singletonObjects
中,并将其从singletonFactories
(三级缓存)和earlySingletonObjects
(二级缓存)删除。
以上小结只是加载bean
的一种路径,因为加载bean
时有很多判断、递归,这里就不赘述了。
以上小结中,有两点比较重要的点:1. bean
的生命周期;2. 循环依赖的解决;循环依赖的流程图上文已给出,这里总结下bean
的生命周期
作用域
在使用Spring Bean
过程中,我们会接触到作用域这个概念,常见的Scope
:
Prototype
: 原型,每次获取都会产生新的实例;Singleton
: 单例,在应用的生命周期里唯一;Request
: Web应用专属,在一个请求里唯一;Session
: Web应用专属,在一个会话里唯一;
这里有一个比较有意思的问题:当一个Prototype
beanA跟一个Singleton
beanB绑定后,我们在beanB里多次获取beanA是同一个对象还是不通的对象?
当然是同一个啦,因为单例是固定的,那它里面的属性都是不会变的。那我们在Spring里使用原型模式是不是要很小心,因为你以为的每次使用都是新对象,其实都是老对象,然后数据可能会因此出错?其实不然,Spring考虑到这点了,并使用了TargetSource
替我们解决这个问题。
public class TestController {
@Autowired
ResponseData testBean;
@GetMapping("test")
public ResponseData test() {
return testBean;
}
@Bean
@Scope(scopeName = ConfigurableBeanFactory.SCOPE_PROTOTYPE, proxyMode = ScopedProxyMode.TARGET_CLASS)
public ResponseData testBean() {
return ResponseData.success("hello");
}
}
从上图我们可以得出结论,testBean
是一个通过CGLIB动态代理的实例, 在intercept
方法里通过targetSource.getTarget();
获取到真正的bean
:
public class SimpleBeanTargetSource extends AbstractBeanFactoryBasedTargetSource {
@Override
public Object getTarget() throws Exception {
return getBeanFactory().getBean(getTargetBeanName());
}
}