本系列文章:html
读源码,咱们能够从第一行读起java
谈谈Spring中的对象跟Bean,你知道Spring怎么建立对象的吗?spring
推荐阅读:数组
Spring杂谈微信
本系列文章将会带你一行行的将Spring的源码吃透,推荐阅读的文章是阅读源码的基础!app
在前面的文章中已经知道了Spring是如何将一个对象建立出来的,那么紧接着,Spring就须要将这个对象变成一个真正的Bean了,这个过程主要分为两步ide
在这两个过程当中,Bean的后置处理器会穿插执行,其中有些后置处理器是为了帮助完成属性注入或者初始化的,而有些后置处理器是Spring提供给程序员进行扩展的,固然,这两者并不冲突。整个Spring建立对象并将对象变成Bean的过程就是咱们常常提到了Spring中Bean的生命周期。固然,本系列源码分析的文章不会再对生命周期的概念作过多阐述了,若是你们有这方面的需求的话能够参考我以前的文章,或者关注个人公众号:程序员DMZ
Spring官网阅读(九)Spring中Bean的生命周期(上)
Spring官网阅读(十)Spring中Bean的生命周期(下)
闲话再也不多说,咱们正式进入源码分析阶段,本文重点要分析的方法就是org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#doCreateBean
,其源码以下:
protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final @Nullable Object[] args) throws BeanCreationException { // 建立对象的过程在上篇文章中咱们已经介绍过了,这里再也不赘述 BeanWrapper instanceWrapper = null; if (mbd.isSingleton()) { instanceWrapper = this.factoryBeanInstanceCache.remove(beanName); } if (instanceWrapper == null) { instanceWrapper = createBeanInstance(beanName, mbd, args); } // 获取到建立的这个对象 final Object bean = instanceWrapper.getWrappedInstance(); Class<?> beanType = instanceWrapper.getWrappedClass(); if (beanType != NullBean.class) { mbd.resolvedTargetType = beanType; } // Allow post-processors to modify the merged bean definition. // 按照官方的注释来讲,这个地方是Spring提供的一个扩展点,对程序员而言,咱们能够经过一个实现了MergedBeanDefinitionPostProcessor的后置处理器来修改bd中的属性,从而影响到后续的Bean的生命周期 // 不过官方本身实现的后置处理器并无去修改bd,而是调用了applyMergedBeanDefinitionPostProcessors方法 // 这个方法名直译过来就是-应用合并后的bd,也就是说它这里只是对bd作了进一步的使用而没有真正的修改 synchronized (mbd.postProcessingLock) { // bd只容许被处理一次 if (!mbd.postProcessed) { try { // 应用合并后的bd applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName); } catch (Throwable ex) { throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Post-processing of merged bean definition failed", ex); } // 标注这个bd已经被MergedBeanDefinitionPostProcessor的后置处理器处理过 // 那么在第二次建立Bean的时候,不会再次调用applyMergedBeanDefinitionPostProcessors mbd.postProcessed = true; } } // 这里是用来出来循环依赖的,关于循环以来,在介绍完正常的Bean的建立后,单独用一篇文章说明 // 这里不作过多解释 boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences && isSingletonCurrentlyInCreation(beanName)); if (earlySingletonExposure) { if (logger.isTraceEnabled()) { logger.trace("Eagerly caching bean '" + beanName + "' to allow for resolving potential circular references"); } addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean)); } Object exposedObject = bean; try { // 咱们这篇文章重点要分析的就是populateBean方法,在这个方法中完成了属性注入 populateBean(beanName, mbd, instanceWrapper); // 初始化 exposedObject = initializeBean(beanName, exposedObject, mbd); } catch (Throwable ex) { // 省略异常代码 } // 后续代码不在本文探讨范围内了,暂不考虑 return exposedObject; }
源码以下:
// 能够看到这个方法的代码仍是很简单的,就是调用了MergedBeanDefinitionPostProcessor的postProcessMergedBeanDefinition方法 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); } } }
这个时候咱们就要思考一个问题,容器中如今有哪些后置处理器是MergedBeanDefinitionPostProcessor
呢?
查看这个方法的实现类咱们会发现总共就这么几个类实现了MergedBeanDefinitionPostProcessor
接口。实际上除了ApplicationListenerDetector
以外,其他的后置处理器的逻辑都差很少。咱们在这里咱们主要就分析两个后置处理
首先,咱们来ApplicationListenerDetector
,这个类在以前的文章中也屡次提到过了,它的做用是用来处理嵌套Bean的状况,主要是保证能将嵌套在Bean标签中的ApplicationListener
也能添加到容器的监听器集合中去。咱们先经过一个例子来感觉下这个后置处理器的做用吧
配置文件:
<?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 http://www.springframework.org/schema/beans/spring-beans.xsd"> <bean class="com.dmz.source.populate.service.DmzService" id="dmzService"> <constructor-arg name="orderService"> <bean class="com.dmz.source.populate.service.OrderService"/> </constructor-arg> </bean> </beans>
示例代码:
// 事件 public class DmzEvent extends ApplicationEvent { public DmzEvent(Object source) { super(source); } } public class DmzService { OrderService orderService; public DmzService(OrderService orderService) { this.orderService = orderService; } } // 实现ApplicationListener接口 public class OrderService implements ApplicationListener<DmzEvent> { @Override public void onApplicationEvent(DmzEvent event) { System.out.println(event.getSource()); } } public class Main { public static void main(String[] args) { ClassPathXmlApplicationContext cc = new ClassPathXmlApplicationContext("application-populate.xml"); cc.publishEvent(new DmzEvent("my name is dmz")); } } // 程序运行结果,控制台打印:my name is dmz
说明OrderService
已经被添加到了容器的监听器集合中。可是请注意,在这种状况下,若是要使OrderService
可以执行监听的逻辑,必需要知足下面这两个条件
另外须要注意的是,这种嵌套的Bean比较特殊,它虽然由Spring建立,可是确不存在于容器中,就是说咱们不能将其做为依赖注入到别的Bean中。
对应源码以下:
public void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName) { // 找到注入的元数据,第一次是构建,后续能够直接从缓存中拿 // 注解元数据其实就是当前这个类中的全部须要进行注入的“点”的集合, // 注入点(InjectedElement)包含两种,字段/方法 // 对应的就是AutowiredFieldElement/AutowiredMethodElement InjectionMetadata metadata = findAutowiringMetadata(beanName, beanType, null); // 排除掉被外部管理的注入点 metadata.checkConfigMembers(beanDefinition); }
上面代码的核心逻辑就是
// 这个方法的核心逻辑就是先从缓存中获取已经解析好的注入点信息,很明显,在原型状况下才会使用缓存 // 建立注入点的核心逻辑在buildAutowiringMetadata方法中 private InjectionMetadata findAutowiringMetadata(String beanName, Class<?> clazz, @Nullable PropertyValues pvs) { String cacheKey = (StringUtils.hasLength(beanName) ? beanName : clazz.getName()); InjectionMetadata metadata = this.injectionMetadataCache.get(cacheKey); // 可能咱们会修改bd中的class属性,那么InjectionMetadata中的注入点信息也须要刷新 if (InjectionMetadata.needsRefresh(metadata, clazz)) { synchronized (this.injectionMetadataCache) { metadata = this.injectionMetadataCache.get(cacheKey); if (InjectionMetadata.needsRefresh(metadata, clazz)) { if (metadata != null) { metadata.clear(pvs); } // 这里真正建立注入点 metadata = buildAutowiringMetadata(clazz); this.injectionMetadataCache.put(cacheKey, metadata); } } } return metadata; }
// 咱们应用中使用@Autowired注解标注在字段上或者setter方法可以完成属性注入 // 就是由于这个方法将@Autowired注解标注的方法以及字段封装成InjectionMetadata // 在后续阶段会调用InjectionMetadata的inject方法进行注入 private InjectionMetadata buildAutowiringMetadata(final Class<?> clazz) { List<InjectionMetadata.InjectedElement> elements = new ArrayList<>(); Class<?> targetClass = clazz; do { final List<InjectionMetadata.InjectedElement> currElements = new ArrayList<>(); // 处理全部的被@AutoWired/@Value注解标注的字段 ReflectionUtils.doWithLocalFields(targetClass, field -> { AnnotationAttributes ann = findAutowiredAnnotation(field); if (ann != null) { // 静态字段会直接跳过 if (Modifier.isStatic(field.getModifiers())) { // 省略日志打印 return; } // 获得@AutoWired注解中的required属性 boolean required = determineRequiredStatus(ann); currElements.add(new AutowiredFieldElement(field, required)); } }); // 处理全部的被@AutoWired注解标注的方法,相对于字段而言,这里须要对桥接方法进行特殊处理 ReflectionUtils.doWithLocalMethods(targetClass, method -> { // 只处理一种特殊的桥接场景,其他的桥接方法都会被忽略 Method bridgedMethod = BridgeMethodResolver.findBridgedMethod(method); if (!BridgeMethodResolver.isVisibilityBridgeMethodPair(method, bridgedMethod)) { return; } AnnotationAttributes ann = findAutowiredAnnotation(bridgedMethod); // 处理方法时须要注意,当父类中的方法被子类重写时,若是子父类中的方法都加了@Autowired // 那么此时父类方法不能被处理,即不能被封装成一个AutowiredMethodElement if (ann != null && method.equals(ClassUtils.getMostSpecificMethod(method, clazz))) { if (Modifier.isStatic(method.getModifiers())) { // 省略日志打印 return; } if (method.getParameterCount() == 0) { // 当方法的参数数量为0时,虽然不须要进行注入,可是仍是会把这个方法做为注入点使用 // 这个方法最终仍是会被调用 if (logger.isInfoEnabled()) { logger.info("Autowired annotation should only be used on methods with parameters: " + method); } } boolean required = determineRequiredStatus(ann); // PropertyDescriptor: 属性描述符 // 就是经过解析getter/setter方法,例如void getA()会解析获得一个属性名称为a // readMethod为getA的PropertyDescriptor, // 在《Spring官网阅读(十四)Spring中的BeanWrapper及类型转换》文中已经作过解释 // 这里再也不赘述,这里之因此来这么一次查找是由于当XML中对这个属性进行了配置后, // 那么就不会进行自动注入了,XML中显示指定的属性优先级高于注解 PropertyDescriptor pd = BeanUtils.findPropertyForMethod(bridgedMethod, clazz); // 构造一个对应的AutowiredMethodElement,后续这个方法会被执行 // 方法的参数会被自动注入,这里不限于setter方法 currElements.add(new AutowiredMethodElement(method, required, pd)); } }); // 会处理父类中字段上及方法上的@AutoWired注解,而且父类的优先级比子类高 elements.addAll(0, currElements); targetClass = targetClass.getSuperclass(); } while (targetClass != null && targetClass != Object.class); return new InjectionMetadata(clazz, elements); }
上面的代码总体来讲应该很简单,就如咱们以前所说的,处理带有@Autowired注解的字段及方法,同时会过滤掉全部的静态字段及方法。上面复杂的地方在于对桥接方法的处理,可能大部分人都没办法理解这几行代码:
// 第一行 Method bridgedMethod = BridgeMethodResolver.findBridgedMethod(method); // 第二行 if (!BridgeMethodResolver.isVisibilityBridgeMethodPair(method, bridgedMethod)) { return; } // 第三行 if (ann != null && method.equals(ClassUtils.getMostSpecificMethod(method, clazz))) { }
要理解这些代码,首先你得知道什么是桥接,为此我已经写好了一篇文章:
除了在上面的文章中提到的桥接方法外,还有一种特殊的状况
// A类跟B类在同一个包下,A不是public的 class A { public void test(){ } } // 在B中会生成一个跟A中的方法描述符(参数+返回值)如出一辙的桥接方法 // 这个桥接方法实际上就是调用父类中的方法 // 具体能够参考:https://bugs.java.com/bugdatabase/view_bug.do?bug_id=63424113 public class B extends A { }
在理解了什么是桥接以后,那么上边的第一行
代码你应该就能看懂了,就以上面的代码为例,B中会生成一个桥接方法,对应的被桥接的方法就是A中的test
方法。
接着,咱们看看第二行代码
public static boolean isVisibilityBridgeMethodPair(Method bridgeMethod, Method bridgedMethod) { // 说明这个方法自己就不是桥接方法,直接返回true if (bridgeMethod == bridgedMethod) { return true; } // 说明是桥接方法,而且方法描述符一致 // 当且仅当是上面例子中描述的这种桥接的时候这个判断才会知足 // 正常来讲桥接方法跟被桥接方法的返回值+参数类型确定不一致 // 因此这个判断会过滤掉其他的全部类型的桥接方法 // 只会保留本文说起这种特殊状况下产生的桥接方法 return (bridgeMethod.getReturnType().equals(bridgedMethod.getReturnType()) && Arrays.equals(bridgeMethod.getParameterTypes(), bridgedMethod.getParameterTypes())); }
最后,再来看看第三行
代码,核心就是这句method.equals(ClassUtils.getMostSpecificMethod(method, clazz)
。这句代码的主要目的就是为了处理下面这种状况
@Component public class D extends C { @Autowired @Override public void setDmzService(DmzService dmzService) { dmzService.init(); this.dmzService = dmzService; } } // C不是Spring中的组件 public class C { DmzService dmzService; @Autowired public void setDmzService(DmzService dmzService) { this.dmzService = dmzService; } }
这种状况下,在处理D中的@Autowired注解时,虽然咱们要处理父类中的@Autowired
注解,可是由于子类中的方法已经复写了父类中的方法,因此此时应该要跳过父类中的这个被复写的方法,这就是第三行
代码的做用。
到这里咱们主要分析了applyMergedBeanDefinitionPostProcessors
这段代码的做用,它的执行时机是在建立对象以后,属性注入以前。按照官方的定义来讲,到这里咱们仍然可使用这个方法来修改bd的定义,那么相对于经过BeanFactoryPostProcessor
的方式修改bd,applyMergedBeanDefinitionPostProcessors
这个方法影响的范围更小,BeanFactoryPostProcessor
影响的是整个Bean的生命周期,而applyMergedBeanDefinitionPostProcessors
只会影响属性注入以后的生命周期。
其次,咱们分析了Spring中内置的MergedBeanDefinitionPostProcessor
,选取了其中两个特殊的后置处理器进行分析,其中ApplicationListenerDetector
主要处理内嵌的事件监听器,而AutowiredAnnotationBeanPostProcessor
主要用于处理@Autowired注解,实际上咱们会发现,到这里还只是完成了@Autowired注解的解析,尚未真正开始进行注入,真正注入的逻辑在后面咱们要分析的populateBean
方法中,在这个方法中会使用解析好的注入元信息完成真正的属性注入,那么接下来咱们就开始分析populateBean
这个方法的源码。
循环依赖的代码咱们暂且跳过,后续出一篇专门文章解读循环依赖,咱们直接看看populateBean到底作了什么。
protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) { // 处理空实例 if (bw == null) { // 若是建立的对象为空,可是在XML中又配置了须要注入的属性的话,那么直接报错 if (mbd.hasPropertyValues()) { throw new BeanCreationException( mbd.getResourceDescription(), beanName, "Cannot apply property values to null instance"); } else { // 空对象,不进行属性注入 return; } } // 知足两个条件,不是合成类 && 存在InstantiationAwareBeanPostProcessor // 其中InstantiationAwareBeanPostProcessor主要做用就是做为Bean的实例化先后的钩子 // 外加完成属性注入,对于三个方法就是 // postProcessBeforeInstantiation 建立对象前调用 // postProcessAfterInstantiation 对象建立完成,@AutoWired注解解析后调用 // postProcessPropertyValues(已过时,被postProcessProperties替代) 进行属性注入 // 下面这段代码的主要做用就是咱们能够提供一个InstantiationAwareBeanPostProcessor // 提供的这个后置处理若是实现了postProcessAfterInstantiation方法而且返回false // 那么能够跳过Spring默认的属性注入,可是这也意味着咱们要本身去实现属性注入的逻辑 // 因此通常状况下,咱们也不会这么去扩展 if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) { for (BeanPostProcessor bp : getBeanPostProcessors()) { if (bp instanceof InstantiationAwareBeanPostProcessor) { InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp; if (!ibp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) { return; } } } } // 这里其实就是判断XML是否提供了属性相关配置 PropertyValues pvs = (mbd.hasPropertyValues() ? mbd.getPropertyValues() : null); // 确认注入模型 int resolvedAutowireMode = mbd.getResolvedAutowireMode(); // 主要处理byName跟byType两种注入模型,byConstructor这种注入模型在建立对象的时候已经处理过了 // 这里都是对自动注入进行处理,byName跟byType两种注入模型均是依赖setter方法 // byName,根据setter方法的名字来查找对应的依赖,例如setA,那么就是去容器中查找名字为a的Bean // byType,根据setter方法的参数类型来查找对应的依赖,例如setXx(A a),就是去容器中查询类型为A的bean if (resolvedAutowireMode == AUTOWIRE_BY_NAME || resolvedAutowireMode == AUTOWIRE_BY_TYPE) { MutablePropertyValues newPvs = new MutablePropertyValues(pvs); if (resolvedAutowireMode == AUTOWIRE_BY_NAME) { autowireByName(beanName, mbd, bw, newPvs); } if (resolvedAutowireMode == AUTOWIRE_BY_TYPE) { autowireByType(beanName, mbd, bw, newPvs); } // pvs是XML定义的属性 // 自动注入后,bean实际用到的属性就应该要替换成自动注入后的属性 pvs = newPvs; } // 检查是否有InstantiationAwareBeanPostProcessor // 前面说过了,这个后置处理器就是来完成属性注入的 boolean hasInstAwareBpps = hasInstantiationAwareBeanPostProcessors(); // 是否须要依赖检查,默认是不会进行依赖检查的 boolean needsDepCheck = (mbd.getDependencyCheck() != AbstractBeanDefinition.DEPENDENCY_CHECK_NONE); // 下面这段代码有点麻烦了,由于涉及到版本问题 // 其核心代码就是调用了postProcessProperties完成了属性注入 PropertyDescriptor[] filteredPds = null; // 存在InstantiationAwareBeanPostProcessor,咱们须要调用这类后置处理器的方法进行注入 if (hasInstAwareBpps) { if (pvs == null) { pvs = mbd.getPropertyValues(); } for (BeanPostProcessor bp : getBeanPostProcessors()) { if (bp instanceof InstantiationAwareBeanPostProcessor) { InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp; // 这句就是核心 PropertyValues pvsToUse = ibp.postProcessProperties(pvs, bw.getWrappedInstance(), beanName); if (pvsToUse == null) { if (filteredPds == null) { // 获得须要进行依赖检查的属性的集合 filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching); } // 这个方法已通过时了,放到这里就是为了兼容老版本 pvsToUse = ibp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName); if (pvsToUse == null) { return; } } pvs = pvsToUse; } } } // 须要进行依赖检查 if (needsDepCheck) { if (filteredPds == null) { // 获得须要进行依赖检查的属性的集合 filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching); } // 对须要进行依赖检查的属性进行依赖检查 checkDependencies(beanName, mbd, filteredPds, pvs); } // 将XML中的配置属性应用到Bean上 if (pvs != null) { applyPropertyValues(beanName, mbd, bw, pvs); } }
上面这段代码主要能够拆分为三个部分
对应源码以下:
protected void autowireByName( String beanName, AbstractBeanDefinition mbd, BeanWrapper bw, MutablePropertyValues pvs) { // 获得符合下面条件的属性名称 // 1.有setter方法 // 2.须要进行依赖检查 // 3.不包含在XML配置中 // 4.不是简单类型(基本数据类型,枚举,日期等) // 这里能够看到XML配置优先级高于自动注入的优先级 // 不进行依赖检查的属性,也不会进行属性注入 String[] propertyNames = unsatisfiedNonSimpleProperties(mbd, bw); for (String propertyName : propertyNames) { if (containsBean(propertyName)) { Object bean = getBean(propertyName); // 将自动注入的属性添加到pvs中去 pvs.add(propertyName, bean); // 注册bean之间的依赖关系 registerDependentBean(propertyName, beanName); // 忽略日志 } // 忽略日志 } }
看到了吗?代码就是这么的简单,不是要经过名称注入吗?直接经过beanName调用getBean,完事儿
protected void autowireByType( String beanName, AbstractBeanDefinition mbd, BeanWrapper bw, MutablePropertyValues pvs) { // 这个类型转换器,主要是在处理@Value时须要使用 TypeConverter converter = getCustomTypeConverter(); if (converter == null) { converter = bw; } Set<String> autowiredBeanNames = new LinkedHashSet<>(4); // 获得符合下面条件的属性名称 // 1.有setter方法 // 2.须要进行依赖检查 // 3.不包含在XML配置中 // 4.不是简单类型(基本数据类型,枚举,日期等) // 这里能够看到XML配置优先级高于自动注入的优先级 String[] propertyNames = unsatisfiedNonSimpleProperties(mbd, bw); for (String propertyName : propertyNames) { try { PropertyDescriptor pd = bw.getPropertyDescriptor(propertyName); if (Object.class != pd.getPropertyType()) { // 这里获取到的就是setter方法的参数,由于咱们须要按照类型进行注入嘛 MethodParameter methodParam = BeanUtils.getWriteMethodParameter(pd); // 若是是PriorityOrdered在进行类型匹配时不会去匹配factoryBean // 若是不是PriorityOrdered,那么在查找对应类型的依赖的时候会会去匹factoryBean // 这就是Spring的一种设计理念,实现了PriorityOrdered接口的Bean被认为是一种 // 最高优先级的Bean,这一类的Bean在进行为了完成装配而去检查类型时, // 不去检查factoryBean // 具体能够参考PriorityOrdered接口上的注释文档 boolean eager = !(bw.getWrappedInstance() instanceof PriorityOrdered); // 将参数封装成为一个依赖描述符 // 依赖描述符会经过:依赖所在的类,字段名/方法名,依赖的具体类型等来描述这个依赖 DependencyDescriptor desc = new AutowireByTypeDependencyDescriptor(methodParam, eager); // 解析依赖,这里会处理@Value注解 // 另外,经过指定的类型到容器中查找对应的bean Object autowiredArgument = resolveDependency(desc, beanName, autowiredBeanNames, converter); if (autowiredArgument != null) { // 将查找出来的依赖属性添加到pvs中,后面会将这个pvs应用到bean上 pvs.add(propertyName, autowiredArgument); } // 注册bean直接的依赖关系 for (String autowiredBeanName : autowiredBeanNames) { registerDependentBean(autowiredBeanName, beanName); if (logger.isDebugEnabled()) { logger.debug("Autowiring by type from bean name '" + beanName + "' via property '" + propertyName + "' to bean named '" + autowiredBeanName + "'"); } } autowiredBeanNames.clear(); } } catch (BeansException ex) { throw new UnsatisfiedDependencyException(mbd.getResourceDescription(), beanName, propertyName, ex); } } }
这个方法在Spring杂谈 | 什么是ObjectFactory?什么是ObjectProvider?已经作过度析了,本文再也不赘述。
能够看到,真正作事的方法是
doResolveDependency
@Override public Object resolveDependency(DependencyDescriptor descriptor, String requestingBeanName, Set<String> autowiredBeanNames, @Nullable TypeConverter typeConverter) throws BeansException { // descriptor表明当前须要注入的那个字段,或者方法的参数,也就是注入点 // ParameterNameDiscovery用于解析方法参数名称 descriptor.initParameterNameDiscovery(getParameterNameDiscoverer()); // 1. Optional<T> if (Optional.class == descriptor.getDependencyType()) { return createOptionalDependency(descriptor, requestingBeanName); // 2. ObjectFactory<T>、ObjectProvider<T> } else if (ObjectFactory.class == descriptor.getDependencyType() || ObjectProvider.class == descriptor.getDependencyType()) { return new DependencyObjectProvider(descriptor, requestingBeanName); // 3. javax.inject.Provider<T> } else if (javaxInjectProviderClass == descriptor.getDependencyType()) { return new Jsr330Factory().createDependencyProvider(descriptor, requestingBeanName); } else { // 4. @Lazy Object result = getAutowireCandidateResolver().getLazyResolutionProxyIfNecessary( descriptor, requestingBeanName); // 5. 正常状况 if (result == null) { 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 { Object shortcut = descriptor.resolveShortcut(this); if (shortcut != null) { return shortcut; } // 依赖的具体类型 Class<?> type = descriptor.getDependencyType(); // 处理@Value注解,这里获得的时候@Value中的值 Object value = getAutowireCandidateResolver().getSuggestedValue(descriptor); if (value != null) { if (value instanceof String) { // 解析@Value中的占位符 String strVal = resolveEmbeddedValue((String) value); // 获取到对应的bd BeanDefinition bd = (beanName != null && containsBean(beanName) ? getMergedBeanDefinition(beanName) : null); // 处理EL表达式 value = evaluateBeanDefinitionString(strVal, bd); } // 经过解析el表达式可能还须要进行类型转换 TypeConverter converter = (typeConverter != null ? typeConverter : getTypeConverter()); return (descriptor.getField() != null ? converter.convertIfNecessary(value, type, descriptor.getField()) : converter.convertIfNecessary(value, type, descriptor.getMethodParameter())); } // 对map,collection,数组类型的依赖进行处理 // 最终会根据集合中的元素类型,调用findAutowireCandidates方法 Object multipleBeans = resolveMultipleBeans(descriptor, beanName, autowiredBeanNames, typeConverter); if (multipleBeans != null) { return multipleBeans; } // 根据指定类型可能会找到多个bean // 这里返回的既有多是对象,也有多是对象的类型 // 这是由于到这里还不能明确的肯定当前bean到底依赖的是哪个bean // 因此若是只会返回这个依赖的类型以及对应名称,最后还须要调用getBean(beanName) // 去建立这个Bean Map<String, Object> matchingBeans = findAutowireCandidates(beanName, type, descriptor); // 一个都没找到,直接抛出异常 if (matchingBeans.isEmpty()) { if (isRequired(descriptor)) { raiseNoMatchingBeanFound(type, descriptor.getResolvableType(), descriptor); } return null; } String autowiredBeanName; Object instanceCandidate; // 经过类型找到了多个 if (matchingBeans.size() > 1) { // 根据是不是主Bean // 是不是最高优先级的Bean // 是不是名称匹配的Bean // 来肯定具体的须要注入的Bean的名称 // 到这里能够知道,Spring在查找依赖的时候遵循先类型再名称的原则(没有@Qualifier注解状况下) autowiredBeanName = determineAutowireCandidate(matchingBeans, descriptor); if (autowiredBeanName == null) { // 没法推断出具体的名称 // 若是依赖是必须的,直接抛出异常 // 若是依赖不是必须的,可是这个依赖类型不是集合或者数组,那么也抛出异常 if (isRequired(descriptor) || !indicatesMultipleBeans(type)) { return descriptor.resolveNotUnique(type, matchingBeans); } // 依赖不是必须的,可是依赖类型是集合或者数组,那么返回一个null else { return null; } } instanceCandidate = matchingBeans.get(autowiredBeanName); } else { // 直接找到了一个对应的Bean Map.Entry<String, Object> entry = matchingBeans.entrySet().iterator().next(); autowiredBeanName = entry.getKey(); instanceCandidate = entry.getValue(); } if (autowiredBeanNames != null) { autowiredBeanNames.add(autowiredBeanName); } // 前面已经说过了,这里可能返回的是Bean的类型,因此须要进一步调用getBean if (instanceCandidate instanceof Class) { instanceCandidate = descriptor.resolveCandidate(autowiredBeanName, type, this); } // 作一些检查,若是依赖是必须的,查找出来的依赖是一个null,那么报错 // 查询处理的依赖类型不符合,也报错 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()); } return result; } finally { ConstructorResolver.setCurrentInjectionPoint(previousInjectionPoint); } }
protected Map<String, Object> findAutowireCandidates( @Nullable String beanName, Class<?> requiredType, DependencyDescriptor descriptor) { // 简单来讲,这里就是到容器中查询requiredType类型的全部bean的名称的集合 // 这里会根据descriptor.isEager()来决定是否要匹配factoryBean类型的Bean // 若是isEager()为true,那么会匹配factoryBean,反之,不会 String[] candidateNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors( this, requiredType, true, descriptor.isEager()); Map<String, Object> result = new LinkedHashMap<>(candidateNames.length); // 第一步会到resolvableDependencies这个集合中查询是否已经存在了解析好的依赖 // 像咱们之因此可以直接在Bean中注入applicationContext对象 // 就是由于Spring以前就将这个对象放入了resolvableDependencies集合中 for (Class<?> autowiringType : this.resolvableDependencies.keySet()) { if (autowiringType.isAssignableFrom(requiredType)) { Object autowiringValue = this.resolvableDependencies.get(autowiringType); // 若是resolvableDependencies放入的是一个ObjectFactory类型的依赖 // 那么在这里会生成一个代理对象 // 例如,咱们能够在controller中直接注入request对象 // 就是由于,容器启动时就在resolvableDependencies放入了一个键值对 // 其中key为:Request.class,value为:ObjectFactory // 在实际注入时放入的是一个代理对象 autowiringValue = AutowireUtils.resolveAutowiringValue(autowiringValue, requiredType); if (requiredType.isInstance(autowiringValue)) { // 这里放入的key不是Bean的名称 // value是实际依赖的对象 result.put(ObjectUtils.identityToString(autowiringValue), autowiringValue); break; } } } // 接下来开始对以前查找出来的类型匹配的全部BeanName进行处理 for (String candidate : candidateNames) { // 不是自引用,什么是自引用? // 1.候选的Bean的名称跟须要进行注入的Bean名称相同,意味着,本身注入本身 // 2.或者候选的Bean对应的factoryBean的名称跟须要注入的Bean名称相同, // 也就是说A依赖了B可是B的建立又须要依赖A // 要符合注入的条件 if (!isSelfReference(beanName, candidate) && isAutowireCandidate(candidate, descriptor)) { // 调用addCandidateEntry,加入到返回集合中,后文有对这个方法的分析 addCandidateEntry(result, candidate, descriptor, requiredType); } } // 排除自引用的状况下,没有找到一个合适的依赖 if (result.isEmpty() && !indicatesMultipleBeans(requiredType)) { // 1.先走fallback逻辑,Spring提供的一个扩展吧,感受没什么卵用 // 默认状况下fallback的依赖描述符就是自身 DependencyDescriptor fallbackDescriptor = descriptor.forFallbackMatch(); for (String candidate : candidateNames) { if (!isSelfReference(beanName, candidate) && isAutowireCandidate(candidate, fallbackDescriptor)) { addCandidateEntry(result, candidate, descriptor, requiredType); } } // fallback仍是失败 if (result.isEmpty()) { // 处理自引用 // 从这里能够看出,自引用的优先级是很低的,只有在容器中真正的只有这个Bean能做为 // 候选者的时候,才会去处理,不然自引用是被排除掉的 for (String candidate : candidateNames) { if (isSelfReference(beanName, candidate) && // 不是一个集合或者 // 是一个集合,可是beanName跟candidate的factoryBeanName相同 (!(descriptor instanceof MultiElementDescriptor) || !beanName.equals(candidate)) && isAutowireCandidate(candidate, fallbackDescriptor)) { addCandidateEntry(result, candidate, descriptor, requiredType); } } } } return result; } // candidates:就是findAutowireCandidates方法要返回的候选集合 // candidateName:当前的这个候选Bean的名称 // descriptor:依赖描述符 // requiredType:依赖的类型 private void addCandidateEntry(Map<String, Object> candidates, String candidateName, DependencyDescriptor descriptor, Class<?> requiredType) { // 若是依赖是一个集合,或者容器中已经包含这个单例了 // 那么直接调用getBean方法建立或者获取这个Bean if (descriptor instanceof MultiElementDescriptor || containsSingleton(candidateName)) { Object beanInstance = descriptor.resolveCandidate(candidateName, requiredType, this); candidates.put(candidateName, (beanInstance instanceof NullBean ? null : beanInstance)); } // 若是依赖的类型不是一个集合,这个时候还不能肯定到底要使用哪一个依赖, // 因此不能将这些Bean建立出来,因此这个时候,放入candidates是Bean的名称以及类型 else { candidates.put(candidateName, getType(candidateName)); } }
// 在applyMergedBeanDefinitionPostProcessors方法执行的时候, // 已经解析过了@Autowired注解(buildAutowiringMetadata方法) public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) { // 这里获取到的是解析过的缓存好的注入元数据 InjectionMetadata metadata = findAutowiringMetadata(beanName, bean.getClass(), pvs); try { // 直接调用inject方法 // 存在两种InjectionMetadata // 1.AutowiredFieldElement // 2.AutowiredMethodElement // 分别对应字段的属性注入以及方法的属性注入 metadata.inject(bean, beanName, pvs); } catch (BeanCreationException ex) { throw ex; } catch (Throwable ex) { throw new BeanCreationException(beanName, "Injection of autowired dependencies failed", ex); } return pvs; }
// 最终反射调用filed.set方法 protected void inject(Object bean, @Nullable String beanName, @Nullable PropertyValues pvs) throws Throwable { Field field = (Field) this.member; Object value; if (this.cached) { // 第一次注入的时候确定没有缓存 // 这里也是对原型状况的处理 value = resolvedCachedArgument(beanName, this.cachedFieldValue); } else { DependencyDescriptor desc = new DependencyDescriptor(field, this.required); desc.setContainingClass(bean.getClass()); Set<String> autowiredBeanNames = new LinkedHashSet<>(1); Assert.state(beanFactory != null, "No BeanFactory available"); TypeConverter typeConverter = beanFactory.getTypeConverter(); try { // 这里能够看到,对@Autowired注解在字段上的处理 // 跟byType下自动注入的处理是同样的,就是调用resolveDependency方法 value = beanFactory.resolveDependency(desc, beanName, autowiredBeanNames, typeConverter); } catch (BeansException ex) { throw new UnsatisfiedDependencyException(null, beanName, new InjectionPoint(field), ex); } synchronized (this) { // 没有缓存过的话,这里须要进行缓存 if (!this.cached) { if (value != null || this.required) { this.cachedFieldValue = desc; // 注册Bean之间的依赖关系 registerDependentBeans(beanName, autowiredBeanNames); // 若是这个类型的依赖只存在一个的话,咱们就能肯定这个Bean的名称 // 那么直接将这个名称缓存到ShortcutDependencyDescriptor中 // 第二次进行注入的时候就能够直接调用getBean(beanName)获得这个依赖了 // 实际上正常也只有一个,多个就报错了 // 另外这里会过滤掉@Vlaue获得的依赖 if (autowiredBeanNames.size() == 1) { String autowiredBeanName = autowiredBeanNames.iterator().next(); // 经过resolvableDependencies这个集合找的依赖不知足containsBean条件 // 不会进行缓存,由于缓存实际仍是要调用getBean,而resolvableDependencies // 是无法经过getBean获取的 if (beanFactory.containsBean(autowiredBeanName) && beanFactory.isTypeMatch(autowiredBeanName, field.getType())) { // 依赖描述符封装成ShortcutDependencyDescriptor进行缓存 this.cachedFieldValue = new ShortcutDependencyDescriptor( desc, autowiredBeanName, field.getType()); } } } else { this.cachedFieldValue = null; } this.cached = true; } } } if (value != null) { // 反射调用Field.set方法 ReflectionUtils.makeAccessible(field); field.set(bean, value); } }
// 代码看着很长,实际上逻辑跟字段注入基本同样 protected void inject(Object bean, @Nullable String beanName, @Nullable PropertyValues pvs) throws Throwable { // 判断XML中是否配置了这个属性,若是配置了直接跳过 // 换而言之,XML配置的属性优先级高于@Autowired注解 if (checkPropertySkipping(pvs)) { return; } Method method = (Method) this.member; Object[] arguments; if (this.cached) { arguments = resolveCachedArguments(beanName); } else { // 经过方法参数类型构造依赖描述符 // 逻辑基本同样的,最终也是调用beanFactory.resolveDependency方法 Class<?>[] paramTypes = method.getParameterTypes(); arguments = new Object[paramTypes.length]; DependencyDescriptor[] descriptors = new DependencyDescriptor[paramTypes.length]; Set<String> autowiredBeans = new LinkedHashSet<>(paramTypes.length); Assert.state(beanFactory != null, "No BeanFactory available"); TypeConverter typeConverter = beanFactory.getTypeConverter(); // 遍历方法的每一个参数 for (int i = 0; i < arguments.length; i++) { MethodParameter methodParam = new MethodParameter(method, i); DependencyDescriptor currDesc = new DependencyDescriptor(methodParam, this.required); currDesc.setContainingClass(bean.getClass()); descriptors[i] = currDesc; try { // 仍是要调用这个方法 Object arg = beanFactory.resolveDependency(currDesc, beanName, autowiredBeans, typeConverter); if (arg == null && !this.required) { arguments = null; break; } arguments[i] = arg; } catch (BeansException ex) { throw new UnsatisfiedDependencyException(null, beanName, new InjectionPoint(methodParam), ex); } } synchronized (this) { if (!this.cached) { if (arguments != null) { Object[] cachedMethodArguments = new Object[paramTypes.length]; System.arraycopy(descriptors, 0, cachedMethodArguments, 0, arguments.length); // 注册bean之间的依赖关系 registerDependentBeans(beanName, autowiredBeans); // 跟字段注入差很少,存在@Value注解,不进行缓存 if (autowiredBeans.size() == paramTypes.length) { Iterator<String> it = autowiredBeans.iterator(); for (int i = 0; i < paramTypes.length; i++) { String autowiredBeanName = it.next(); if (beanFactory.containsBean(autowiredBeanName) && beanFactory.isTypeMatch(autowiredBeanName, paramTypes[i])) { cachedMethodArguments[i] = new ShortcutDependencyDescriptor( descriptors[i], autowiredBeanName, paramTypes[i]); } } } this.cachedMethodArguments = cachedMethodArguments; } else { this.cachedMethodArguments = null; } this.cached = true; } } } if (arguments != null) { try { // 反射调用方法 // 像咱们的setter方法就是在这里调用的 ReflectionUtils.makeAccessible(method); method.invoke(bean, arguments); } catch (InvocationTargetException ex) { throw ex.getTargetException(); } } }
protected void checkDependencies( String beanName, AbstractBeanDefinition mbd, PropertyDescriptor[] pds, PropertyValues pvs) throws UnsatisfiedDependencyException { int dependencyCheck = mbd.getDependencyCheck(); for (PropertyDescriptor pd : pds) { // 有set方法可是在pvs中没有对应属性,那么须要判断这个属性是否要进行依赖检查 // 若是须要进行依赖检查的话,就须要报错了 // pvs中保存的是自动注入以及XML配置的属性 if (pd.getWriteMethod() != null && !pvs.contains(pd.getName())) { // 是不是基本属性,枚举/日期等也包括在内 boolean isSimple = BeanUtils.isSimpleProperty(pd.getPropertyType()); // 若是DEPENDENCY_CHECK_ALL,对任意属性都开启了依赖检查,报错 // DEPENDENCY_CHECK_SIMPLE,对基本属性开启了依赖检查而且是基本属性,报错 // DEPENDENCY_CHECK_OBJECTS,对非基本属性开启了依赖检查而且不是非基本属性,报错 boolean unsatisfied = (dependencyCheck == AbstractBeanDefinition.DEPENDENCY_CHECK_ALL) || (isSimple && dependencyCheck == AbstractBeanDefinition.DEPENDENCY_CHECK_SIMPLE) || (!isSimple && dependencyCheck == AbstractBeanDefinition.DEPENDENCY_CHECK_OBJECTS); if (unsatisfied) { throw new UnsatisfiedDependencyException(mbd.getResourceDescription(), beanName, pd.getName(), "Set this property value or disable dependency checking for this bean."); } } } }
到这一步解析出来的属性主要有三个来源
可是在应用到Bean前还须要作一步类型转换,这一部分代码实际上跟咱们以前在Spring官网阅读(十四)Spring中的BeanWrapper及类型转换介绍的差很少,并且由于XML跟自动注入的方式都不常见,正常@Autowired
的方式进行注入的话,这个方法没有什么用,因此本文就再也不赘述。
本文咱们主要分析了Spring在属性注入过程当中的相关代码,整个属性注入能够分为两个部分
@Autowired
/@Vale
的方式完成属性注入byType
/byName
)完成属性注入的核心方法其实就是doResolveDependency
。doResolveDependency
这个方法的逻辑简单来讲分为两步:
从上面也能够知道,其实整个属性注入的逻辑是很简单的。
若是本文对你有帮助的话,记得点个赞吧!也欢迎关注个人公众号,微信搜索:程序员DMZ,或者扫描下方二维码,跟着我一块儿认认真真学Java,踏踏实实作一个coder。