SpringIOC的加载过程
1、首先通过BeanDefinitionReader读取配置文件,得到完成的Bean定义对象BeanDefinition对象,此时只是得到Bean的相关定义信息,还没有开始实例化Bean
2、上图中可以看出,当实现BeanFactoryPostProcessor时,可以对BeanDefination对象进行增强操作,并且当多个类实现接口时,可以重复进行增强,如下图所示
3、得到完成的BeanDefinition后就可以创建Bean对象了,包括从实例化->mergeBeanDefinition -> 属性填充 -> 初始化 -> 使用 -> 销毁一系列操作
SpringBean的生命周期
SpringBean的生命周期大致分为:实例化bean->属性填充->初始化bean->使用->销毁几个阶段,如下图所示
实例化
在实例化过程中,通过实现InstantiationAwareBeanPostProcessor接口,可以对准备进行实例化的Bean进行前置、后置和属性处理,对应实现接口如下:
/**
* @author Aaron
* @date 2023.03.10
*/
@Component
@Slf4j
public class BeanInstantiationDemo implements InstantiationAwareBeanPostProcessor {
@Override
public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
log.warn("------BeforeInstantiation处理,此时Bean还未创建,需要拿到Class和beanName通过反射(大部分)创建对象\n当前beanClass为:{}\nbeanName为:{}\n------",beanClass,beanName);
return InstantiationAwareBeanPostProcessor.super.postProcessBeforeInstantiation(beanClass, beanName);
}
@Override
public boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException {
log.warn("------AfterInstantiation处理,此时Bean已经被创建,所以可以那到当前Bean的信息------\n当前Bean为:{}\nbeanName为:{}",bean,beanName);
return InstantiationAwareBeanPostProcessor.super.postProcessAfterInstantiation(bean, beanName);
}
@Override
public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) throws BeansException {
log.warn("对Bean属性值的设置:{}",pvs );
return InstantiationAwareBeanPostProcessor.super.postProcessProperties(pvs, bean, beanName);
}
}
启动时打印日志如下:
从图中也可以看出,对BeanDefinition的增强在实例化前,而且对实例化的增强打印了多次,这是因为初始化的前置方法和后置方法是为所有 Bean 服务的,而非为某一个 Bean 服务的
Bean的实例化本质上就是选择构造函数然后使用反射创建对象,Bean创建时选择构造函数的代码在AbstractAutowireCapableBeanFactory.java#createBeanInstance中,具体代码如下:
protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) {
// 再次解析BeanDefinition中的class,确保class已经被解析
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,如果提供,则使用Supplier进行实例化对象
Supplier<?> instanceSupplier = mbd.getInstanceSupplier();
if (instanceSupplier != null) {
return obtainFromSupplier(instanceSupplier, beanName);
}
// 是否提供了,工厂方法,如果提供,则使用工厂方法产生对象
// 在configuration中标注@Bean的代码也会在此处被解析为FactoryMethod
if (mbd.getFactoryMethodName() != null) {
return instantiateUsingFactoryMethod(beanName, mbd, args);
}
// 创建相同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);
}
}
// 此处开始推断需要创建对象时的构造方法
// 执行后置处理器,获取Bean的候选构造方法
Constructor<?>[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName);
// 需要自动注入的情况
if (ctors != null || mbd.getResolvedAutowireMode() == AUTOWIRE_CONSTRUCTOR ||
mbd.hasConstructorArgumentValues() || !ObjectUtils.isEmpty(args)) {
return autowireConstructor(beanName, mbd, ctors, args);
}
// 首选的默认构造方法
ctors = mbd.getPreferredConstructors();
if (ctors != null) {
return autowireConstructor(beanName, mbd, ctors, null);
}
// 默认使用无参的构造方法
return instantiateBean(beanName, mbd);
}
经过查看,可以发现Spring推断构造函数的逻辑如下:
- 先判断是否提供Supplier,如果有则使用Supplier进行生产
最终调用实例化的代码如下:
public static <T> T instantiateClass(Constructor<T> ctor, Object... args) throws BeanInstantiationException {
Assert.notNull(ctor, "Constructor must not be null");
try {
ReflectionUtils.makeAccessible(ctor);
// 判断如果不是Kotlin类型则使用构造器的newInstance方法创建对象
return (KotlinDetector.isKotlinReflectPresent() && KotlinDetector.isKotlinType(ctor.getDeclaringClass()) ?
KotlinDelegate.instantiateClass(ctor, args) : ctor.newInstance(args));
}
catch (InstantiationException ex) {
throw new BeanInstantiationException(ctor, "Is it an abstract class?", ex);
}
catch (IllegalAccessException ex) {
throw new BeanInstantiationException(ctor, "Is the constructor accessible?", ex);
}
catch (IllegalArgumentException ex) {
throw new BeanInstantiationException(ctor, "Illegal arguments for constructor", ex);
}
catch (InvocationTargetException ex) {
throw new BeanInstantiationException(ctor, "Constructor threw exception", ex.getTargetException());
}
}