Spring Bean生命周期之Bean的实例化详解

网友投稿 307 2022-08-23


Spring Bean生命周期之Bean的实例化详解

目录前言实例化前阶段实例化阶段实例化后阶段总结

前言

上一节说到了BeanDefinition的合并过程,这节该说Bean的实例化过程了。根据AbstractAutowireCapableBeanFactory#createBean源码逻辑 可将实例化过程分为实例化前阶段、实例化过程、实例化后阶段。

实例化前阶段

protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)

throws BeanCreationException {

//省略无关代码

try {

// 这里就是我们分析的重点了 ⭐️

Object bean = resolveBeforeInstantiation(beanName, mbdToUse);

//⭐️ 注意这个逻辑:如果postProcessBeforeInstantiation方法返回非null 则将返回值作为创建的Bean。并中断正常的创建流程

if (bean != null) {

return bean;

}

}

catch (Throwable ex) {

//省略异常信息

}

try {

//真正创建Bean的逻辑 实例化Bean对象,为Bean属性赋值等,这里暂不展开

Object beanInstance = doCreateBean(beanName, mbdToUse, args);

//省略日志输出

return beanInstance;

}

catch (BeanCreationException | ImplicitlyAppearedSingletonException ex) {//省略异常信息

}

resolveBeforeInstantiation这个方法在BeanPostProcessor浅析 这一节分析过了 这里不再具体展开了。

如果InstantiationAwareBeanPostProcessor#postProcessBeforeInstantiation 方法返回null,那么将不会中断正常Bean创建过程。下面就来到的Bean实例化部分了。

实例化阶段

protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) {

//解析BeanClass,在BeanDefinition中类信息是以字符串形式展现,这里解析到字符串后 会将其加载为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#get得到实例化对象

Supplier> instanceSupplier = mbd.getInstanceSupplier();

if (instanceSupplier != null) {

return obtainFromSupplier(instanceSupplier, beanName);

}

//如果工厂方法不为空,则使用工厂方法初始化

if (mbd.getFactoryMethodName() != null) {

return instantiateUsingFactoryMethod(beanName, mbd, args);

}

boolean resolved = false;

boolean autowireNecessary = false;

if (args == null) {

//加锁

synchronized (mbd.constructorArgumentLock) {

//条件成立 说明构造函数或FactoryMethod已经被解析并被缓存,可直接利用构造函数解析

//与后面的SimpleInstantiationStrategy#instantiate呼应

if (mbd.resolvedConstructorOrFactoryMethod != null) {

resolved = true;

autowireNecessary = mbd.constructorArgumentsResolved;

}

}

}

//如果已经被解析过

if (resolved) {

//条件成立 使用构造函数注入

if (autowireNecessary) {

return autowireConstructor(beanName, mbd, null, null);

}

else {

//使用默认构造函数解析

return instantiateBean(beanName, mbd);

}

}

// 使用SmartInstantiationAwareBeanPostProcessor 找到候选的构造函数 用于注入

Constructor>[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName);

// AutowireMode==AUTOWIRE_CONSTRUCTOR 条件成立 说明使用基于构造函数的注入方式 (默认是AUTOWIRE_NO,需要动态检测)

// mbd.hasConstructorArgumentValues() 条件成立 说明构造函数中拥有参数

if (ctors != null || mbd.getResolvedAutowireMode() == AUTOWIRE_CONSTRUCTOR ||

mbd.hasConstructorArgumentValues() || !ObjectUtils.isEmpty(args)) {

//基于构造函数自动注入

return autowireConstructor(beanName, mbd, ctors, args);

}

// 如果mbd中配置了构造函数 则使用它进行注入

ctors = mbd.getPreferredConstructors();

if (ctors != null) {

return autowireConstructor(beanName, mbd, ctors, null);

}

// 使用默认构造函数实例化

return instantiateBean(beanName, mbd);

}

上面将doCreateBean精简一下,只暴露出我们比较关系的部分。一目了然,Bean的实例化过程就藏在createBeanInstance方法中。

protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) {

//解析BeanClass,在BeanDefinition中类信息是以字符串形式展现,这里解析到字符串后 会将其加载为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#get得到实例化对象

Supplier> instanceSupplier = mbd.getInstanceSupplier();

if (instanceSupplier != null) {

return obtainFromSupplier(instanceSupplier, beanName);

}

//如果工厂方法不为空,则使用工厂方法初始化

if (mbd.getFactoryMethodName() != null) {

return instantiateUsingFactoryMethod(beanName, mbd, args);

}

boolean resolved = false;

boolean autowireNecessary = false;

if (args == null) {

//加锁

synchronized (mbd.constructorArgumentLock) {

//条件成立 说明构造函数或FactoryMethod已经被解析并被缓存,可直接利用构造函数解析

//与后面的SimpleInstantiationStrategy#instantiate呼应

if (mbd.resolvedConstructorOrFactoryMethod != null) {

resolved = true;

autowireNecessary = mbd.constructorArgumentsResolved;

}

}

}

//如果已经被解析过

if (resolved) {

//条件成立 使用构造函数注入

if (autowireNecessary) {

return autowireConstructor(beanName, mbd, null, null);

}

else {

//使用默认构造函数解析

return instantiateBean(beanName, mbd);

}

}

// 使用SmartInstantiationAwareBeanPostProcessor 找到候选的构造函数 用于注入

Constructor>[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName);

// AutowireMode==AUTOWIRE_CONSTRUCTOR 条件成立 说明使用基于构造函数的注入方式 (默认是AUTOWIRE_NO,需要动态检测)

// mbd.hasConstructorArgumentValues() 条件成立 说明构造函数中拥有参数

if (ctors != null || mbd.getResolvedAutowireMode() == AUTOWIRE_CONSTRUCTOR ||

mbd.hasConstructorArgumentValues() || !ObjectUtils.isEmpty(args)) {

//基于构造函数自动注入

return autowireConstructor(beanName, mbd, ctors, args);

}

// 如果mbd中配置了构造函数 则使用它进行注入

ctors = mbd.getPreferredConstructors();

if (ctors != null) {

return autowireConstructor(beanName, mbd, ctors, null);

}

// 使用默认构造函数实例化

return instantiateBean(beanName, mbd);

}

分析了上面的源码之后,我们试着总结一下上面代码主要完成的事情:

1、如果mbd配置了instanceSupplier回调,则使用instanceSupplier去初始化BeanDefinition

2、如果mbd配置了工厂方法,则使用工厂方法区初始化BeanDefinition

3、实例化BeanDefinition

如果mbd已经被解析过了,则根据缓存 选择使用有参构造函数注入还是默认构造函数注入如果mbd没有被解析过,找到mbd中候选的构造函数(一个类可能有多个构造函数),再根据一些限定条件 选择是基于有参构造函数初始化还是默认构造函数初始化

针对第1点,其实就是lambda8 supplier接口的使用,不再介绍。

针对第3点,其实就是通过反射机制 创建实例对象,最终调用了SimpleInstantiationStrategy#instantiate方法

针对第2点 举例说明下 工厂方法与静态工厂生成Bean的两种形式,再来展开说下instantiateUsingFactoryMethod源码。

配置Xml文件

xmlns="http://springframework.org/schema/beans"

xmlns:xsi="http://w3.org/2001/XMLSchema-instance"

xsi:schemaLocation="http://springframework.org/schema/beans

https://springframework.org/schema/beans/spring-beans.xsd">

xmlns="http://springframework.org/schema/beans"

xmlns:xsi="http://w3.org/2001/XMLSchema-instance"

xsi:schemaLocation="http://springframework.org/schema/beans

https://springframework.org/schema/beans/spring-beans.xsd">

//实体对象

@Data

public class People implements Serializable {

private String name;

private Integer age;

public People() {

}

public static People createPeople() {

People people = new People();

people.setAge(18);

people.setName("我就是我");

return people;

}

}

