温馨提示×

温馨提示×

您好,登录后才能下订单哦!

密码登录×
登录注册×
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》

Spring Bean中Bean的实例化分析

发布时间:2022-03-04 16:09:33 来源:亿速云 阅读:202 作者:iii 栏目:开发技术

这篇文章主要介绍了Spring Bean中Bean的实例化分析的相关知识,内容详细易懂,操作简单快捷,具有一定借鉴价值,相信大家阅读完这篇Spring Bean中Bean的实例化分析文章都会有所收获,下面我们一起来看看吧。

实例化前阶段

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文件

<?xml version="1.0" encoding="UTF-8"?> <beans         xmlns="http://www.springframework.org/schema/beans"         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"         xsi:schemaLocation="http://www.springframework.org/schema/beans         https://www.springframework.org/schema/beans/spring-beans.xsd">     <bean id="peopleFactory" class="com.wojiushiwo.factorymethod.PeopleFactory"/>     <!--实例方法-->     <bean id="instanceMethod" factory-bean="peopleFactory" factory-method="createPeople"/>	<!--静态方法-->     <bean id="staticFactoryMethod" class="com.wojiushiwo.factorymethod.People" factory-method="createPeople"/> </beans>
//实体对象 @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<Method> candidateList = new ArrayList<>();	for (Method candidate : rawCandidates) {         //如果方法修饰符包含static,并且方法名称是配置的FactoryMethod,则添加到候选集合中	if (Modifier.isStatic(candidate.getModifiers()) == isStatic && mbd.isFactoryMethod(candidate)) {	candidateList.add(candidate);	}	}	  //如果候选集合有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<Method> 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);	}	else {	minNrOfArgs = 0;	}	}	LinkedList<UnsatisfiedDependencyException> 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<String> argTypes = new ArrayList<>(minNrOfArgs);	if (explicitArgs != null) {	for (Object arg : explicitArgs) {	argTypes.add(arg != null ? arg.getClass().getSimpleName() : "null");	}	}	else if (resolvedValues != null) {	Set<ValueHolder> valueHolders = new LinkedHashSet<>(resolvedValues.getArgumentCount());	valueHolders.addAll(resolvedValues.getIndexedArgumentValues().values());	valueHolders.addAll(resolvedValues.getGenericArgumentValues());	for (ValueHolder value : valueHolders) {	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;	}

关于“Spring Bean中Bean的实例化分析”这篇文章的内容就介绍到这里,感谢各位的阅读!相信大家对“Spring Bean中Bean的实例化分析”知识都有一定的了解,大家如果还想学习更多知识,欢迎关注亿速云行业资讯频道。

向AI问一下细节

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

AI