Spring Bean学习总结
BeanDefinition:定义 Bean的作用范围、角色、依赖、懒加载等与 Spring容器运行和管理Bean息息相关的属性,以达到对Bean的Spring特性的定制,是Spring Bean描述定义信息的核心接口类。
1、Bean的注册
在使用Spring时,我们可以通过获取一个应用上下文(ApplicationContext)对象来操作各种Bean。如果使用基于注解的配置方式,可以使用AnnotationConfigApplicationContext来初始化容器上下文对象。
AnnotationConfigApplicationContext主要构造方法:
public AnnotationConfigApplicationContext(Class<?>... componentClasses) {
this();
//根据java配置类注册bean
register(componentClasses);
refresh();
}
public AnnotationConfigApplicationContext(String... basePackages) {
this();
//根据包路径扫描
scan(basePackages);
refresh();
}
以register()方法为例进行讨论:
@Override
public void register(Class<?>... componentClasses) {
Assert.notEmpty(componentClasses, "At least one component class must be specified");
this.reader.register(componentClasses);
}
在方法内使用了AnnotatedBeanDefinitionReader工具类来完成bean的注册。在this.reader.register()方法中,遍历所有传入的componentClasses注解类,然后通过registerBean()完成注册。
public void register(Class<?>... componentClasses) {
for (Class<?> componentClass : componentClasses) {
registerBean(componentClass);
}
}
public void registerBean(Class<?> beanClass) {
doRegisterBean(beanClass, null, null, null, null);
}
registerBean方法内继续调用doRegisterBean:
private <T> void doRegisterBean(Class<T> beanClass, @Nullable String name,
@Nullable Class<? extends Annotation>[] qualifiers, @Nullable Supplier<T> supplier,
@Nullable BeanDefinitionCustomizer[] customizers) {
//将注解类转换成一个BeanDefinition
AnnotatedGenericBeanDefinition abd = new AnnotatedGenericBeanDefinition(beanClass);
//...
//获取Bean的作用域元数据,解析Bean作用域
ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(abd);
//将Bean作用域写回BeanDefinition
abd.setScope(scopeMetadata.getScopeName());
//生成beanName
String beanName = (name != null ? name : this.beanNameGenerator.generateBeanName(abd, this.registry));
//解析@Lazy、@Primary等注解
AnnotationConfigUtils.processCommonDefinitionAnnotations(abd);
if (qualifiers != null) {
for (Class<? extends Annotation> qualifier : qualifiers) {
if (Primary.class == qualifier) {
abd.setPrimary(true);
}
else if (Lazy.class == qualifier) {
abd.setLazyInit(true);
}
else {
abd.addQualifier(new AutowireCandidateQualifier(qualifier));
}
}
}
//...
//注册Bean的定义
BeanDefinitionReaderUtils.registerBeanDefinition(definitionHolder, this.registry);
}
最后,通过registerBeanDefinition()方法完成Bean的注册,该方法内部通过ListableBeanFactory的实现类DefaultListableBeanFactory将Bean定义信息注册到Spring IoC容器中。
基本流程:
graph LR;
A[构建BeanDefinition]-->B[设置BeanDefinition属性]
B-->C[注册BeanDefinition]
2、Bean的运行实现
将Bean的定义加载到了容器中后,还需要调用refresh()方法刷新容器。这里只关注finishBeanFactoryInitialization方法
public void refresh() throws BeansException, IllegalStateException {
try {
//...
// 初始化所有的单例Bean
finishBeanFactoryInitialization(beanFactory);
//...
}
}
}
}
finishBeanFactoryInitialization()方法才是真正的完成Bean实例化的入口。在这个方法中,完成Bean的实例化代码实际上位于它的子类DefaultListableBeanFactory中:
public void preInstantiateSingletons() throws BeansException {
List<String> beanNames = new ArrayList<>(this.beanDefinitionNames);
//触发所有非懒加载的单例Bean的初始化操作
for (String beanName : beanNames) {
//...
getBean(beanName);
//...
}
}
进入到getBean()方法,一路跟踪源码到doCreateBean方法:
protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final @Nullable Object[] args)
throws BeanCreationException {
//1. 实例化Bean
instanceWrapper = createBeanInstance(beanName, mbd, args);
//2. 属性注入
populateBean(beanName, mbd, instanceWrapper);
//3. 初始化Bean
exposedObject = initializeBean(beanName, exposedObject, mbd);
//...
return exposedObject;
}
该方法包含三个核心方法:
-
createBeanInstance():实例化,通过构造方法反射创建一个bean实例对象,实例化所得到的对象,是“不完整”的对象;
-
populateBean():属性填充,实现属性的自动注入,包含byName、byType类型的自动装配,以及基于@Autowired、@Value注解的属性设值。执行完这一步之后,可以说Bean已经是完整的了。
-
initializeBean():初始化,在属性填充之后,执行Aware扩展以及Bean后处理器和init初始化方法等。
单例对象的初始化步骤:
graph LR;
A[createBeanInstance:实例化]-->B[populateBean:属性填充]
B-->C[initializeBean:初始化]
3、创建Bean
Spring为开发人员提供了三种不同的依赖注入类型,分别是字段注入、构造器注入和Setter方法注入。但是它们的注入顺序不一致,因为Spring在实例化Bean时要先找到合适的构造方法,并准备构造方法的参数等数据,再进行实例化。在实例化后产生对象时才能对当前对象的属性进行装载注入(如反射调用方法、为属性赋值等);
查看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());
}
// 1、如果提供了Supplier,通过Supplier产生对象
Supplier<?> instanceSupplier = mbd.getInstanceSupplier();
if (instanceSupplier != null) {
return obtainFromSupplier(instanceSupplier, beanName);
}
// 2、如果有工厂方法,使用工厂方法产生对象
// 在@Configration配置@Bean的方法,也会被解析为FactoryMethod
if (mbd.getFactoryMethodName() != null) {
return instantiateUsingFactoryMethod(beanName, mbd, args);
}
// ...
// 3、推断构造方法
// 3.1 执行后置处理器,获取候选构造方法
Constructor<?>[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName);
// 3.2 需要自动注入的构造函数
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);
}
// 3.3 使用默认无参构造函数创建对象
return instantiateBean(beanName, mbd);
}
具体逻辑是:
1.先判断是否提供了Supplier,如果提供,则通过Supplier产生对象。
2.再判断是否提供工厂方法,如果提供,则使用工厂方法产生对象。
3.如果都没提供,需要进行构造方法的推断,逻辑为:
- 如果没有,Spring默认选择无参构造方法;
- 如果有,且有
@Autowired(required=true)的构造方法,就会选择该构造方法; -
- 如果有,但是没有
@Autowired(required=true)的构造方法,Spring会从所有加了@Autowired的构造方法中,根据构造器参数个数、类型匹配程度等综合打分,选择一个匹配参数最多,类型最准确的构造方法。 - 如果仅有一个构造方法,会直接使用该构造方法(
如果构造方法有参数,会自动注入依赖参数) - 如果有多个构造参数,会判断有没有加了
@Autowired注解的构造参数:
- 如果有,但是没有
4、Bean的属性注入
本阶段完成了Spring的核心功能之一:依赖注入,包括自动注入、@Autowired注入、@Resource注入等。
属性注入的前提是当前对象已经完成了实例化,这样才能注入属性,因为注入属性的前提是有真正的targetObject。
在创建 Bean 实例后调用了 populateBean 方法。属性注入就是通过populateBean方法开始的。
protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) {
//如果实例为null,并且属性值不为空,则不能注入,抛出异常;如果属性值为空,则跳出当前方法
if (bw == null) {
if (mbd.hasPropertyValues()) {
throw new BeanCreationException(
mbd.getResourceDescription(), beanName, "Cannot apply property values to null instance");
}
else {
// Skip property population phase for null instance.
return;
}
}
// 如果当前bean不是合成的bean,并且在当前工厂中注册了InstantiationAwareBeanPostProcessor后处理器,则顺序调用该类型Bean后处理器修改bean的状态,其中任意一个发生问题,则方法不再继续
if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
for (BeanPostProcessor bp : getBeanPostProcessors()) {
if (bp instanceof InstantiationAwareBeanPostProcessor) {
InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
// 实例化后执行, 这里如果返回 false 会跳过依赖注入阶段
if (!ibp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) {
return;
}
}
}
}
PropertyValues pvs = (mbd.hasPropertyValues() ? mbd.getPropertyValues() : null);
// 获取bean的注入类型
int resolvedAutowireMode = mbd.getResolvedAutowireMode();
// 只处理当前bean按类型自动注入和按名称自动注入
if (resolvedAutowireMode == AUTOWIRE_BY_NAME || resolvedAutowireMode == AUTOWIRE_BY_TYPE) {
MutablePropertyValues newPvs = new MutablePropertyValues(pvs);
//如果是按名称注入,则直接通过getBean方法获取这些bean,然后注入,添加属性信息并注册当前依赖的Bean到BeanFactory中
if (resolvedAutowireMode == AUTOWIRE_BY_NAME) {
autowireByName(beanName, mbd, bw, newPvs);
}
// 按类型获取并解决依赖,调用resolveDependency来处理,在获取对象的值后调用类型转换处理返回值,并且添加到属性信息
if (resolvedAutowireMode == AUTOWIRE_BY_TYPE) {
autowireByType(beanName, mbd, bw, newPvs);
}
pvs = newPvs;
}
boolean hasInstAwareBpps = hasInstantiationAwareBeanPostProcessors();
boolean needsDepCheck = (mbd.getDependencyCheck() != AbstractBeanDefinition.DEPENDENCY_CHECK_NONE);
PropertyDescriptor[] filteredPds = null;
if (hasInstAwareBpps) {
if (pvs == null) {
pvs = mbd.getPropertyValues();
}
//调用bean后处理器的postProcessProperties方法,用来解析@Autowired、@Value、@Resource等注解注入属性
for (BeanPostProcessor bp : getBeanPostProcessors()) {
if (bp instanceof InstantiationAwareBeanPostProcessor) {
InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
PropertyValues pvsToUse = ibp.postProcessProperties(pvs, bw.getWrappedInstance(), beanName);
if (pvsToUse == null) {
if (filteredPds == null) {
filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
}
pvsToUse = ibp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName);
if (pvsToUse == null) {
return;
}
}
pvs = pvsToUse;
}
}
}
if (needsDepCheck) {
if (filteredPds == null) {
filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
}
checkDependencies(beanName, mbd, filteredPds, pvs);
}
if (pvs != null) {
//解析转换所有属性信息,为这个bean实例装入所有属性
applyPropertyValues(beanName, mbd, bw, pvs);
}
}
5、Bean的初始化
该阶段主要做bean的初始化操作,包括:回调Aware接口、回调初始化方法、生成代理对象等。
查看initializeBean方法:
protected Object initializeBean(String beanName, Object bean, @Nullable RootBeanDefinition mbd) {
// 1、回调Aware接口的实现方法,注入BeanName、ClassLoader和BeanFactory
if (System.getSecurityManager() != null) {
AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
invokeAwareMethods(beanName, bean);
return null;
}, getAccessControlContext());
}
else {
invokeAwareMethods(beanName, bean);
}
Object wrappedBean = bean;
//2、调用Bean后处理器,初始化之前执行, 这里返回的对象会替换掉原本的 bean, 如 @PostConstruct、@ConfigurationProperties
if (mbd == null || !mbd.isSynthetic()) {
wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
}
//3、调用初始化方法
try {
invokeInitMethods(beanName, wrappedBean, mbd);
}
catch (Throwable ex) {
throw new BeanCreationException(
(mbd != null ? mbd.getResourceDescription() : null),
beanName, "Invocation of init method failed", ex);
}
//4、调用Bean后处理器,初始化之后执行, 这里返回的对象会替换掉原本的 bean, 如代理增强
if (mbd == null || !mbd.isSynthetic()) {
wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
}
return wrappedBean;
}
查看invokeInitMethods方法:
protected void invokeInitMethods(String beanName, Object bean, @Nullable RootBeanDefinition mbd)
throws Throwable {
//1. 调用InitializingBean的afterPropertiesSet方法
boolean isInitializingBean = (bean instanceof InitializingBean);
if (isInitializingBean && (mbd == null || !mbd.isExternallyManagedInitMethod("afterPropertiesSet"))) {
if (logger.isTraceEnabled()) {
logger.trace("Invoking afterPropertiesSet() on bean with name '" + beanName + "'");
}
if (System.getSecurityManager() != null) {
try {
AccessController.doPrivileged((PrivilegedExceptionAction<Object>) () -> {
((InitializingBean) bean).afterPropertiesSet();
return null;
}, getAccessControlContext());
}
catch (PrivilegedActionException pae) {
throw pae.getException();
}
}
else {
((InitializingBean) bean).afterPropertiesSet();
}
}
//2. 调用自定义初始化方法
if (mbd != null && bean.getClass() != NullBean.class) {
String initMethodName = mbd.getInitMethodName();
if (StringUtils.hasLength(initMethodName) &&
!(isInitializingBean && "afterPropertiesSet".equals(initMethodName)) &&
!mbd.isExternallyManagedInitMethod(initMethodName)) {
invokeCustomInitMethod(beanName, bean, mbd);
}
}
}
由源码分析可知,构造函数 > @PostConstruct > InitializingBean > 自定义init-method
在初始化完成后,bean会被放到单例池中,后续有使用到该bean的地方,直接从单例池中获取,不会再次创建bean(仅单例)。
6、Bean的销毁
回doGetBean方法,在方法的最后:
protected Object doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
throws BeanCreationException {
//...
// Register bean as disposable.
try {
registerDisposableBeanIfNecessary(beanName, bean, mbd);
}
catch (BeanDefinitionValidationException ex) {
throw new BeanCreationException(
mbd.getResourceDescription(), beanName, "Invalid destruction signature", ex);
}
return exposedObject;
}
在创建bean的时候,会判断如果bean是DisposableBean、AutoCloseable的子类,或者有 destroy-method等,会注册为可销毁的bean,在容器关闭时,调用对应的方法进行bean的销毁。