Spring 中 Bean 的生命周期
1,什么是 Bean?
凡是由 Spring IoC 容器负责实例化,组装和管理的对象,我们都称之为 Bean 对象。Bean 对象本身可以看做是 Pojo。
官网解释:
In Spring, the objects that form the backbone of your application and that are managed by the Spring IoC container are called beans. A bean is an object that is instantiated, assembled, and managed by a Spring IoC container. Otherwise, a bean is simply one of many objects in your application. Beans, and the dependencies among them, are reflected in the configuration metadata used by a container.
2,Bean 的生命周期
2.1,BeanDefinition 读取&解析
我们可以通过 XML 或者是配置注解的方式为 Bean 进行配置。该阶段由 BeanDefinitionReader 接口负责,并由其实现类具体实现。
另一方面,Spring 的配置文件读取是通过 Resource 接口定义:
总结:文件解析流程
- 获取对 XML 文件的验证模式;(DTD 和 XSD 方式,文件头注明)
- 加载 XML 文件,获得对应的 Doucument;
- 根据 Document 注册 Bean 信息。
2.2,BeanDefinition 注册&加载
通过上述方式我们获得 Document 后解析为 BeanDefinition,通过 BeanDefinitionRegistry 的唯一真正实现子类 DefaultListableBeanFactory#registerBeanDefinition 注册,并存储在 beanDefinitionMap 中。
同时,此过程中还涉及到 BeanDefinition 的合并与转换,比如将存在父子关系的 RootBeanDefinition 和 ChileBeanDefinition 通过
DefaultListableBeanFactory#getMergedBeanDefinition 方法合并为一个最终的 RootBeanDefinition。因为解析得到的 BeanDefinition 是以 GenericBeanDefinition 的形式而存在的,也要做一步转换。
何谓父子关系?也就是 bean 之间可以继承,子类享有父类的属性。
有没有想想我们为什么需要 BeanDefinition,按道理我们需要的是 Bean 工厂。
其实,在 BeanDefinition 中有个 Object beanClass;通过 AbstractBeanFactory#resolveBeanClass 将 object 类型对象转换为 class 型以便后续进行实例化。
2.3,Bean 实例化
2.3.1,Bean 实例化前
实例化前,可以通过实现 BeanFactoryPostProcessor#postProcessBeanFactory,并根据优先级顺序对读取的 BeanDefinition 进行属性覆盖和增加。(注意不能提前获取 Bean 对象,会造成 Bean 的提前初始化。)
此过程相当于对 BeanFactory 的一个扩展。
2.3.2,Bean 实例化
这个阶段会在实例 Bean 的过程中穿插涉及到 InstantiationAwareBeanPostProcessor 的较多操作,我们主要看下它的实现方法的调用机制。
首先,通过 AbstractAutowireCapableBeanFactory#createBean#doCreateBean#createBeanInstance 方法,同时对于不同的 Bean 会有不同的实例策略:
protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) {
// BeanDefinition 加载获得类对象
Class<?> beanClass = resolveBeanClass(mbd, beanName);
if (beanClass != null && !Modifier.isPublic(beanClass.getModifiers()) && !mbd.isNonPublicAccessAllowed()) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"Bean class isn't public, and non-public access not allowed: " + beanClass.getName());
}
Supplier<?> instanceSupplier = mbd.getInstanceSupplier();
if (instanceSupplier != null) {
return obtainFromSupplier(instanceSupplier, beanName);
}
//1,如果 factory-method 属性不为空,则使用 factory-method 方式实例化
if (mbd.getFactoryMethodName() != null) {
return instantiateUsingFactoryMethod(beanName, mbd, args);
}
// Shortcut when re-creating the same bean...
boolean resolved = false;
boolean autowireNecessary = false;
if (args == null) {
synchronized (mbd.constructorArgumentLock) {
if (mbd.resolvedConstructorOrFactoryMethod != null) {
resolved = true;
autowireNecessary = mbd.constructorArgumentsResolved;
}
}
}
if (resolved) {
if (autowireNecessary) {
return autowireConstructor(beanName, mbd, null, null);
}
else {
return instantiateBean(beanName, mbd);
}
}
//2,决定候选的构造器实例化 bean...
Constructor<?>[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName);
if (ctors != null ||
mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_CONSTRUCTOR ||
mbd.hasConstructorArgumentValues() || !ObjectUtils.isEmpty(args)) {
return autowireConstructor(beanName, mbd, ctors, args);
}
//3, 否则指向默认的无参构造策略:
//最终通过 BeanUtils#instantiateClass 调用 ctor.newInstance 方法反射创建
return instantiateBean(beanName, mbd);
}
当然,对于有依赖的 Bean,可以通过后置增强器实现依赖 Bean 的实例化,处理原则是先实现依赖的 Bean,再实例 Bean。
重点来了,在实例化阶段可以进行增强操作,具体通过 AbstractAutowireCapableBeanFactory#creatBean 方法中通过调用 resolveBeforeInstantiation 里的增强操作,如果返回不为空则直接完成 Bean 的实例化操作退出;如果返回为空,则进入上层的 createBean 方法执行 doCreateBean,继续完成 spring 正常的执行流程。
protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
throws BeanCreationException {
//省略。。。。。
try {
// Give BeanPostProcessors a chance to return a proxy instead of the target bean instance.
Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
if (bean != null) {
return bean;
}
}
}
这里的 resolveBeforeInstantiation 分别进行了 applyBeanPostProcessorsBeforeInstantiation 和 applyBeanPostProcessorsAfterInitialization 实现实例化前和初始化后的增强操作。可见,如果在实例化前进行了增强,那么会跳过实例化后和初始化前操作,直接创建完成 Bean 对象。下一阶段将会进行属性填充。
protected Object resolveBeforeInstantiation(String beanName, RootBeanDefinition mbd) {
Object bean = null;
if (!Boolean.FALSE.equals(mbd.beforeInstantiationResolved)) {
// Make sure bean class is actually resolved at this point.
if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
Class<?> targetType = determineTargetType(beanName, mbd);
if (targetType != null) {
bean = applyBeanPostProcessorsBeforeInstantiation(targetType, beanName);
if (bean != null) {
bean = applyBeanPostProcessorsAfterInitialization(bean, beanName);
}
}
}
mbd.beforeInstantiationResolved = (bean != null);
}
return bean;
}
上面说道,当我们的 resolveBeforeInstantiation 返回为空的时候会正常执行对象的实例,doCreateBean 方法触发:
protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final @Nullable Object[] args) throws BeanCreationException {
// Instantiate the bean.
BeanWrapper instanceWrapper = null;
if (mbd.isSingleton()) {
instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
}
if (instanceWrapper == null) {
//如果 bean 实例未被创建,先创建 bean,这里调用 createBeanInstance 又回到了上面
instanceWrapper = createBeanInstance(beanName, mbd, args);
}
// Initialize the bean instance.
Object exposedObject = bean;
try {
//属性赋值
populateBean(beanName, mbd, instanceWrapper);
//initializeBean 进去便触发我们的初始化方法
exposedObject = initializeBean(beanName, exposedObject, mbd);
}
我们再来看 populateBean:
protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) {
// Give any InstantiationAwareBeanPostProcessors the opportunity to modify the
// state of the bean before properties are set. This can be used, for example,
// to support styles of field injection.
boolean continueWithPropertyPopulation = true;
if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
for (BeanPostProcessor bp : getBeanPostProcessors()) {
if (bp instanceof InstantiationAwareBeanPostProcessor) {
InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
//实例化后置处理器(属性赋值也被认为是实例化阶段)
if (!ibp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) {
continueWithPropertyPopulation = false;
break;
}
}
}
}
小结:
BeanPostProcessor 定义的初始化前后方法,会在 resolveBeforeInstantiation 触发前置处理器;或是在 initializeBean 触发前置和后置处理器。
InstantiationAwareBeanPostProcessor 定义的方法,会在实例化过程中,由 resolveBeforeInstantiation 触发前置处理器,populateBean 触发后置处理器。
2.3.3,属性赋值
这一步进行属性填充,具体是 InstantiationAwareBeanPostProcessor#populateBean 里的 getPropertyValues。该方法最终会通过调用 Filed.set 方法完成 xml 中标签 property 配置的属性注入。
该方法的另外两个实现:
AutowiredAnnotationBeanPostProcessor 在这个方法对@Autowired、@Value 标注的字段、方法注入值。
CommonAnnotationBeanPostProcessor 在这个方法对@Resource 标注的字段和方法注入值。
2.4,Bean 初始化
2.4.1,Bean 初始化前
此过程对 AbstractAutowireCapableBeanFactory#initializeBea 中的调用顺序:
- applyBeanPostProcessorsBeforeInitialization#postProcessBeforeInitialization 的前置处理器
- invokeInitMethods #初始化方法
- applyBeanPostProcessorsAfterInitialization#postProcessAfterInitialization 的后置处理器
2.4.2,Bean 初始化
调用 InitializingBean#afterPropertiesSet 方法;
然后调用定义 bean 的时候指定的初始化方法
Bean 知道初始化方法的方式:
方式 1:xml 方式指定初始化方法
方式 2:@Bean 的方式指定初始化方法
@Bean(initMethod = “初始化的方法”)
方式 3:api 的方式指定初始化方法
this.beanDefinition.setInitMethodName(methodName);
2.4.3,Bean 初始化后
调用 BeanPostProcessor 接口的 postProcessAfterInitialization 方法。
2.5,Bean 使用
直接调用 getBean 方法。
2.6,Bean 销毁
轮询 beanPostProcessors 列表,如果是 DestructionAwareBeanPostProcessor 这种类型的,会调用其内部的 postProcessBeforeDestruction 方法;
如果 bean 实现了 org.springframework.beans.factory.DisposableBean 接口,会调用这个接口中的 destroy 方法;
调用 bean 自定义的销毁方法。
3,面试
3.1,FactoryBean
某些时候实例化一个 Bean 非常复杂,如果他有较多的属性时,需要配置大量信息。而使用工厂BeanFactory创建bean的方式会严格执行生命周期,带来许多不便。为此可以通过实现 FactoryBean 接口定制实例化 Bean 逻辑。
当我们在配置文件中将 bean 的 class 属性设为 FactoryBean 接口类型时,通过 getBean 方法获取的 bean 不是 FactoryBean 本身而是 FactoryBean#getObject() 方法返回的对象,这里有一个代理。如果需要获取 FactoryBean 实例对象,需要显式的进行 getBean(&beanName)。
简而言之,FactoryBean是个小工厂,BeanFactory是个根工厂。
3.2,三级缓存解决循环依赖
/** Cache of singleton objects: bean name --> bean instance */
private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256);
/** Cache of singleton factories: bean name --> ObjectFactory */
private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap<>(16);
/** Cache of early singleton objects: bean name --> bean instance */
private final Map<String, Object> earlySingletonObjects = new HashMap<>(16);