Spring Bean实例化

软件发布|下载排行|最新软件

当前位置:首页IT学院IT技术

Spring Bean实例化

码农的进阶之路   2022-05-23 我要评论

前言

上一节说到了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文件

<?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;
		}

总结

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

Copyright 2022 版权所有 软件发布 访问手机版

声明:所有软件和文章来自软件开发商或者作者 如有异议 请与本站联系 联系我们