//People工厂类

public class PeopleFactory {

public People createPeople() {

return People.createPeople();

}

}

public class FactoryMethodDemo {

public static void main(String[] args) {

ClassPathXmlApplicationContext context=new ClassPathXmlApplicationContext("META-INF/spring.xml");

context.refresh();

People people = (People) context.getBean("staticFactoryMethod");

System.out.println(people);

People people = (People) context.getBean("instanceMethod");

System.out.println(people);

context.close();

}

}

public BeanWrapper instantiateUsingFactoryMethod(

String beanName, RootBeanDefinition mbd, @Nullable Object[] explicitArgs) {

BeanWrapperImpl bw = new BeanWrapperImpl();

this.beanFactory.initBeanWrapper(bw);

Object factoryBean;

Class> factoryClass;

boolean isStatic;

//获取FactoryBeanName,实例方法与静态工厂方法的区别就在于有没有FactoryBeanName

String factoryBeanName = mbd.getFactoryBeanName();

if (factoryBeanName != null) {

//如果存在FactoryBeanName,则说明是实例方法

if (factoryBeanName.equals(beanName)) {

throw new BeanDefinitionStoreException(mbd.getResourceDescription(), beanName,

"factory-bean reference points back to the same bean definition");

}

//获取当前factoryBeanName名称的Bean

factoryBean = this.beanFactory.getBean(factoryBeanName);

if (mbd.isSingleton() && this.beanFactory.containsSingleton(beanName)) {

throw new ImplicitlyAppearedSingletonException();

}

//获取工厂类Class

factoryClass = factoryBean.getClass();

//标记为非静态

isStatic = false;

}

else {

// 走到这里,说明是静态工厂方法

if (!mbd.hasBeanClass()) {

throw new BeanDefinitionStoreException(mbd.getResourceDescription(), beanName,

"bean definition declares neither a bean class nor a factory-bean reference");

}

//factoryBean设置为null

factoryBean = null;

//获取工厂类Class,这里使用BeanDefinition作为其工厂类

factoryClass = mbd.getBeanClass();

//标记为非静态

isStatic = true;

}

Method factoryMethodToUse = null;

ArgumentsHolder argsHolderToUse = null;

Object[] argsToUse = null;

//explicitArgs 这个是getBean方法传递过来的,一般为null

if (explicitArgs != null) {

argsToUse = explicitArgs;

}

else {

Object[] argsToResolve = null;

//加锁

synchronized (mbd.constructorArgumentLock) {

//获取被解析的工厂方法

factoryMethodToUse = (Method) mbd.resolvedConstructorOrFactoryMethod;

//条件成立 说明工厂方法已经被解析过了,并存到了mbd中缓存起来了

if (factoryMethodToUse != null && mbd.constructorArgumentsResolved) {

// Found a cached factory method...

argsToUse = mbd.resolvedConstructorArguments;

if (argsToUse == null) {

argsToResolve = mbd.preparedConstructorArguments;

}

}

}

if (argsToResolve != null) {

argsToUse = resolvePreparedArguments(beanName, mbd, bw, factoryMethodToUse, argsToResolve, true);

}

}

if (factoryMethodToUse == null || argsToUse == null) {

//获取工厂类

factoryClass = ClassUtils.getUserClass(factoryClass);

//获取类中的方法

Method[] rawCandidates = getCandidateMethods(factoryClass, mbd);

List candidateList = new ArrayList<>();

for (Method candidate : rawCandidates) {

//如果方法修饰符包含static,并且方法名称是配置的FactoryMethod,则添加到候选集合中

if (Modifier.isStatic(candidate.getModifiers()) == isStatic && mbd.isFactoryMethod(candidate)) {

candidateList.add(candidate);

http:// }

}

//如果候选集合有1个元素 并且BeanDefinition中未设置构造参数 (explicitArgs一般都为null )

if (candidateList.size() == 1 && explicitArgs == null && !mbd.hasConstructorArgumentValues()) {

//获取方法

Method uniqueCandidate = candidateList.get(0);

//如果方法参数为空

if (uniqueCandidate.getParameterCount() == 0) {

mbd.factoryMethodToIntrospect = uniqueCandidate;

synchronized (mbd.constructorArgumentLock) {

//将下面这些全缓存到mbd中,下次直接用(与createBeanInstance方法呼应上了)

mbd.resolvedConstructorOrFactoryMethod = uniqueCandidate;

mbd.constructorArgumentsResolved = true;

mbd.resolvedConstructorArguments = EMPTY_ARGS;

}

//实例化bd,设置到BeanWrapper中

bw.setBeanInstance(instantiate(beanName, mbd, factoryBean, uniqueCandidate, EMPTY_ARGS));

return bw;

}

}

//程序走到这里 大概率是BeanDefinition中设置了构造参数

Method[] candidates = candidateList.toArray(new Method[0]);

//按照修饰符及方法参数 进行排序

AutowireUtils.sortFactoryMethods(candidates);

ConstructorArgumentValues resolvedValues = null;

//是否构造函数注入

boolean autowiring = (mbd.getResolvedAutowireMode() == AutowireCapableBeanFactory.AUTOWIRE_CONSTRUCTOR);

int minTypeDiffWeight = Integer.MAX_VALUE;

Set ambiguousFactoryMethods = null;

//最小参数数量 默认是0

int minNrOfArgs;

if (explicitArgs != null) {

minNrOfArgs = explicitArgs.length;

}

else {

//走到这里 说明explicitArgs未被设置参数

//如果bd设置了构造参数,则从bd中解析参数

if (mbd.hasConstructorArgumentValues()) {

ConstructorArgumentValues cargs = mbd.getConstructorArgumentValues();

resolvedValues = new ConstructorArgumentValues();

//得到解析的最小参数数量

minNrOfArgs = resolveConstructorArguments(beanName, mbd, bw, cargs, resolvedValues);

http://}

else {

minNrOfArgs = 0;

}

}

LinkedList causes = null;

//下面主要是推断参数、FactoryMethod,代码比较长 就先不分析了

for (Method candidate : candidates) {

Class>[] paramTypes = candidate.getParameterTypes();

if (paramTypes.length >= minNrOfArgs) {

ArgumentsHolder argsHolder;

if (explicitArgs != null) {

// Explicit arguments given -> arguments length must match exactly.

if (paramTypes.length != explicitArgs.length) {

continue;

}

argsHolder = new ArgumentsHolder(explicitArgs);

}

else {

// Resolved constructor arguments: type conversion and/or autowiring necessary.

try {

String[] paramNames = null;

ParameterNameDiscoverer pnd = this.beanFactory.getParameterNameDiscoverer();

if (pnd != null) {

paramNames = pnd.getParameterNames(candidate);

}

argsHolder = createArgumentArray(beanName, mbd, resolvedValues, bw,

paramTypes, paramNames, candidate, autowiring, candidates.length == 1);

}

catch (UnsatisfiedDependencyException ex) {

if (logger.isTraceEnabled()) {

logger.trace("Ignoring factory method [" + candidate + "] of bean '" + beanName + "': " + ex);

}

// Swallow and try next overloaded factory method.

if (causes == null) {

causes = new LinkedList<>();

}

causes.add(ex);

continue;

}

}

int typeDiffWeight = (mbd.isLenientConstructorResolution() ?

argsHolder.getTypeDifferenceWeight(paramTypes) : argsHolder.getAssignabilityWeight(paramTypes));

// Choose this factory method if it represents the closest match.

if (typeDiffWeight < minTypeDiffWeight) {

factoryMethodToUse = candidate;

argsHolderToUse = argsHolder;

argsToUse = argsHolder.arguments;

minTypeDiffWeight = typeDiffWeight;

ambiguousFactoryMethods = null;

}

// Find out about ambiguity: In case of the same type difference weight

// for methods with the same number of parameters, collect such candidates

// and eventually raise an ambiguity exception.

// However, only perform that check in non-lenient constructor resolution mode,

// and explicitly ignore overridden methods (with the same parameter signature).

else if (factoryMethodToUse != null && typeDiffWeight == minTypeDiffWeight &&

!mbd.isLenientConstructorResolution() &&

paramTypes.length == factoryMethodToUse.getParameterCount() &&

!Arrays.equals(paramTypes, factoryMethodToUse.getParameterTypes())) {

if (ambiguousFactoryMethods == null) {

ambiguousFactoryMethods = new LinkedHashSet<>();

ambiguousFactoryMethods.add(factoryMethodToUse);

}

ambiguousFactoryMethods.add(candidate);

}

}

}

if (factoryMethodToUse == null) {

if (causes != null) {

UnsatisfiedDependencyException ex = causes.removeLast();

for (Exception cause : causes) {

this.beanFactory.onSuppressedException(cause);

}

throw ex;

}

List argTypes = new ArrayList<>(minNrOfArgs);

if (explicitArgs != null) {

for (Object arg : explicitArgs) {

argTypes.add(arg != null ? arg.getClass().getSimpleName() : "null");

}

}

else if (resolvedValues != null) {

Set valueHolders = new LinkedHashSet<>(resolvedValues.getArgumentCount());

valueHolders.addAll(resolvedValues.getIndexedArgumentValues().values());

valueHolders.addAll(resolvedValues.getGenericArgumentValues());

for (ValueHolder value : valuehttp://Holders) {

String argType = (value.getType() != null ? ClassUtils.getShortName(value.getType()) :

(value.getValue() != null ? value.getValue().getClass().getSimpleName() : "null"));

argTypes.add(argType);

}

}

String argDesc = StringUtils.collectionToCommaDelimitedString(argTypes);

//抛出异常

}

else if (void.class == factoryMethodToUse.getReturnType()) {

//抛出异常

}

else if (ambiguousFactoryMethods != null) {

//抛出异常

}

if (explicitArgs == null && argsHolderToUse != null) {

mbd.factoryMethodToIntrospect = factoryMethodToUse;

argsHolderToUse.storeCache(mbd, factoryMethodToUse);

}

}

Assert.state(argsToUse != null, "Unresolved factory method arguments");

//实例化bd 设置到BeanWrapper中

bw.setBeanInstance(instantiate(beanName, mbd, factoryBean, factoryMethodToUse, argsToUse));

return bw;

}

至此经过createBeanInstance方法 就为我们创建了一个实例对象,但是现在这个对象属性还未被赋值。

实例化后阶段

实例对象创建之后,就来到了对象属性赋值过程了,我们大致看一下populateBean方法,观察下InstantiationAwareBeanPostProcessor对属性赋值过程的影响

protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) {

//省略无关代码

boolean continueWithPropertyPopulation = true;

//条件一 synthetic默认值是false 一般都会成立

//条件二 成立的话 说明存在InstantiationAwareBeanPostProcessor

if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {

for (BeanPostProcessor bp : getBeanPostProcessors()) {

if (bp instanceof InstantiationAwareBeanPostProcessor) {

InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;

//在BeanPostProcessor浅析中分析到此方法时说过,若Bean实例化后回调不返回true 则对属性赋值过程产生影响。以下代码就是说明

if (!ibp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) {

continueWithPropertyPopulation = false;

break;

}

}

}

}

//ibp.postProcessAfterInstantiation=false时 属性赋值过程终止

if (!continueWithPropertyPopulation) {

return;

}

总结

本篇文章就到这里了,希望能够给你带来帮助,也希望您能够多多关注我们的更多内容!


版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:Scrapy学习笔记-scrapy的__main__.py和__init__.py(python中的scrapy)
下一篇:Python入门之——getopt模块(python getopt使用)
相关文章

 发表评论

暂时没有评论,来抢沙发吧~