前言
createBean进行了一些创建Bean实例前的工作:
- 检查当前BeanDefinition的Class是否可以被解析.
- 检查当前BeanDefinition的Lookup method是否存在,并且确认重载状态.
- 激活Bean实例化前的后置处理器.
随后,进行
doCreateBean
的调用.那么本文就来分析doCreateBean
的代码逻辑.
doCreateBean的总体流程
- 根据当前Bean的构造策略进行实例化,此时的bean未进行依赖注入: createBeanInstance.
-
解析Bean中被Spring注解标记的成员变量,如
@AutoWired
、@Value
、Resource
: applyMergedBeanDefinitionPostProcessors. - 判断是否要暴露早期引用的bean,为了解决循环依赖: addSingletonFactory.
- 填充bean实例属性: populateBean.
- 生命周期函数回调: initializeBean.
- 判断在循环依赖的情况下Bean的引用是否一致: allowRawInjectionDespiteWrapping
- 注册销毁方法: registerDisposableBeanIfNecessary
1. 根据当前Bean的构造策略进行实例化
在讲Bean的实例化前,需要简单了解一下什么是
BeanWrapper
.
1.1 BeanWrapper
JavaDoc: 提供用于分析和操作标准JavaBean的操作:获得和设置属性值(单独或批量),获取属性描述符以及查询属性的可读性/可写性的能力。
此接口支持嵌套属性,使子属性上的属性设置达到无限深度.
来看看接口清单.
public interface BeanWrapper extends ConfigurablePropertyAccessor {
// 指定数组和集合自动增长的限制。默认不限制,即无限.
void setAutoGrowCollectionLimit(int autoGrowCollectionLimit);
// 返回数组和集合自动增长的限制.
int getAutoGrowCollectionLimit();
// 返回当前BeanWrapper包装的Bean实例
Object getWrappedInstance();
// 返回当前BeanWrapper包装的Bean类型-Class
Class<?> getWrappedClass();
// 获取包装对象的PropertyDescriptors(由标准JavaBean自省确定)
PropertyDescriptor[] getPropertyDescriptors();
// 获取包装对象的PropertyDescriptor
PropertyDescriptor getPropertyDescriptor(String propertyName) throws InvalidPropertyException;
}
简单来说,通过这个接口视图,可以获取Bean的信息.例如:对象实例、Class、Property.
OK,简单了解过后,我们来看看实例化Bean的第一步-createBeanInstance
,调用构造函数获取一个对象实例。注意,这个对象实例并未是完整的Bean.
- AbstractAutowireCapableBeanFactory#doCreateBean
protected Object doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
throws BeanCreationException {
// Instantiate the bean.
// bean实例化包装类
BeanWrapper instanceWrapper = null;
if (mbd.isSingleton()) {
// 从未完成创建的包装bean缓存中清理并获取相关的包装bean实例,单例,不可以重复
instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
}
if (instanceWrapper == null) {
// 创建bean的方式有三种:
// 1.Factory method 2.constructor 3. supplier
instanceWrapper = createBeanInstance(beanName, mbd, args);
}
// 获取被包装的Bean,后续对bean的改动等于对wrapper进行改动,即对wrapper的改动也会改动bean
Object bean = instanceWrapper.getWrappedInstance();
// 获取实例化对象的类型
Class<?> beanType = instanceWrapper.getWrappedClass();
if (beanType != NullBean.class) {
mbd.resolvedTargetType = beanType;
}
举例说明: 假设有一个Bean是这样定义的.
@Controller
public class HelloController {
@Autowired
private HelloService helloService;
public void hello(){
System.out.println(helloService.hello()+",this is controller");
}
}
那么当我们getBean("helloController"),我们是希望
HelloController
中的helloService
是被实例化的(依赖注入).这时,我们才认为这是一个完整的Bean.而createBeanInstance
执行完后,仅仅是new HelloController
而已,此时并未将helloService
注入进来.(便于理解,其实Spring会做较为复杂的推断.)
- AbstractAutowireCapableBeanFactory#createBeanInstance
protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) {
// Make sure bean class is actually resolved at this point.
// 获取Class对象,前面在createBean已经进行过解析了,这里会直接从mbd.getBeanClass()返回
Class<?> beanClass = resolveBeanClass(mbd, beanName);
// 检查是否可以破环private的保护进行反射创建实例
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());
}
// 是否通过lambda的方式进行创建.在AbstractBeanDefinition中存储了此值.
Supplier<?> instanceSupplier = mbd.getInstanceSupplier();
if (instanceSupplier != null) {
return obtainFromSupplier(instanceSupplier, beanName);
}
// 通过工厂方法创建,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) {
// 如果已缓存的解析构造函数或者factoryMethod不为空
// 那么可以利用构造函数解析
if (mbd.resolvedConstructorOrFactoryMethod != null) {
resolved = true;
autowireNecessary = mbd.constructorArgumentsResolved;
}
}
}
if (resolved) {
// 自动注入,调用构造函数自动注入
if (autowireNecessary) {
return autowireConstructor(beanName, mbd, null, null);
}
else {
// 使用默认的构造函数构造
return instantiateBean(beanName, mbd);
}
}
// Candidate constructors for autowiring?
// 根据参数解析确定构造函数
Constructor<?>[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName);
// 解析的构造器不为空 | 注入类型为AUTOWIRE_CONSTRUCTOR | 有参 | 传入的参数不为空
if (ctors != null || mbd.getResolvedAutowireMode() == AUTOWIRE_CONSTRUCTOR ||
mbd.hasConstructorArgumentValues() || !ObjectUtils.isEmpty(args)) {
// 进行对象实例化
return autowireConstructor(beanName, mbd, ctors, args);
}
// Preferred constructors for default construction?
ctors = mbd.getPreferredConstructors();
if (ctors != null) {
return autowireConstructor(beanName, mbd, ctors, null);
}
// No special handling: simply use no-arg constructor.
// 如果没有推断出特殊的构造方法,使用这个默认的模式
// 无参的默认构造方法,内部使用JDK的反射.
return instantiateBean(beanName, mbd);
}
这里的逻辑在依赖注入概览的时候大概讲过,现在来重温一篇:
- 获取Class对象,校验是否为public、如果不是再判断是否为可以无视
private
的,也就是能否获取private
的授权.- 推断构造方法.查看BeanDefinition是否提供了类初始化的
Supplier
(lambda).如果提供,按照此方法进行实例化.- 查看BeanDefinition是否需要工厂方法进行初始化,如果是,使用
factory-method
进行初始化.- 查看BeanDefinition是否已经解析过构造方法,如果
constructorArgumentsResolved
为true
,那么直接使用解析好的构造方法进行实例化.- 如果都没有,那么看看构造注入策略是否为构造注入,并且是有参的形式.如果符合.进行自动注入
autowireConstructor(beanName, mbd, ctors, args)
- 如果以上条件都不符合,那么使用默认的JDK无参构造方法-
instantiateBean
- AbstractAutowireCapableBeanFactory#instantiateBean
根据初始化策略获取实例进行初始化,默认为
SimpleInstantiationStrategy
protected BeanWrapper instantiateBean(String beanName, RootBeanDefinition mbd) {
try {
Object beanInstance;
if (System.getSecurityManager() != null) {
beanInstance = AccessController.doPrivileged(
(PrivilegedAction<Object>) () -> getInstantiationStrategy().instantiate(mbd, beanName, this),
getAccessControlContext());
}
else {
// 从这里开始调用反射,获取当前的初始化策略,进行初始化.
// 默认使用 SimpleInstantiationStrategy.instantiate
beanInstance = getInstantiationStrategy().instantiate(mbd, beanName, this);
}
BeanWrapper bw = new BeanWrapperImpl(beanInstance);
initBeanWrapper(bw);
return bw;
}
catch (Throwable ex) {
throw new BeanCreationException(
mbd.getResourceDescription(), beanName, "Instantiation of bean failed", ex);
}
}
- SimpleInstantiationStrategy#instantiate
通常我们的Bean都会进入这种加载策略模式.在这里Spring获取当前BeanDefinition的构造函数,然后调用
BeanUtils.instantiateClass(constructorToUse);
,这里其实就是使用反射获取实例了。
public Object instantiate(RootBeanDefinition bd, @Nullable String beanName, BeanFactory owner) {
// Don't override the class with CGLIB if no overrides.
// 如果Bean中的方法没有重写,则不需要CGLIB来重写
// 通常这种情况会在 lookup method 和 replace method中
if (!bd.hasMethodOverrides()) {
Constructor<?> constructorToUse;
synchronized (bd.constructorArgumentLock) {
// 获取对象的构造方法或者工厂方法
constructorToUse = (Constructor<?>) bd.resolvedConstructorOrFactoryMethod;
if (constructorToUse == null) {
final Class<?> clazz = bd.getBeanClass();
// 是否为接口
if (clazz.isInterface()) {
throw new BeanInstantiationException(clazz, "Specified class is an interface");
}
try {
if (System.getSecurityManager() != null) {
constructorToUse = AccessController.doPrivileged(
(PrivilegedExceptionAction<Constructor<?>>) clazz::getDeclaredConstructor);
}
else {
// 获取默认的构造方法
constructorToUse = clazz.getDeclaredConstructor();
}
bd.resolvedConstructorOrFactoryMethod = constructorToUse;
}
catch (Throwable ex) {
throw new BeanInstantiationException(clazz, "No default constructor found", ex);
}
}
}
// newInstance
return BeanUtils.instantiateClass(constructorToUse);
}
else {
// Must generate CGLIB subclass.
// 使用CGLIB进行动态代理
return instantiateWithMethodInjection(bd, beanName, owner);
}
}
2. 解析Bean中被Spring注解标记的成员变量
进行对象初始化的步骤后,Spring开始解析当前Bean中被
@Autowired
注解标记的成员变量,这个工作交由applyMergedBeanDefinitionPostProcessors
中调用的MergedBeanDefinitionPostProcessor
来完成.
// 调用BeanDefinition属性合并后完成的BeanPostProcessor->MergedBeanDefinitionPostProcessor
synchronized (mbd.postProcessingLock) {
if (!mbd.postProcessed) {
try {
// @Value、@Autowired的注解解析入口
applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
}
catch (Throwable ex) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"Post-processing of merged bean definition failed", ex);
}
mbd.postProcessed = true;
}
}
- AbstractAutowireCapableBeanFactory#applyMergedBeanDefinitionPostProcessors
applyMergedBeanDefinitionPostProcessors
主要工作是通过MergedBeanDefinitionPostProcessor
接口的实现类来记录一些Spring需要识别的成员变量.
例如:
AutowiredAnnotationBeanPostProcessor
负责找到被@Autowired
、Value
所标注的成员变量.
CommonAnnotationBeanPostProcessor
负责找到被@Resource
、@PostConstruct
、@PreDestroy
标记的成员变量.
protected void applyMergedBeanDefinitionPostProcessors(RootBeanDefinition mbd, Class<?> beanType, String beanName) {
for (BeanPostProcessor bp : getBeanPostProcessors()) {
if (bp instanceof MergedBeanDefinitionPostProcessor) {
MergedBeanDefinitionPostProcessor bdp = (MergedBeanDefinitionPostProcessor) bp;
// AutowiredAnnotationBeanPostProcessor实现了MergedBeanDefinitionPostProcessor接口.
// 该PostPorcessor会将被@Autowired、@Value标记的成员变量进行记录.
// CommonAnnotationBeanPostProcessor也是MergedBeanDefinitionPostProcessor的一个实现.
// 该类负责记录@Resource、@PostConstruct、@PreDestroy.
bdp.postProcessMergedBeanDefinition(mbd, beanType, beanName);
}
}
}
2.1 Spring中的责任链模式
这里由于篇幅原因,就不对
CommonAnnotationBeanPostProcessor
做详细介绍了,Spring在applyMergedBeanDefinitionPostProcessors
中使用了责任链模式,对实现了MergedBeanDefinitionPostProcessor
接口的BeanPostProcessor
发送请求,每个BeanPostProcessor
接收到参数后,执行自己的专属任务.
2.2 AutowiredAnnotationBeanPostProcessor
- 构造函数
在构造函数中,AutowiredAnnotationBeanPostProcessor在
autowiredAnnotationTypes
中加入了需要识别的注解类型-@Autowired
、@Value
、@Inject
.
/**
* Create a new {@code AutowiredAnnotationBeanPostProcessor} for Spring's
* standard {@link Autowired @Autowired} annotation.
* <p>Also supports JSR-330's {@link javax.inject.Inject @Inject} annotation,
* if available.<br>
* 为Spring的标准@Autowired注解创建一个新的AutowiredAnnotationBeanPostProcessor。<br>
* 还支持JSR-330的@Inject注解。
*/
@SuppressWarnings("unchecked")
public AutowiredAnnotationBeanPostProcessor() {
this.autowiredAnnotationTypes.add(Autowired.class);
this.autowiredAnnotationTypes.add(Value.class);
try {
this.autowiredAnnotationTypes.add((Class<? extends Annotation>)
ClassUtils.forName("javax.inject.Inject", AutowiredAnnotationBeanPostProcessor.class.getClassLoader()));
logger.trace("JSR-330 'javax.inject.Inject' annotation found and supported for autowiring");
}
catch (ClassNotFoundException ex) {
// JSR-330 API not available - simply skip.
}
}
- AutowiredAnnotationBeanPostProcessor#postProcessMergedBeanDefinition
findAutowiringMetadata:扫描找出被
@Autowired
和@Vaule
注解标记的成员,并使用InjectionMetadata
进行封装,最后将Spring容器需要用默认策略注入的metadata保存到checkedElements中.
下面我们来了解一下什么是InjectionMetadata
.
@Override
public void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName) {
InjectionMetadata metadata = findAutowiringMetadata(beanName, beanType, null);
metadata.checkConfigMembers(beanDefinition);
}
2.3 InjectionMetadata
InjectionMetadata是Spring的一个内部框架使用的类,用于管理注入元数据。不适用于直接在应用程序中使用。
- InjectionMetadata的核心成员变量
targetClass-被解析的目标Class.
injectedElements-装载被@Value和@Autowired注解标记的成员集合.
checkedElements-和injectedElements一样,仅保存Spring默认处理的属性或者方法.
public class InjectionMetadata {
private static final Log logger = LogFactory.getLog(InjectionMetadata.class);
/**
* 目标class
*/
private final Class<?> targetClass;
/**
* <p>当postProcessor处理bean时,会解析bean class的所有属性.</p>
* <p>在解析时会判断属性上是否标记:@Value、@Autowired</p>
* <p>如果有,那么对该属性值进行解析,将解析结果放入injectedElements中</p>
* <p>可以说这是被注入元素的集合</p>
*/
private final Collection<InjectedElement> injectedElements;
/**
* 和injectedElements一样,仅保存Spring默认处理的属性或者方法
*/
@Nullable
private volatile Set<InjectedElement> checkedElements;
- InjectedElement
InjectedElement-用于装载被解析的Member,其中
Member
是Java中Field
和Method
的上层接口.
isField-布尔值,用于标记当前Member是否为Field类型.
/**
* A single injected element.<br>
* 单个注入元素。
*/
public abstract static class InjectedElement {
/**
* 被注解标记的成员,Field还是Method.<br>
* Member类是Field和Method的上层抽象.<br>
*/
protected final Member member;
/**
* 是否为Field
*/
protected final boolean isField;
/**
* 属性描述,JavaBean中的接口
*/
@Nullable
protected final PropertyDescriptor pd;
@Nullable
protected volatile Boolean skip;
}
- AutowiredAnnotationBeanPostProcessor#findAutowiringMetadata
OK,继续回到解析依赖注入的成员变量逻辑中.看看这个方法的代码逻辑
private InjectionMetadata findAutowiringMetadata(String beanName, Class<?> clazz, @Nullable PropertyValues pvs) {
// Fall back to class name as cache key, for backwards compatibility with custom callers.
// 获取类名---------例如:UserService<->userService
String cacheKey = (StringUtils.hasLength(beanName) ? beanName : clazz.getName());
// Quick check on the concurrent map first, with minimal locking.
// 首先以最小的锁定快速检查并发映射。从容器中查找是否有给定类的autowired相关注解元信息.
// 此处又见双重检测锁机制
InjectionMetadata metadata = this.injectionMetadataCache.get(cacheKey);
// 检查当前注解元数据是否需要重新获取,内部进行判空逻辑
if (InjectionMetadata.needsRefresh(metadata, clazz)) {
synchronized (this.injectionMetadataCache) {
metadata = this.injectionMetadataCache.get(cacheKey);
if (InjectionMetadata.needsRefresh(metadata, clazz)) {
if (metadata != null) {
// 如果需要重新解析,先清空metadata
metadata.clear(pvs);
}
// 重新解析被@Autowired、@Value标记的成员
metadata = buildAutowiringMetadata(clazz);
// 重新将注解元数据放入缓存中
this.injectionMetadataCache.put(cacheKey, metadata);
}
}
}
return metadata;
}
- 首先获取当前class的类名,规则为小写开头的驼峰.
- 从被解析过的注解元数据缓存中获取当前类的
metedata
(这里又又又用了双重检查锁机制保证线程安全和尽可能的使锁覆盖的代码块更小,因为多线程环境下,可能会同时解析同一个类).- 如果可以找到元数据,则直接return.
- 如果需要重新解析元数据,那么使用双重检查锁保证线程安全,同时清空缓存中的
metedata
,进入buildAutowiringMetadata
中解析类得到metadata
.- 将解析后的
metadata
回种到缓存中.
- AutowiredAnnotationBeanPostProcessor#buildAutowiringMetadata
/**
* 解析当前Class被@Autowired标记的成员
* @param clazz
* @return
*/
private InjectionMetadata buildAutowiringMetadata(final Class<?> clazz) {
List<InjectionMetadata.InjectedElement> elements = new ArrayList<>();
Class<?> targetClass = clazz;
// 递归遍历当前类及其所有基类,解析全部注解元信息
do {
final List<InjectionMetadata.InjectedElement> currElements = new ArrayList<>();
// 收集被@Autowired、@Value标记的Field.
// 利用反射机制获取给定类中所有的声明字段,获取字段上的注解信息
// doWithLocalFields->获取当前类的所有Field,每个field执行lambda内的逻辑.
ReflectionUtils.doWithLocalFields(targetClass, field -> {
// 此处逻辑较为复杂,通过debug发现如果为被标注的属性,会返回required:true.
// 大致的意思是这个field是否被特定的注解标记?这里留一个疑问
AnnotationAttributes ann = findAutowiredAnnotation(field);
if (ann != null) {
// 如果是static属性的成员,Spring不提供支持
if (Modifier.isStatic(field.getModifiers())) {
if (logger.isInfoEnabled()) {
logger.info("Autowired annotation is not supported on static fields: " + field);
}
return;
}
// 判断required的状态
boolean required = determineRequiredStatus(ann);
// 将当前成员添加进currElements
currElements.add(new AutowiredFieldElement(field, required));
}
});
// 上面是寻找被@Autowired和@Value标记的field,这里是寻找method
ReflectionUtils.doWithLocalMethods(targetClass, method -> {
Method bridgedMethod = BridgeMethodResolver.findBridgedMethod(method);
if (!BridgeMethodResolver.isVisibilityBridgeMethodPair(method, bridgedMethod)) {
return;
}
AnnotationAttributes ann = findAutowiredAnnotation(bridgedMethod);
if (ann != null && method.equals(ClassUtils.getMostSpecificMethod(method, clazz))) {
if (Modifier.isStatic(method.getModifiers())) {
if (logger.isInfoEnabled()) {
logger.info("Autowired annotation is not supported on static methods: " + method);
}
return;
}
// 如果方法不包含参数,打印警告信息
if (method.getParameterCount() == 0) {
if (logger.isInfoEnabled()) {
logger.info("Autowired annotation should only be used on methods with parameters: " +
method);
}
}
boolean required = determineRequiredStatus(ann);
// 找到方法内的属性
PropertyDescriptor pd = BeanUtils.findPropertyForMethod(bridgedMethod, clazz);
currElements.add(new AutowiredMethodElement(method, required, pd));
}
});
elements.addAll(0, currElements);
// 递归父类
targetClass = targetClass.getSuperclass();
}
while (targetClass != null && targetClass != Object.class);
return new InjectionMetadata(clazz, elements);
}
这里的方法较长,其实核心为寻找出当前类被
@Autowired
和@Value
标记的成员-Member
.而JDK中的Member
又可以分为Field
和Method
,所以你会看到ReflectionUtils.doWithLocalFields
和ReflectionUtils.doWithLocalMethods
,它们负责判断出当前的成员是否被标记,如果被标记,那么加入element
集合中.其中逻辑在findAutowiredAnnotation
中,这里不做展开。值得一提的是,Spring在5.2的版本中,对此处做了一些重构.
扫描完后,会将目标类与收集到的被注解标记的成员通过构造函数进行装配,返回InjectionMetadata
.
3. 检测是否需要提交暴露早期引用的Bean-addSingletonFactory
Spring是默认支持循环依赖的,但是循环依赖仅仅支持单例Bean的属性注入.
// 向容器中缓存单例模式的Bean对象,以防止循环引用
// 判断是否要暴露早期引用的bean
// 1. 是否为单例.
// 2. 是否允许循环引用
// 3. 是否在创建中的bean
boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
isSingletonCurrentlyInCreation(beanName));
if (earlySingletonExposure) {
if (logger.isTraceEnabled()) {
logger.trace("Eagerly caching bean '" + beanName +
"' to allow for resolving potential circular references");
}
// 匿名内部类,防止循环引用,尽早只有对象的引用
// 注意,此时的addSingletonFactory仅仅是注册了一个lambda代码块.
// getEarlyBeanReference实现的是ObjectFactory的getObject方法.
// 真正调用getObject的地方在doGetBean中的getSingleton中
addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
}
这里Spring判断了三个条件来决定是否提前暴露早期引用的Bean.
- 是否为单例
- 是否允许循环引用
- 是否在创建中的bean.
如果条件成立,那么此时会往三级缓存中注册一个lambda代码块,该代码块其实是实现
ObjectFactory
中的getObject
方法,getEarlyBeanReference
方法会判断是否需要对Bean进行增强,然后返回早期的bean引用。注意,注册代码块,而不是调用。也就是说这里只是注册一个回调的方法,真正回调的地方其实在前面已经讲过的doGetBean
中的getSingleton
中.熟悉函数式编程的朋友应该可以理解.
- DefaultSingletonBeanRegistry#addSingletonFactory
注意一个细节,三级缓存中,同一个Bean只会存在唯一一份引用.
也就是说,如果这个引用在三级缓存中,一级、二级缓存就不会存在这份引用.
protected void addSingletonFactory(String beanName, ObjectFactory<?> singletonFactory) {
Assert.notNull(singletonFactory, "Singleton factory must not be null");
synchronized (this.singletonObjects) {
if (!this.singletonObjects.containsKey(beanName)) {
// 往三级缓存中添加
this.singletonFactories.put(beanName, singletonFactory);
// 从二级缓存中移除
this.earlySingletonObjects.remove(beanName);
// 记录注册单例的顺序
this.registeredSingletons.add(beanName);
}
}
}
4. 填充Bean实例的属性-populateBean
一个重量级方法,经过populateBean处理过后的bean即为完备的bean了。
什么是完备的Bean?
例如HelloController
声明了@AutoWired
需要注入HelloService
依赖,那么执行完populateBean
就会将HelloService
这个Bean注入到HelloController
中,此时拥有了完整的依赖的HelloController
便为一个完备的Bean.
这里留个坑位,以后再补充populateBean
的逻辑.
5. 生命周期函数回调-initializeBean
这里也是一个重量级方法,关于Spring的生命周期回调函数这里简单介绍一下:
- 激活部分的Aware接口:BeanNameAware、BeanClassLoaderAware、BeanFactoryAware.
- 激活BeanPostProcessor的postProcessBeforeInitialization方法.
- 激活InitializingBean的afterPropertiesSet方法、
@Bean
时指定的initMethod.- 激活BeanPostProcessor的postProcessAfterInitialization方法
下面贴出源码作为佐证.
5.1 initializeBean入口-doCreateBean
try {
// 填充bean实例属性
populateBean(beanName, mbd, instanceWrapper);
// 初始化bean,过程:
// 1. 判断是否实现了BeanNameAware、BeanClassLoaderAware、BeanFactoryAware.
// 如果有,将相关属性进行传递.
// 2. 调用BeanPostProcessor的前置操作:例如->@PostConstruct
// 3. 调用bean初始化的前置操作,即生命周期回调函数.
// 实现InitializingBean#afterPropertiesSet、具有依赖注入的自定义方法
// 4. 调用BeanPostProcessor的后置操作
exposedObject = initializeBean(beanName, exposedObject, mbd);
}
5.2 AbstractAutowireCapableBeanFactory#initializeBean
protected Object initializeBean(String beanName, Object bean, @Nullable RootBeanDefinition mbd) {
if (System.getSecurityManager() != null) {
AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
invokeAwareMethods(beanName, bean);
return null;
}, getAccessControlContext());
}
else {
// 激活BeanNameAware、BeanClassLoaderAware、BeanFactoryAware
invokeAwareMethods(beanName, bean);
}
Object wrappedBean = bean;
if (mbd == null || !mbd.isSynthetic()) {
// 激活BeanPostProcessor的postProcessBeforeInitialization方法
wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
}
try {
// 激活InitializingBean的afterPropertiesSet方法、initMethod
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;
}
关于BeanPostProcessor,在我前面的文章中已经介绍过了.
这里我们来关注几个平时可能会用到的Lifecycle Callback
:
- @PostConstruct.
- InitializingBean#afterPropertiesSet.
- initMethod.
执行顺序为:1->2->3
Spring官方推荐使用@PostConstruct
注解的方式来触发生命周期回调.
下面推荐两个链接,希望深入的朋友可以点击前往:
Spring官网关于生命周期回调的说明.
执行解析@PostConstruct.
6. 检测循环依赖,防止Bean出现不一样的引用.
// 如果容器允许循环依赖,则进行相应处理
if (earlySingletonExposure) {
// 获取指定名称的已注册单例Bean对象.
Object earlySingletonReference = getSingleton(beanName, false);
if (earlySingletonReference != null) {
// 如果经过initializeBean后获取到的Bean还是同一个(没有被增强)
if (exposedObject == bean) {
// 确保byName获取到的Bean和正在实例化的Bean是同一个
exposedObject = earlySingletonReference;
}
// 如果上面的判断没通过,则表明引用的bean和注入的bean不一致
// 此时有两个判断条件:
// 1. 在循环引用的情况下是否要求注入原始bean实例,即使注入的bean最终被增强(AOP处理)也是如此.
// 意思就是说,只认原始类型,如果在initializeBean中对bean进行了替换,Spring会认为是异常.
// 2. 当前是否触发了循环依赖: dependentBeanMap记录着每个依赖于此Bean的Bean实例集合
// 当发生循环依赖的时候不允许新创建实例对象
else if (!this.allowRawInjectionDespiteWrapping && hasDependentBean(beanName)) {
String[] dependentBeans = getDependentBeans(beanName);
Set<String> actualDependentBeans = new LinkedHashSet<>(dependentBeans.length);
// 获取依赖于当前bean的bean实例
for (String dependentBean : dependentBeans) {
// 移除掉只是用来进行类型检查的单例bean
if (!removeSingletonIfCreatedForTypeCheckOnly(dependentBean)) {
actualDependentBeans.add(dependentBean);
}
}
// 因为bean创建后其依赖的bean一定是已经创建的
// actualDependentBeans不为空则表示当前bean创建后其依赖的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 " +
"'getBeanNamesForType' with the 'allowEagerInit' flag turned off, for example.");
}
}
}
}
这里Spring主要是考虑Bean在钩子方法中被用户自定义的BeanPostProcessor或者某个生命周期回调中进行替换了,如此一来,之前如果有别的Bean依赖了当前创建的Bean,那么就会触发
BeanCurrentlyInCreationException
,因为引用的Bean对象不一致了.
7. 注册销毁逻辑-registerDisposableBeanIfNecessary
主要是注册实现了
DisposableBean
或者@Bean
时指定了destroyMethod
的方法,在Bean销毁时进行回调.
网友评论