本系列所有基于 Spring 5.2.2.BUILD-SNAPSHOT
版本。由于 Spring 整个体系太过于庞大,因此只会进行关键部分的源码解析。html
本篇文章主要介绍 Spring IoC 容器是怎么建立 bean
的实例。java
在上一篇Spring IoC bean 的加载中有这么一段代码:git
if (mbd.isSingleton()) { // 建立和注册单例 bean sharedInstance = getSingleton(beanName, () -> { try { // 建立 bean 实例 return createBean(beanName, mbd, args); } // 省略异常处理... }); bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd); }
若是 bean
的做用域是单例,会调用 getSingleton()
方法并传入 beanName
和 ObjectFacoty
做为参数;而 getSingleton()
方法会调用 ObjectFactory
的 getObject()
方法也就是上面代码中的 createBean()
方法,返回 bean
。github
这里的 ObjectFactory
是 bean
的延迟依赖查找接口,定义以下:spring
@FunctionalInterface public interface ObjectFactory<T> { T getObject() throws BeansException; }
只有在调用 getObject()
方法时才会真正去获取 bean
。下面咱们正式开始分析 createBean()
方法。数组
protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) throws BeanCreationException { RootBeanDefinition mbdToUse = mbd; // 将String类型的class字符串,转换为Class对象,例如在XML中配置的class属性 Class<?> resolvedClass = resolveBeanClass(mbd, beanName); if (resolvedClass != null && !mbd.hasBeanClass() && mbd.getBeanClassName() != null) { mbdToUse = new RootBeanDefinition(mbd); mbdToUse.setBeanClass(resolvedClass); } try { // 进行定义的方法覆盖 mbdToUse.prepareMethodOverrides(); } catch (BeanDefinitionValidationException ex) { throw new BeanDefinitionStoreException(mbdToUse.getResourceDescription(), beanName, "Validation of method overrides failed", ex); } try { // 若是bean的实例化前回调方法返回非null,直接返回实例,跳事后面步骤。见下文详解 Object bean = resolveBeforeInstantiation(beanName, mbdToUse); if (bean != null) { return bean; } } catch (Throwable ex) { throw new BeanCreationException(mbdToUse.getResourceDescription(), beanName, "BeanPostProcessor before instantiation of bean failed", ex); } try { // 真正去建立bean的方法 Object beanInstance = doCreateBean(beanName, mbdToUse, args); if (logger.isTraceEnabled()) { logger.trace("Finished creating instance of bean '" + beanName + "'"); } // 返回bean的实例 return beanInstance; } // 省略异常处理... }
咱们先看一下 InstantiationAwareBeanPostProcessor
接口的定义:缓存
public interface InstantiationAwareBeanPostProcessor extends BeanPostProcessor { /** * Bean 实例化前调用,返回非 {@code null} 回调事后面流程 * 返回 {@code null} 则进行 IoC 容器对 Bean 的实例化 */ @Nullable default Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException { return null; } /** * Bean 实例化以后,属性填充以前调用,返回 {@code true} 则进行默认的属性填充步骤, * 返回 {@code false} 会跳过属性填充阶段,一样也会跳过初始化阶段的生命周期方法的回调。 */ default boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException { return true; } /** * Bean 实例化后属性赋值前调用,PropertyValues 是已经封装好的设置的属性值,返回 {@code null} 继续 */ @Nullable default PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) throws BeansException { return null; } /** * 5.1 版本后已经被上面 postProcessProperties 方法所替代,功能与上面方法同样 */ @Deprecated @Nullable default PropertyValues postProcessPropertyValues(PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName) throws BeansException { return pvs; } }
上面接口继承于 BeanPostProcessor
(BeanPostProcessor
中定义了 bean
的初始化阶段生命周期回调方法,会在后续介绍)提供了三个扩展点,以下:app
bean
实例化前bean
实例化后bean
属性赋值前这也是 bean
实例化阶段的生命周期回调方法。ide
protected Object resolveBeforeInstantiation(String beanName, RootBeanDefinition mbd) { Object bean = null; // 判断bean在实例化以前是否已经解析过 if (!Boolean.FALSE.equals(mbd.beforeInstantiationResolved)) { // 若是bean是合成的 && 有实现 InstantiationAwareBeanPostProcessor 接口 if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) { // 解析bean的类型 Class<?> targetType = determineTargetType(beanName, mbd); if (targetType != null) { // 执行bean的实例化前回调 bean = applyBeanPostProcessorsBeforeInstantiation(targetType, beanName); // 若是实例化前生命周期回调方法返回的不是null if (bean != null) { // 执行bean的实例化后回调,由于会跳事后续步骤,因此只能在此处调用了 bean = applyBeanPostProcessorsAfterInitialization(bean, beanName); } } } // 若是bean不为空,则将beforeInstantiationResolved赋值为true,表明在实例化以前已经解析 mbd.beforeInstantiationResolved = (bean != null); } return bean; }
protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final @Nullable Object[] args) throws BeanCreationException { // 实例化 bean BeanWrapper instanceWrapper = null; if (mbd.isSingleton()) { // 若是bean的做用域是singleton,则须要移除未完成的FactoryBean实例的缓存 instanceWrapper = this.factoryBeanInstanceCache.remove(beanName); } if (instanceWrapper == null) { // 经过构造函数反射建立bean的实例,可是属性并未赋值,见下文详解 instanceWrapper = createBeanInstance(beanName, mbd, args); } // 获取bean的实例 final Object bean = instanceWrapper.getWrappedInstance(); // 获取bean的类型 Class<?> beanType = instanceWrapper.getWrappedClass(); if (beanType != NullBean.class) { mbd.resolvedTargetType = beanType; } synchronized (mbd.postProcessingLock) { if (!mbd.postProcessed) { try { // BeanDefinition 合并后的回调,见下文详解 applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName); } // 省略异常处理... mbd.postProcessed = true; } } // bean的做用域是单例 && 容许循环引用 && 当前bean正在建立中 boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences && isSingletonCurrentlyInCreation(beanName)); // 若是容许bean提早曝光 if (earlySingletonExposure) { // 将beanName和ObjectFactory造成的key-value对放入singletonFactories缓存中 addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean)); } Object exposedObject = bean; try { // 给 bean 的属性赋值 populateBean(beanName, mbd, instanceWrapper); // 初始化 bean exposedObject = initializeBean(beanName, exposedObject, mbd); } // 省略异常处理... // 若是容许单例bean提早暴露 if (earlySingletonExposure) { Object earlySingletonReference = getSingleton(beanName, false); // 只有在检测到循环依赖的状况下才不为空 if (earlySingletonReference != null) { // 若是exposedObject没有在初始化方法中被改变,也就是没有被加强 if (exposedObject == bean) { exposedObject = earlySingletonReference; } else if (!this.allowRawInjectionDespiteWrapping && hasDependentBean(beanName)) { String[] dependentBeans = getDependentBeans(beanName); Set<String> actualDependentBeans = new LinkedHashSet<>(dependentBeans.length); // 检测依赖 for (String dependentBean : dependentBeans) { if (!removeSingletonIfCreatedForTypeCheckOnly(dependentBean)) { actualDependentBeans.add(dependentBean); } } if (!actualDependentBeans.isEmpty()) { throw new BeanCurrentlyInCreationException(beanName, "Bean with name '" + beanName + "' has been injected into other beans [" + StringUtils.collectionToCommaDelimitedString(actualDependentBeans) + "] in its raw version as part of a circular reference, but has eventually been wrapped. This means that said other beans do not use the final version of the bean. This is often the result of over-eager type matching - consider using 'getBeanNamesOfType' with the 'allowEagerInit' flag turned off, for example."); } } } } try { // 用于注册销毁bean registerDisposableBeanIfNecessary(beanName, bean, mbd); } catch (BeanDefinitionValidationException ex) { throw new BeanCreationException( mbd.getResourceDescription(), beanName, "Invalid destruction signature", ex); } // 返回bean实例 return exposedObject; }
protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) { // 解析 bean 的类型 Class<?> beanClass = resolveBeanClass(mbd, beanName); // 判断beanClass是不是public修饰的类,而且是否容许访问非公共构造函数和方法,不是抛出异常 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()); } // Spring 5新添加的,若是存在Supplier回调,则使用给定的回调方法初始化策略。 // 可使RootBeanDefinition#setInstanceSupplier()设置 Supplier<?> instanceSupplier = mbd.getInstanceSupplier(); if (instanceSupplier != null) { return obtainFromSupplier(instanceSupplier, beanName); } // 若是设置工厂方法则使用给定的方法建立bean实例,这里分为静态工厂和实例化工厂 if (mbd.getFactoryMethodName() != null) { return instantiateUsingFactoryMethod(beanName, mbd, args); } // 快捷方式建立相同的bean // resolved: 构造函数或工厂方法是否已经解析过 boolean resolved = false; // autowireNecessary: 是否须要自动注入 (便是否须要解析构造函数) boolean autowireNecessary = false; if (args == null) { synchronized (mbd.constructorArgumentLock) { // 若是resolvedConstructorOrFactoryMethod不为空,表明构造函数或工厂方法已经解析过 if (mbd.resolvedConstructorOrFactoryMethod != null) { resolved = true; // 根据constructorArgumentsResolved判断是否须要自动注入 autowireNecessary = mbd.constructorArgumentsResolved; } } } if (resolved) { if (autowireNecessary) { // 若是构造函数或工厂方法已经解析过而且须要自动注入,则执行构造器自动注入,见下文详解 return autowireConstructor(beanName, mbd, null, null); } else { // 不然使用默认构造函数进行bean实例化,见下文详解 return instantiateBean(beanName, mbd); } } // 调用SmartInstantiationAwareBeanPostProcessor的determineCandidateConstructors()方法 // 拿到 bean 的候选构造函数 Constructor<?>[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName); // 候选构造函数不为空 || 构造函数依赖注入 || 定义了构造函数的参数值 || args不为空,则执行构造器自动注入 if (ctors != null || mbd.getResolvedAutowireMode() == AUTOWIRE_CONSTRUCTOR || mbd.hasConstructorArgumentValues() || !ObjectUtils.isEmpty(args)) { return autowireConstructor(beanName, mbd, ctors, args); } // 若是有首选的构造函数,使用该构造函数去建立bean实例 ctors = mbd.getPreferredConstructors(); if (ctors != null) { return autowireConstructor(beanName, mbd, ctors, null); } // 没有特殊处理,使用默认无参构造器实例化bean return instantiateBean(beanName, mbd); }
上面方法主要判断是使用构造函数自动注入,仍是使用默认构造函数构造。总结起来如下几种状况会使用构造函数自动注入:函数
SmartInstantiationAwareBeanPostProcessor
接口中的 determineCandidateConstructors()
方法BeanDefinition
定义了构造函数参数,如 XML 中的 <constructor-arg index="0" value="1"/>
getBean()
方法时显示指定了 args
参数上面方法中还有一个判断是否有缓存的过程,是由于一个 bean
对应的类中可能会有多个构造函数,而每一个构造函数的参数不一样,Spring 在根据参数及类型去判断最终会使用哪一个构造函数进行实例化。可是,判断的过程是个比较消耗性能的步骤,因此采用缓存机制,若是已经解析过则不须要重复解析而是直接从 RootBeanDefinition
中的属性 resolvedConstructorOrFactoryMethod
缓存的值去取,不然须要再次解析,并将解析的结果添加至 RootBeanDefinition
中的属性 resolvedConstructorOrFactoryMethod
中。
这里简单介绍一下 SmartInstantiationAwareBeanPostProcessor
这个接口,它继承于 InstantiationAwareBeanPostProcessor
,以下:
public interface SmartInstantiationAwareBeanPostProcessor extends InstantiationAwareBeanPostProcessor { /** * 预测 bean 的类型 */ @Nullable default Class<?> predictBeanType(Class<?> beanClass, String beanName) throws BeansException { return null; } /** * 选择合适的构造器,好比目标对象有多个构造器,在这里能够进行一些定制化,选择合适的构造器 */ @Nullable default Constructor<?>[] determineCandidateConstructors(Class<?> beanClass, String beanName) throws BeansException { return null; } /** * 得到提早暴露的 bean 引用,主要用于解决循环引用的问题 * 只有单例对象才会调用此方法 */ default Object getEarlyBeanReference(Object bean, String beanName) throws BeansException { return bean; } }
其实咱们熟知的 @Autowired
注解标注在构造函数上实现自动注入,也是重写了该接口的 determineCandidateConstructors()
方法实现的。
protected BeanWrapper instantiateBean(final String beanName, final RootBeanDefinition mbd) { try { Object beanInstance; final BeanFactory parent = this; // 使用指定的策略去实力化bean beanInstance = getInstantiationStrategy().instantiate(mbd, beanName, parent); // 将实例化后的bean封装成BeanWrapper后返回 BeanWrapper bw = new BeanWrapperImpl(beanInstance); initBeanWrapper(bw); return bw; } // 省略异常处理... } // SimpleInstantiationStrategy.java public Object instantiate(RootBeanDefinition bd, @Nullable String beanName, BeanFactory owner) { // 若是有须要覆盖或者动态替换的方法则固然须要使用CGLIB进行动态代理,由于能够在建立代理的同时将方法织入类中 // 可是若是没有须要动态改变的方法,为了方便直接用反射就能够了 if (!bd.hasMethodOverrides()) { Constructor<?> constructorToUse; synchronized (bd.constructorArgumentLock) { // 获取缓存的构造方法或工厂方法 constructorToUse = (Constructor<?>) bd.resolvedConstructorOrFactoryMethod; // 缓存为空 if (constructorToUse == null) { final Class<?> clazz = bd.getBeanClass(); // 若是clazz是接口,抛出异常 if (clazz.isInterface()) { throw new BeanInstantiationException(clazz, "Specified class is an interface"); } try { // 获取默认的无参构造函数 constructorToUse = clazz.getDeclaredConstructor(); // 设置缓存 bd.resolvedConstructorOrFactoryMethod = constructorToUse; } catch (Throwable ex) { throw new BeanInstantiationException(clazz, "No default constructor found", ex); } } } // 这里就是用指定的无参构造器去实例化该bean,不作具体分析了 return BeanUtils.instantiateClass(constructorToUse); } else { // 用CGLIB生成子类动态织入重写的方法 return instantiateWithMethodInjection(bd, beanName, owner); } }
protected BeanWrapper autowireConstructor(String beanName, RootBeanDefinition mbd, @Nullable Constructor<?>[] ctors, @Nullable Object[] explicitArgs) { // 寻找适合的构造器,进行实例化 return new ConstructorResolver(this).autowireConstructor(beanName, mbd, ctors, explicitArgs); } public BeanWrapper autowireConstructor(String beanName, RootBeanDefinition mbd, @Nullable Constructor<?>[] chosenCtors, @Nullable Object[] explicitArgs) { BeanWrapperImpl bw = new BeanWrapperImpl(); this.beanFactory.initBeanWrapper(bw); // 最终实例化的构造函数 Constructor<?> constructorToUse = null; // 最终用于实例化的参数Holder ArgumentsHolder argsHolderToUse = null; // 最终用于实例化的构造函数参数 Object[] argsToUse = null; // 若是explicitArgs不为空,则使用explicitArgs当作构造器函数参数 if (explicitArgs != null) { argsToUse = explicitArgs; } else { Object[] argsToResolve = null; synchronized (mbd.constructorArgumentLock) { // 获取已经缓存的构造函数或工厂方法 constructorToUse = (Constructor<?>) mbd.resolvedConstructorOrFactoryMethod; if (constructorToUse != null && mbd.constructorArgumentsResolved) { // 获取已经缓存的构造函数参数 argsToUse = mbd.resolvedConstructorArguments; if (argsToUse == null) { // 若是已经缓存了构造函数或工厂方法, // 那么resolvedConstructorArguments和preparedConstructorArguments一定有一个缓存了构造函数参数 argsToResolve = mbd.preparedConstructorArguments; } } } if (argsToResolve != null) { // 若是argsToResolve不为空,则对构造函数参数进行解析,也就是会进行类型转换之类的操做 // 例如 A(int,int),把配置中的 ("1","1") 转换为 (1,1) argsToUse = resolvePreparedArguments(beanName, mbd, bw, constructorToUse, argsToResolve, true); } } // 若是没有缓存构造函数或者其参数 if (constructorToUse == null || argsToUse == null) { Constructor<?>[] candidates = chosenCtors; if (candidates == null) { Class<?> beanClass = mbd.getBeanClass(); try { // 若是容许访问非public的构造函数和方法(该值默认为 true),就获取全部构造函数,不然只获取public修饰的构造函数 candidates = (mbd.isNonPublicAccessAllowed() ? beanClass.getDeclaredConstructors() : beanClass.getConstructors()); } catch (Throwable ex) { throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Resolution of declared constructors on bean Class [" + beanClass.getName() + "] from ClassLoader [" + beanClass.getClassLoader() + "] failed", ex); } } // 若是只有一个构造函数 && getBean()没有显示指定args && 没有定义构造函数的参数值 if (candidates.length == 1 && explicitArgs == null && !mbd.hasConstructorArgumentValues()) { // 获取构造函数 Constructor<?> uniqueCandidate = candidates[0]; if (uniqueCandidate.getParameterCount() == 0) { synchronized (mbd.constructorArgumentLock) { // 设置构造函数和参数的缓存 mbd.resolvedConstructorOrFactoryMethod = uniqueCandidate; mbd.constructorArgumentsResolved = true; mbd.resolvedConstructorArguments = EMPTY_ARGS; } // 经过无参构造函数建立bean的实例,而后直接返回 bw.setBeanInstance(instantiate(beanName, mbd, uniqueCandidate, EMPTY_ARGS)); return bw; } } // 若是候选构造函数不为空 || 构造函数自动注入模式 boolean autowiring = (chosenCtors != null || mbd.getResolvedAutowireMode() == AutowireCapableBeanFactory.AUTOWIRE_CONSTRUCTOR); ConstructorArgumentValues resolvedValues = null; int minNrOfArgs; // getBean()显示指定了参数,获取参数长度 if (explicitArgs != null) { minNrOfArgs = explicitArgs.length; } else { // 获取定义的构造函数参数 ConstructorArgumentValues cargs = mbd.getConstructorArgumentValues(); resolvedValues = new ConstructorArgumentValues(); // 解析构造函数参数并赋值到resolvedValues,返回参数个数。见下文详解 minNrOfArgs = resolveConstructorArguments(beanName, mbd, bw, cargs, resolvedValues); } // 这里对构造函数进行排序,规则是首先是public构造函数且参数个数从多到少,而后是非public构造函数且参数个数有多到少 AutowireUtils.sortConstructors(candidates); // 最小匹配权重,权重越小,越接近咱们要找的目标构造函数 int minTypeDiffWeight = Integer.MAX_VALUE; Set<Constructor<?>> ambiguousConstructors = null; LinkedList<UnsatisfiedDependencyException> causes = null; // 遍历构造函数,找出符合的构造函数 for (Constructor<?> candidate : candidates) { // 获取参数数量 int parameterCount = candidate.getParameterCount(); // 若是已经找到知足的构造函数 && 目标构造函数参数个数大于当前遍历的构造函数参数个数则终止 // 由于构造函数已是排过序的,后面不会再有更适合的了 if (constructorToUse != null && argsToUse != null && argsToUse.length > parameterCount) { break; } // 若是目标的构造函数参数个数小于咱们须要的,直接跳过 if (parameterCount < minNrOfArgs) { continue; } ArgumentsHolder argsHolder; // 获取到构造函数的参数类型 Class<?>[] paramTypes = candidate.getParameterTypes(); if (resolvedValues != null) { try { // 评估参数名称,就是判断构造函数上是否标注了@ConstructorProperties注解,若是标注了,直接取其中定义的参数名称 String[] paramNames = ConstructorPropertiesChecker.evaluate(candidate, parameterCount); // 没有标注@ConstructorProperties注解,使用参数名称解析器,获取参数名称 if (paramNames == null) { ParameterNameDiscoverer pnd = this.beanFactory.getParameterNameDiscoverer(); if (pnd != null) { paramNames = pnd.getParameterNames(candidate); } } // 建立一个参数数组以调用构造函数或工厂方法,见下文详解 // 主要是经过参数类型和参数名解析构造函数或工厂方法所需的参数(若是参数是其余bean,则会解析依赖的bean) argsHolder = createArgumentArray(beanName, mbd, resolvedValues, bw, paramTypes, paramNames,getUserDeclaredConstructor(candidate), autowiring, candidates.length == 1); } catch (UnsatisfiedDependencyException ex) { // Swallow and try next constructor. if (causes == null) { causes = new LinkedList<>(); } causes.add(ex); continue; } } // resolvedValues为空, explicitArgs不为空,即显示指定了getBean()的args参数 else { // 若是当前构造函数参数个数不等的explicitArgs的长度,直接跳过该构造函数 if (parameterCount != explicitArgs.length) { continue; } // 把explicitArgs封装进ArgumentsHolder argsHolder = new ArgumentsHolder(explicitArgs); } // 根据mbd的解析构造函数模式(true: 宽松模式,false:严格模式) // 将argsHolder的参数和paramTypes进行比较,计算paramTypes的类型差别权重值 int typeDiffWeight = (mbd.isLenientConstructorResolution() ?argsHolder.getTypeDifferenceWeight(paramTypes) : argsHolder.getAssignabilityWeight(paramTypes)); // 差别值越小表明构造函数越匹配,则选择此构造函数 if (typeDiffWeight < minTypeDiffWeight) { constructorToUse = candidate; argsHolderToUse = argsHolder; argsToUse = argsHolder.arguments; minTypeDiffWeight = typeDiffWeight; // 若是出现权重值更小的候选者,则将ambiguousConstructors清空,容许以前存在权重值相同的候选者 ambiguousConstructors = null; } // 两个候选者权重值相同,而且是当前遍历过权重值最小的 else if (constructorToUse != null && typeDiffWeight == minTypeDiffWeight) { // 将两个候选者添加到ambiguousConstructors if (ambiguousConstructors == null) { ambiguousConstructors = new LinkedHashSet<>(); ambiguousConstructors.add(constructorToUse); } ambiguousConstructors.add(candidate); } } // 没有找到匹配的构造函数,抛出异常 if (constructorToUse == null) { if (causes != null) { UnsatisfiedDependencyException ex = causes.removeLast(); for (Exception cause : causes) { this.beanFactory.onSuppressedException(cause); } throw ex; } throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Could not resolve matching constructor (hint: specify index/type/name arguments for simple parameters to avoid type ambiguities)"); } // 若是有多个匹配的候选者,而且不是宽松模式,抛出异常 else if (ambiguousConstructors != null && !mbd.isLenientConstructorResolution()) { throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Ambiguous constructor matches found in bean '" + beanName + "'(hint: specify index/type/name arguments for simple parameters to avoid type ambiguities): " + ambiguousConstructors); } // getBean()方法没有指定args参数 && 构造函数参数不为空 if (explicitArgs == null && argsHolderToUse != null) { // 缓存解析事后的构造函数和参数 argsHolderToUse.storeCache(mbd, constructorToUse); } } Assert.state(argsToUse != null, "Unresolved constructor arguments"); // 利用反射建立bean实例 bw.setBeanInstance(instantiate(beanName, mbd, constructorToUse, argsToUse)); return bw; }
上面方法的功能主要以下:
explicitArgs
参数不为空,那就能够直接肯定参数。由于 explicitArgs
参数是在调用 getBean()
时手动指定的,这个主要用于静态工厂方法的调用。BeanDefinition
中读取,咱们所定义的 bean
都会生成一个 BeanDefinition
,其中记录了定义了构造函数参数经过 getConstructorArgumentValues()
获取。public
构造函数且参数个数从多到少,而后是非public
构造函数且参数个数有多到少。这样能够迅速判断排在后面的构造函数参数个数是否符合条件。bean
。private int resolveConstructorArguments(String beanName, RootBeanDefinition mbd, BeanWrapper bw, ConstructorArgumentValues cargs, ConstructorArgumentValues resolvedValues) { // 获取自定义类型转换器 TypeConverter customConverter = this.beanFactory.getCustomTypeConverter(); TypeConverter converter = (customConverter != null ? customConverter : bw); // 若是没有自定义的转换器就用bw BeanDefinitionValueResolver valueResolver = new BeanDefinitionValueResolver(this.beanFactory, beanName, mbd, converter); // minNrOfArgs初始化为indexedArgumentValues+genericArgumentValues的个数总和 int minNrOfArgs = cargs.getArgumentCount(); // 遍历IndexArgumentValues,这里的IndexArgumentValues就带下标的,如:<constructor-arg index="0" value="1"/> for (Map.Entry<Integer, ConstructorArgumentValues.ValueHolder> entry : cargs.getIndexedArgumentValues().entrySet()) { int index = entry.getKey(); if (index < 0) { throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Invalid constructor argument index: " + index); } // 若是index大于minNrOfArgs,修改minNrOfArgs值 if (index > minNrOfArgs) { // 由于index是构造函数下标值,因此总数这边要加1 minNrOfArgs = index + 1; } ConstructorArgumentValues.ValueHolder valueHolder = entry.getValue(); // 若是参数类型已经转换过,直接添加进resolvedValues if (valueHolder.isConverted()) { resolvedValues.addIndexedArgumentValue(index, valueHolder); } // 参数类型没有转换过,进行转换 else { Object resolvedValue = valueResolver.resolveValueIfNecessary("constructor argument", valueHolder.getValue()); // 使用转换过的参数值构建ValueHolder ConstructorArgumentValues.ValueHolder resolvedValueHolder = new ConstructorArgumentValues.ValueHolder(resolvedValue, valueHolder.getType(), valueHolder.getName()); resolvedValueHolder.setSource(valueHolder); // 添加进resolvedValues resolvedValues.addIndexedArgumentValue(index, resolvedValueHolder); } } // 遍历GenericArgumentValues并进行类型转换和上面同样,这里的GenericArgumentValues就是没有指定下标的 // 如:<constructor-arg value="1"/> for (ConstructorArgumentValues.ValueHolder valueHolder : cargs.getGenericArgumentValues()) { if (valueHolder.isConverted()) { resolvedValues.addGenericArgumentValue(valueHolder); } else { Object resolvedValue = valueResolver.resolveValueIfNecessary("constructor argument", valueHolder.getValue()); ConstructorArgumentValues.ValueHolder resolvedValueHolder = new ConstructorArgumentValues.ValueHolder( resolvedValue, valueHolder.getType(), valueHolder.getName()); resolvedValueHolder.setSource(valueHolder); resolvedValues.addGenericArgumentValue(resolvedValueHolder); } } // 返回参数个数 return minNrOfArgs; }
上面方法主要将 indexedArgumentValues
和 genericArgumentValues
属性中的值经过调用 resolveValueIfNecessary()
方法进行解析;resolveValueIfNecessary()
方法主要解析参数的类型,好比 ref
属性引用的 beanName
会经过 getBean()
返回实例。
private ArgumentsHolder createArgumentArray(String beanName, RootBeanDefinition mbd, @Nullable ConstructorArgumentValues resolvedValues,BeanWrapper bw, Class<?>[] paramTypes, @Nullable String[] paramNames, Executable executable, boolean autowiring, boolean fallback) throws UnsatisfiedDependencyException { // 获取类型转换器 TypeConverter customConverter = this.beanFactory.getCustomTypeConverter(); TypeConverter converter = (customConverter != null ? customConverter : bw); // 构建ArgumentsHolder ArgumentsHolder args = new ArgumentsHolder(paramTypes.length); Set<ConstructorArgumentValues.ValueHolder> usedValueHolders = new HashSet<>(paramTypes.length); Set<String> autowiredBeanNames = new LinkedHashSet<>(4); // 遍历参数类型数组 for (int paramIndex = 0; paramIndex < paramTypes.length; paramIndex++) { // 获取参数类型和名称 Class<?> paramType = paramTypes[paramIndex]; String paramName = (paramNames != null ? paramNames[paramIndex] : ""); ConstructorArgumentValues.ValueHolder valueHolder = null; if (resolvedValues != null) { // 根据参数的下标、类型、名称查询是否有匹配的 valueHolder = resolvedValues.getArgumentValue(paramIndex, paramType, paramName, usedValueHolders); // 没有匹配的 && 不是自动装配。尝试下一个通用的无类型参数值做为降级方法 // 它能够在类型转换后匹配 (例如,String -> int) if (valueHolder == null && (!autowiring || paramTypes.length == resolvedValues.getArgumentCount())) { valueHolder = resolvedValues.getGenericArgumentValue(null, null, usedValueHolders); } } // 找到了匹配的valueHolder if (valueHolder != null) { // 添加进usedValueHolders usedValueHolders.add(valueHolder); Object originalValue = valueHolder.getValue(); Object convertedValue; // 类型已经转换过 if (valueHolder.isConverted()) { // 获取已经转换过的值,做为args在paramIndex的预备参数 convertedValue = valueHolder.getConvertedValue(); args.preparedArguments[paramIndex] = convertedValue; } // 类型没有转换过 else { // 将构造方法和参数下标封装成MethodParameter(MethodParameter是封装方法和参数索引的工具类) MethodParameter methodParam = MethodParameter.forExecutable(executable, paramIndex); try { // 将原始值转换为paramType类型的值,没法转换时抛出异常 convertedValue = converter.convertIfNecessary(originalValue, paramType, methodParam); } catch (TypeMismatchException ex) { throw new UnsatisfiedDependencyException(mbd.getResourceDescription(), beanName, new InjectionPoint(methodParam), "Could not convert argument value of type [" + ObjectUtils.nullSafeClassName(valueHolder.getValue()) + "] to required type [" + paramType.getName() + "]: " + ex.getMessage()); } Object sourceHolder = valueHolder.getSource(); if (sourceHolder instanceof ConstructorArgumentValues.ValueHolder) { Object sourceValue = ((ConstructorArgumentValues.ValueHolder) sourceHolder).getValue(); // 标记args须要解析 args.resolveNecessary = true; // 将sourceValue做为args在paramIndex位置的预备参数 args.preparedArguments[paramIndex] = sourceValue; } } // 将convertedValue做为args在paramIndex位置的参数 args.arguments[paramIndex] = convertedValue; // 将originalValue做为args在paramIndex位置的原始参数 args.rawArguments[paramIndex] = originalValue; } // 没有找到匹配的valueHolder else { // 将构造方法和参数下标封装成MethodParameter MethodParameter methodParam = MethodParameter.forExecutable(executable, paramIndex); // 找不到明确的匹配,而且不是自动注入,抛出异常 if (!autowiring) { throw new UnsatisfiedDependencyException(mbd.getResourceDescription(), beanName, new InjectionPoint(methodParam), "Ambiguous argument values for parameter of type [" + paramType.getName() + "] - did you specify the correct bean references as arguments?"); } try { // 若是是自动注入,用resolveAutowiredArgument()解析参数,见下文详解 // 构造函数自动注入中的参数bean就是在这边处理 Object autowiredArgument = resolveAutowiredArgument( methodParam, beanName, autowiredBeanNames, converter, fallback); // 将经过自动装配解析出来的参数赋值给args args.rawArguments[paramIndex] = autowiredArgument; args.arguments[paramIndex] = autowiredArgument; args.preparedArguments[paramIndex] = autowiredArgumentMarker; args.resolveNecessary = true; } catch (BeansException ex) { throw new UnsatisfiedDependencyException(mbd.getResourceDescription(), beanName, new InjectionPoint(methodParam), ex); } } } // 若是依赖了其余的bean,则注册依赖关系(这边的autowiredBeanNames,就是全部依赖的beanName) for (String autowiredBeanName : autowiredBeanNames) { this.beanFactory.registerDependentBean(autowiredBeanName, beanName); } // 返回解析后的参数值 return args; }
上面方法判断构造函数若是有匹配的参数会转换成对应类型,若是没有匹配的参数,多半是构造函数自动注入,经过 resolveAutowiredArgument()
去查找 bean
并返回实例。
protected Object resolveAutowiredArgument(MethodParameter param, String beanName, @Nullable Set<String> autowiredBeanNames, TypeConverter typeConverter, boolean fallback) { // 获取参数的类型 Class<?> paramType = param.getParameterType(); // 若是参数类型是InjectionPoint if (InjectionPoint.class.isAssignableFrom(paramType)) { // 拿到当前的InjectionPoint(存储了当前正在解析依赖的方法参数信息,DependencyDescriptor) InjectionPoint injectionPoint = currentInjectionPoint.get(); if (injectionPoint == null) { // 当前injectionPoint为空,则抛出异常:目前没有可用的InjectionPoint throw new IllegalStateException("No current InjectionPoint available for " + param); } // 当前injectionPoint不为空,直接返回 return injectionPoint; } try { // 解析指定依赖,DependencyDescriptor: // 将MethodParameter的方法参数索引信息封装成DependencyDescriptor,见下文详解 return this.beanFactory.resolveDependency( new DependencyDescriptor(param, true), beanName, autowiredBeanNames, typeConverter); } // 忽略异常处理... }
上面方法中的 resolveDependency()
方法就是解决依赖注入的关键所在,在分析这个方法以前咱们先简单看一下 DependencyDescriptor
类。
public class DependencyDescriptor extends InjectionPoint implements Serializable { // 包装依赖(属性或者方法的某个参数)所在的声明类 private final Class<?> declaringClass; // 若是所包装依赖是方法的某个参数,则这里记录该方法的名称 @Nullable private String methodName; // 若是所包装的是方法的某个参数,则这里记录该参数的类型 @Nullable private Class<?>[] parameterTypes; // 若是所包装的是方法的某个参数,则这里记录该参数在该函数参数列表中的索引 private int parameterIndex; // 若是所包装的是属性,则这里记录该属性的名称 @Nullable private String fieldName; // 标识所包装依赖是否必要依赖 private final boolean required; // 标识所包装依赖是否须要饥饿加载 private final boolean eager; // 标识所包装依赖的嵌套级别 private int nestingLevel = 1; // 标识所包装依赖的包含者类,一般和声明类是同一个 @Nullable private Class<?> containingClass; // 省略其余代码... }
这个类就是依赖描述符,存储了须要注入 bean
的类型、构造器参数的下标(构造器注入该值不为空)、是否必需、字段名称(字段注入该值不为空)、方法名称(set
方法注入该值不为空)等。
public Object resolveDependency(DependencyDescriptor descriptor, @Nullable String requestingBeanName, @Nullable Set<String> autowiredBeanNames, @Nullable TypeConverter typeConverter) throws BeansException { descriptor.initParameterNameDiscovery(getParameterNameDiscoverer()); // Optional类型的处理,说明Spring也能够注入Optional类型的参数 if (Optional.class == descriptor.getDependencyType()) { return createOptionalDependency(descriptor, requestingBeanName); } // ObjectFactory或ObjectProvider类型的处理 else if (ObjectFactory.class == descriptor.getDependencyType() || ObjectProvider.class == descriptor.getDependencyType()) { return new DependencyObjectProvider(descriptor, requestingBeanName); } // javax.inject.Provider类型的处理 else if (javaxInjectProviderClass == descriptor.getDependencyType()) { return new Jsr330Factory().createDependencyProvider(descriptor, requestingBeanName); } else { // 获取延迟解析代理 Object result = getAutowireCandidateResolver().getLazyResolutionProxyIfNecessary( descriptor, requestingBeanName); if (result == null) { // 解析依赖,返回的result为最终须要注入的bean实例,见下文详解 result = doResolveDependency(descriptor, requestingBeanName, autowiredBeanNames, typeConverter); } return result; } }
public Object doResolveDependency(DependencyDescriptor descriptor, @Nullable String beanName,@Nullable Set<String> autowiredBeanNames, @Nullable TypeConverter typeConverter) throws BeansException { InjectionPoint previousInjectionPoint = ConstructorResolver.setCurrentInjectionPoint(descriptor); try { // 获取须要注入bean的快捷方式,不为空直接返回 Object shortcut = descriptor.resolveShortcut(this); if (shortcut != null) { return shortcut; } // 获取须要注入bean的类型 Class<?> type = descriptor.getDependencyType(); // 用于支持Spring中新增的注解@Value(肯定给定的依赖项是否声明@Value注解,若是有则拿到值) Object value = getAutowireCandidateResolver().getSuggestedValue(descriptor); if (value != null) { if (value instanceof String) { String strVal = resolveEmbeddedValue((String) value); BeanDefinition bd = (beanName != null && containsBean(beanName) ? getMergedBeanDefinition(beanName) : null); value = evaluateBeanDefinitionString(strVal, bd); } TypeConverter converter = (typeConverter != null ? typeConverter : getTypeConverter()); try { return converter.convertIfNecessary(value, type, descriptor.getTypeDescriptor()); } catch (UnsupportedOperationException ex) { return (descriptor.getField() != null ? converter.convertIfNecessary(value, type, descriptor.getField()) :converter.convertIfNecessary(value, type, descriptor.getMethodParameter())); } } // 解析MultipleBean,例如 Array,Collection,Map Object multipleBeans = resolveMultipleBeans(descriptor, beanName, autowiredBeanNames, typeConverter); if (multipleBeans != null) { return multipleBeans; } // 根据类型找到匹配的bean // matchingBeans(key: beanName value: 若是bean已经缓存了实例(例如单例bean会缓存其实例), // 就是bean的实例,不然就是对应的class对象) Map<String, Object> matchingBeans = findAutowireCandidates(beanName, type, descriptor); if (matchingBeans.isEmpty()) { // 没有找到匹配的bean,判断是否是必需的,不是直接返回null,不然抛出异常 if (isRequired(descriptor)) { raiseNoMatchingBeanFound(type, descriptor.getResolvableType(), descriptor); } return null; } String autowiredBeanName; Object instanceCandidate; // 若是有多个匹配的候选者 if (matchingBeans.size() > 1) { // 判断最佳的候选者,也就是寻找最匹配的beanName autowiredBeanName = determineAutowireCandidate(matchingBeans, descriptor); if (autowiredBeanName == null) { if (isRequired(descriptor) || !indicatesMultipleBeans(type)) { return descriptor.resolveNotUnique(descriptor.getResolvableType(), matchingBeans); } else { return null; } } // 拿到autowiredBeanName对应的value(bean实例或bean实例类型) instanceCandidate = matchingBeans.get(autowiredBeanName); } else { // 只找到一个符合的bean Map.Entry<String, Object> entry = matchingBeans.entrySet().iterator().next(); autowiredBeanName = entry.getKey(); instanceCandidate = entry.getValue(); } if (autowiredBeanNames != null) { // 将依赖的beanName添加到autowiredBeanNames中 autowiredBeanNames.add(autowiredBeanName); } // 若是须要注入的bean没有缓存实例,那么instanceCandidate是一个Class对象,再根据getBean()去获取对应的实例 if (instanceCandidate instanceof Class) { instanceCandidate = descriptor.resolveCandidate(autowiredBeanName, type, this); } Object result = instanceCandidate; if (result instanceof NullBean) { if (isRequired(descriptor)) { raiseNoMatchingBeanFound(type, descriptor.getResolvableType(), descriptor); } result = null; } if (!ClassUtils.isAssignableValue(type, result)) { throw new BeanNotOfRequiredTypeException(autowiredBeanName, type, instanceCandidate.getClass()); } // 返回最终须要注入的bean实例 return result; } finally { ConstructorResolver.setCurrentInjectionPoint(previousInjectionPoint); } }
上面方法才是真正去获取须要注入的 bean
,大概分为如下几个步骤:
查看是否有快捷方式获取注入 bean
是否为空,不为空直接返回。这里的快捷方式是经过继承 DependencyDescriptor
并重写 resolveShortcut()
来实现。
若是参数使用 @Value
注解修饰了,若是获取到值直接返回。
解析 MultipleBean
,这里的 MultipleBean
通常是 Array
、Collection
、Map
这种,不为空直接返回。
根据类型找到全部匹配的 bean
,matchingBeans
中 key
为 beanName
,value
的值有两种状况,若是bean已经缓存了实例(例如单例bean会缓存其实例),就是bean的实例,不然就是对应的class对象)。
matchingBeans
为空,判断须要注入的 bean
是不是必须的,若是是抛出异常,不然返回 null
。
matchingBeans
长度大于1,表明有多个候选者;选择最佳的候选者,规则是:
primary
属性为 true
的。PriorityOrdered
接口或者标注 @Priority
注解的。只有一个候选者,直接使用。
若是须要注入的 bean
没有缓存实例,那么 instanceCandidate
是一个 Class
对象,再根据 getBean()
方法去获取对应的实例。
最终返回须要注入的 bean
实例。
protected void applyMergedBeanDefinitionPostProcessors(RootBeanDefinition mbd, Class<?> beanType, String beanName) { for (BeanPostProcessor bp : getBeanPostProcessors()) { if (bp instanceof MergedBeanDefinitionPostProcessor) { MergedBeanDefinitionPostProcessor bdp = (MergedBeanDefinitionPostProcessor) bp; bdp.postProcessMergedBeanDefinition(mbd, beanType, beanName); } } }
上面代码很简单,无非就是拿到全部注册的 BeanPostProcessor
,而后遍历判断是不是 MeragedBeanDefinitionPostProcessor
类型,是的话进行 BeanDefinition
合并后的方法回调,在这个回调方法内你能够对指定 bean
的 BeanDefinition
作一些修改。
下面咱们简单看一下 MergedBeanDefinitionPostProcessor
接口中的方法:
public interface MergedBeanDefinitionPostProcessor extends BeanPostProcessor { /** * 对指定bean的BeanDefinition合并后的处理方法回调 */ void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName); /** * 通知已从新设置指定beanName的BeanDefinition,若是实现该方法应该清除受影响的bean的全部元数据 * @since 5.1 */ default void resetBeanDefinition(String beanName) { } }
本文主要介绍了建立 bean
实例的流程,咱们能够从新梳理一下思路:
bean
的实例化前方法回调,若是返回非空,跳事后面步骤bean
的实例,若是是构造函数注入会选择最适合的构造函数进行参数自动注入,不然调用默认的无参构造进行实例化 bean
。因为 doCreateBean()
方法中操做太多,这里会分为几篇文章,一一分析各个阶段。
最后,我模仿 Spring 写了一个精简版,代码会持续更新。地址:https://github.com/leisurexi/tiny-spring。