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文件
<?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; }
总结
本篇文章就到这里了,希望能够给你带来帮助,也希望您能够多多关注脚本之家的更多内容!