深圳网站设计必选成都柚米科技09做,移动登录网页模板免费下载,宝塔面板wordpress安装,网站建设psd模板前言 
源码在我github的guide-spring仓库中#xff0c;可以克隆下来 直接执行。 
我们本文主要来介绍依赖注入的使用示例及其原理 
依赖注入 
什么是依赖注入 
依赖注入#xff08;Dependency Injection#xff0c;简称DI#xff09;是一种设计模式#xff0c;它用于实现对…前言 
源码在我github的guide-spring仓库中可以克隆下来 直接执行。 
我们本文主要来介绍依赖注入的使用示例及其原理 
依赖注入 
什么是依赖注入 
依赖注入Dependency Injection简称DI是一种设计模式它用于实现对象之间的松散耦合。在依赖注入中一个对象不再负责创建或查找它所依赖的对象而是将这些依赖关系通过外部传递进来外部指的就是 IoC 容器IoC 容器负责对象的创建、管理和注入我们也常说 DI 是实现 IoC 的一种具体技术。这种方式有助于提高代码的可维护性、可测试性同时降低了组件之间的耦合度。 
依赖注入的方式 
注入的方式有以下几种 
setter方法注入构造器注入字段注入方法注入接口回调注入 
setter方法和构造器注入方式 
其中setter方法注入和构造器注入在xml配置手动注入时比较常见使用方法可以参考下面的示例代码 
xml 配置 
?xml version1.0 encodingUTF-8?
beans xmlnshttp://www.springframework.org/schema/beansxmlns:xsihttp://www.w3.org/2001/XMLSchema-instancexmlns:utilhttp://www.springframework.org/schema/utilxsi:schemaLocationhttp://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/utilhttp://www.springframework.org/schema/util/spring-util.xsdbean iduser classcom.markus.spring.ioc.overview.domain.User!-- 属性注入 --property nameid value1/property nameusername valuemarkus zhang//beanbean iduser-by-constructor classcom.markus.spring.ioc.overview.domain.User!-- 构造器注入 --constructor-arg index0 value2/constructor-arg index1 valueluna//bean
/beans 
Java 代码 
package com.markus.spring.dependency.injection;import com.markus.spring.ioc.overview.domain.User;
import org.springframework.context.support.ClassPathXmlApplicationContext;/*** author: markus* date: 2023/12/24 10:57 AM* Description: setter方法和构造器注入 示例* Blog: https://markuszhang.com* Its my honor to share what Ive learned with you!*/
public class SetterAndConstructorInjectionDemo {public static void main(String[] args) {ClassPathXmlApplicationContext context  new ClassPathXmlApplicationContext(classpath:/META-INF/dependency-inject.xml);User user  context.getBean(user, User.class);System.out.println(user);User userByConstructor  context.getBean(user-by-constructor, User.class);System.out.println(userByConstructor);context.close();}
}控制台 接口回调注入 
字段和方法注入的方式我们放在下面的自动绑定来说。接下来先把接口回调的注入方式介绍一下。 
准备一个Java Bean 
我们在原本 User 这个 Java Bean 的基础上让其实现 BeanNameAware 接口并重写其 setBeanName 方法这样就可以在 IoC 创建该 Bean 的时候完成 beanName 属性值的回调注入。 
package com.markus.spring.ioc.overview.domain;import org.springframework.beans.factory.BeanNameAware;import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;/*** Author: zhangchenglong06* Date: 2023/11/27* Description:*/
public class User implements BeanNameAware {private Long id;private String username;private String beanName;public User() {System.out.println(开始初始化);}public User(Long id, String username) {this.id  id;this.username  username;}Overridepublic void setBeanName(String name) {this.beanName  name;}
} 
编写一个示例代码 
package com.markus.spring.dependency.injection;import com.markus.spring.ioc.overview.domain.User;
import org.springframework.context.support.ClassPathXmlApplicationContext;/*** author: markus* date: 2023/12/24 11:06 AM* Description: 接口回调注入 示例* Blog: https://markuszhang.com* Its my honor to share what Ive learned with you!*/
public class InterfaceCallbackInjectionDemo {public static void main(String[] args) {ClassPathXmlApplicationContext context  new ClassPathXmlApplicationContext(classpath:/META-INF/dependency-inject.xml);User user  context.getBean(user, User.class);System.out.println(User Bean Name is [   user.getBeanName()   ]);context.close();}
}控制台 手动注入的弊端 
前面我们了解通过属性注入、构造器注入的使用方式看似比较简单、方便但试想如果有注入集合场景的时候我们通过手动注入应该如何实现呢下面来掩饰一下 
xml配置 
?xml version1.0 encodingUTF-8?
beans xmlnshttp://www.springframework.org/schema/beansxmlns:xsihttp://www.w3.org/2001/XMLSchema-instancexmlns:utilhttp://www.springframework.org/schema/utilxsi:schemaLocationhttp://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/utilhttp://www.springframework.org/schema/util/spring-util.xsdbean iduser classcom.markus.spring.ioc.overview.domain.User!-- 属性注入 --property nameid value1/property nameusername valuemarkus zhang//beanbean iduser-by-constructor classcom.markus.spring.ioc.overview.domain.User!-- 构造器注入 --constructor-arg index0 value2/constructor-arg index1 valueluna//beanbean iduser-list-holder classcom.markus.spring.ioc.overview.domain.UserListHolderproperty nameuserslistref beanuser/ref beanuser-by-constructor/!-- 依次增加 --/list/property/bean
/beans 
示例代码 
package com.markus.spring.dependency.injection;import com.markus.spring.ioc.overview.domain.User;
import com.markus.spring.ioc.overview.domain.UserListHolder;
import org.springframework.context.support.ClassPathXmlApplicationContext;/*** author: markus* date: 2023/12/24 10:57 AM* Description: setter方法和构造器注入 示例* Blog: https://markuszhang.com* Its my honor to share what Ive learned with you!*/
public class SetterAndConstructorInjectionDemo {public static void main(String[] args) {ClassPathXmlApplicationContext context  new ClassPathXmlApplicationContext(classpath:/META-INF/dependency-inject.xml);UserListHolder userListHolder  context.getBean(user-list-holder, UserListHolder.class);System.out.println(userListHolder);context.close();}
} 
控制台 我们的目的就是将容器中的所有 User 类型的 Bean 注入到 UserListHolder 中试想如果容器中不断的增加新的 User 类型的 Bean那么通过手动注入的方式则会每次都需要去修改 UserListHolder 这个 Bean这非常的不便下面我们就来介绍下 Spring 框架提供的 自动绑定Autowiring特性。 
自动绑定 
使用和优点 
我们先来看下官方对于自动绑定的说明原文链接 上面解释了自动装配的功能以及其优势和自动绑定的方式。大致意思是说Spring IoC 容器可以自动绑定协作 Bean 之间的关系。我们可以让 Spring 通过查找 ApplicationContext 中的内容将其自动解析注入到你的 Bean 中。自动装配有以下优点 
自动装配可以显著减少手动配置需要的属性或者构造器的参数自动装配可以随着对象的发展自动更新配置例如如果需要向类中添加依赖项则无需修改配置即可满足该依赖项。 
也给出了基于 XMl 配置元信息场景下如何使用自动绑定以及自动绑定的几种模式 
no : 默认状态无自动绑定byName : 通过属性名进行自动绑定byType : 通过类型进行自动绑定constructor : 和 byType 相似不同的是 constructor 是应用与构造器参数上 
我们回到上面在手动注入的弊端中所提到的例子我们通过自动绑定稍加改造即可完成即便容器中增加多少或者删除多少 User 类型的 Bean 配置都不需要更改 UserListHolder 的配置完成其内容的自动更新。 
?xml version1.0 encodingUTF-8?
beans xmlnshttp://www.springframework.org/schema/beansxmlns:xsihttp://www.w3.org/2001/XMLSchema-instancexmlns:utilhttp://www.springframework.org/schema/utilxsi:schemaLocationhttp://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/utilhttp://www.springframework.org/schema/util/spring-util.xsdbean iduser classcom.markus.spring.ioc.overview.domain.User!-- 属性注入 --property nameid value1/property nameusername valuemarkus zhang//beanbean iduser-by-constructor classcom.markus.spring.ioc.overview.domain.User!-- 构造器注入 --constructor-arg index0 value2/constructor-arg index1 valueluna//beanbean iduser-list-holder classcom.markus.spring.ioc.overview.domain.UserListHolderautowirebyType !--通过类型 自动绑定--
!--        property nameusers--
!--            list--
!--                ref beanuser/--
!--                ref beanuser-by-constructor/--
!--                lt;!ndash; 依次增加 ndash;gt;--
!--            /list--
!--        /property--/bean
/beans 
再次执行下上面的程序依然正常执行。 
我们通过自定绑定可以注入很多类型包括数组、集合、Map以及外部化配置下面我们用 Autowired 和 Value 注解完成这些功能。 
package com.markus.spring.dependency.injection;import com.markus.spring.ioc.overview.domain.User;
import com.markus.spring.ioc.overview.domain.UserHolder;
import org.springframework.beans.factory.ObjectFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.*;import java.util.Collection;
import java.util.Map;
import java.util.Optional;/*** Author: zhangchenglong06* Date: 2023/12/18* Description: Autowired 注解注入示例*/
Configuration
PropertySource(classpath:/META-INF/application.properties)
public class AtAutowiredAnnotationInjectionDemo {Autowiredprivate OptionalUser optionalUser;Autowiredprivate ObjectFactoryUser userObjectFactory;/*** Autowired 注入流程* 1. 先按照名称查找* 2. 再按照类型查找*/Autowiredprivate User user1;Autowiredprivate CollectionUser users;Autowiredprivate MapString, User userMap;Autowiredprivate User[] userArrays;private User userFromMethodInjection;Autowiredpublic void setUserFromMethodInjection(User user) {this.userFromMethodInjection  user;}Autowiredprivate UserHolder userHolder;Value(${my_site})private String mySite;public static void main(String[] args) {AnnotationConfigApplicationContext context  new AnnotationConfigApplicationContext();context.register(AtAutowiredAnnotationInjectionDemo.class);context.refresh();AtAutowiredAnnotationInjectionDemo demo  context.getBean(AtAutowiredAnnotationInjectionDemo.class);System.out.println(demo.optionalUser :   demo.optionalUser.get());System.out.println(demo.userObjectFactory :   demo.userObjectFactory.getObject());System.out.println(demo.user :   demo.user1);System.out.println(demo.users :   demo.users);System.out.println(demo.userMap :   demo.userMap);System.out.print(demo.userArrays : [ );for (User userArray : demo.userArrays) {System.out.print(userArray.getBeanName()   );}System.out.println(]);System.out.println(demo.userFromMethodInjection :   demo.userFromMethodInjection);System.out.println(demo.userHolder :   demo.userHolder);System.out.println(demo.mySite :   demo.mySite);context.close();}Bean(user1)public User user1() {User user  new User();user.setId(1L);user.setUsername(Markus Zhang);return user;}Bean(user2)Primarypublic User user2() {User user  new User();user.setId(2L);user.setUsername(Luna);return user;}Beanpublic UserHolder userHolder(Autowired User user) {UserHolder userHolder  new UserHolder();userHolder.setUser(user);return userHolder;}
} 
我们来看下控制台 缺点 
一项技术的落地有它顺应时代的诉求也一定会有它的局限性我们通过官网来叙述下 自动绑定Autowiring 有什么限制或者缺点原文链接 上面大概描述了 自动绑定的缺点和官方给你的建议 
缺点 显示注入比自动绑定优先级更高它总会覆盖自动绑定的属性不能注入简单属性例如原语类型 String、int等这是框架设计的限制(ps: 不过这些类型我们可以通过 Value 实现前面给出了例子)自动绑定没有显示绑定精确尽管 Spring 已经很小心地处理以避免歧义但还是会有意想不到的结果绑定信息不会以可视化的形式展示出来多个 BeanDefinition 的情况下在注入 集合、数组、Map等场景时问题不大但是在注入单个 Bean 时可能会产生问题如果 Spring 在进行注入时找不到唯一 Bean 则会抛出异常 建议 避免使用自动绑定采用显示绑定如果某个 Bean 不想被注入到其他 Bean 中则可通过 autowired-candidate 属性设置为 false 来跳过注入在注入单个 Bean 的场景中我们可以把目标 Bean 的 primary 属性设置为 true通过注解驱动实现更精细粒度的控制  
依赖注入原理 
Bean 生命周期 
在说依赖注入前我们先来整体看下 Spring Bean 的生命周期然后再来说依赖注入发生在哪个阶段接着再去对应源码处解析其原理 上图是 Bean 整个生命周期图我们放大来看构造器注入和 setter 方法注入所在的环节: 构造器注入 
我们把 Spring 源码拷贝出来: 
// org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#createBeanInstance
protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, Nullable Object[] args) {// ... 其他流程省略// Candidate constructors for autowiring?Constructor?[] ctors  determineConstructorsFromBeanPostProcessors(beanClass, beanName);if (ctors ! null || mbd.getResolvedAutowireMode()  AUTOWIRE_CONSTRUCTOR ||mbd.hasConstructorArgumentValues() || !ObjectUtils.isEmpty(args)) {return autowireConstructor(beanName, mbd, ctors, args);}// No special handling: simply use no-arg constructor.return instantiateBean(beanName, mbd);
}可以看到 Spring 在判断是否进行 构造器注入 的条件有以下几种满足其一即可: 
构造器列表不为空BeanDefinition 的 autowireMode 设置为 AUTOWIRE_CONSTRUCTORBeanDefinition 指定了构造器参数args 参数不为空ps: 这个通常为空 
否则不进行特殊处理直接使用无参构造器进行实例化通过 cglib 或者 jdk 动态代理这块不进行细节介绍了。 
下面我们进入到 autowireConstructor 方法看看里面做了什么: 
public BeanWrapper autowireConstructor(String beanName, RootBeanDefinition mbd,Nullable Constructor?[] chosenCtors, Nullable Object[] explicitArgs) {BeanWrapperImpl bw  new BeanWrapperImpl();this.beanFactory.initBeanWrapper(bw);Constructor? constructorToUse  null;ArgumentsHolder argsHolderToUse  null;Object[] argsToUse  null;if (explicitArgs ! null) {argsToUse  explicitArgs;}else {// ... 其他细节忽略// 需要去解析构造器boolean autowiring  (chosenCtors ! null ||mbd.getResolvedAutowireMode()  AutowireCapableBeanFactory.AUTOWIRE_CONSTRUCTOR);ConstructorArgumentValues resolvedValues  null;int minNrOfArgs;if (explicitArgs ! null) {minNrOfArgs  explicitArgs.length;}else {ConstructorArgumentValues cargs  mbd.getConstructorArgumentValues();resolvedValues  new ConstructorArgumentValues();minNrOfArgs  resolveConstructorArguments(beanName, mbd, bw, cargs, resolvedValues);}// 以参数个数的多少对构造器进行排序顺序从多到少AutowireUtils.sortConstructors(candidates);int minTypeDiffWeight  Integer.MAX_VALUE;SetConstructor? ambiguousConstructors  null;LinkedListUnsatisfiedDependencyException 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) {// ...  省略细节// 核心方法是解析当前候选构造器参数对应的参数值argsHolder  createArgumentArray(beanName, mbd, resolvedValues, bw, paramTypes, paramNames,getUserDeclaredConstructor(candidate), autowiring, candidates.length  1);// ... 省略细节}// ... 省略int typeDiffWeight  (mbd.isLenientConstructorResolution() ?argsHolder.getTypeDifferenceWeight(paramTypes) : argsHolder.getAssignabilityWeight(paramTypes));// 如果这个构造器最近接匹配的话就选择这个构造器进行实例化// Choose this constructor if it represents the closest match.if (typeDiffWeight  minTypeDiffWeight) {constructorToUse  candidate;argsHolderToUse  argsHolder;argsToUse  argsHolder.arguments;minTypeDiffWeight  typeDiffWeight;ambiguousConstructors  null;}// ... }// ... 省略其他细节}bw.setBeanInstance(instantiate(beanName, mbd, constructorToUse, argsToUse));return bw;}总结一下 
获取候选构造器集合对构造器集合进行排序根据参数数量从多到少进行排序遍历构造器集合依次解析构造器的参数对应的值核心方法 createArgumentArray解析出值以后通过反射计算出类型差异权重Spring 设计出来的一个算法有兴趣的可以了解下 org.springframework.util.MethodInvoker#getTypeDifferenceWeight如果差异结果最匹配就选择这个构造器进行实例化 
我们再深入到createArgumentArray方法中去看下 
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 {// ... 省略细节for (int paramIndex  0; paramIndex  paramTypes.length; paramIndex) {if (valueHolder ! null) {// ... 省略细节}else {// ... 省略细节try {// 核心在这依次解析构造器中的参数值Object autowiredArgument  resolveAutowiredArgument(methodParam, beanName, autowiredBeanNames, converter, fallback);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);}}// ... 省略细节}// ... 省略细节return args;} 
我们可以看到createArgumentArray方法中主要做的事情就是遍历构造器的参数依次解析其参数值我们再往下看一下resolveAutowiredArgument方法看下它是如何解析出具体值的。 
protected Object resolveAutowiredArgument(MethodParameter param, String beanName,Nullable SetString autowiredBeanNames, TypeConverter typeConverter, boolean fallback) {// ... 省略细节try {// 这块就是最最最最最最最核心的函数了我们在揭幕到这return this.beanFactory.resolveDependency(new DependencyDescriptor(param, true), beanName, autowiredBeanNames, typeConverter);}// ... 省略细节}可以看到 依赖注入实现原理中最最最最核心的函数 org.springframework.beans.factory.config.AutowireCapableBeanFactory#resolveDependency(xxx) 露出水面了我们这里先不深入解析点到为止。 
总结一下构造器注入发生在 Bean 生命周期中 实例化 Bean 阶段也就是 createBeanInstance 函数中这个函数主要目的就是选择出 Bean 对象中最合适的构造器完成对 Bean 的实例化在选择构造器的过程中会有一步判断 用户是否选择进行构造器自动绑定的逻辑如果用户选择了构造器自动绑定那么 Spring 框架会通过反射获取该类的所有构造器选择出最适合的构造器进行实例化。而在选择构造器的过程中会对构造器的参数进行解析解析出来以后通过对比差异Spring 实现了一套类型与参数值的差异算法有兴趣的同学可以深入了解下org.springframework.util.MethodInvoker#getTypeDifferenceWeight来决定最终用来实例化的构造器。而在解析参数值时我们探究到 resolveDependency这个函数通过这个函数可以解析出来当前参数所对应的值。 
构造器注入原理就如上所述了。 
setter方法注入 
同样我们也先把实现setter方法注入的入口函数先拷贝出来 
// org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#populateBean
protected void populateBean(String beanName, RootBeanDefinition mbd, Nullable BeanWrapper bw) {// ... 省略细节PropertyValues pvs  (mbd.hasPropertyValues() ? mbd.getPropertyValues() : null);int resolvedAutowireMode  mbd.getResolvedAutowireMode();if (resolvedAutowireMode  AUTOWIRE_BY_NAME || resolvedAutowireMode  AUTOWIRE_BY_TYPE) {MutablePropertyValues newPvs  new MutablePropertyValues(pvs);// Add property values based on autowire by name if applicable.if (resolvedAutowireMode  AUTOWIRE_BY_NAME) {autowireByName(beanName, mbd, bw, newPvs);}// Add property values based on autowire by type if applicable.if (resolvedAutowireMode  AUTOWIRE_BY_TYPE) {autowireByType(beanName, mbd, bw, newPvs);}pvs  newPvs;}// ... 省略细节
}我们省略其他的细节重点看下这个函数里面对于自动绑定的处理可以看到框架通过判断 BeanDefinition 的 autowiredMode 属性来决定执行 autowireByName 还是 autowireByType 函数。 
autowiredByName 
protected void autowireByName(String beanName, AbstractBeanDefinition mbd, BeanWrapper bw, MutablePropertyValues pvs) {String[] propertyNames  unsatisfiedNonSimpleProperties(mbd, bw);// 获取属性名for (String propertyName : propertyNames) {if (containsBean(propertyName)) {// 通过属性名称进行依赖查找Object bean  getBean(propertyName);pvs.add(propertyName, bean);registerDependentBean(propertyName, beanName);if (logger.isTraceEnabled()) {logger.trace(Added autowiring by name from bean name   beanName  via property   propertyName   to bean named   propertyName  );}}else {if (logger.isTraceEnabled()) {logger.trace(Not autowiring property   propertyName   of bean   beanName  by name: no matching bean found);}}}
}autowiredByType 
protected void autowireByType(String beanName, AbstractBeanDefinition mbd, BeanWrapper bw, MutablePropertyValues pvs) {TypeConverter converter  getCustomTypeConverter();if (converter  null) {converter  bw;}SetString autowiredBeanNames  new LinkedHashSet(4);String[] propertyNames  unsatisfiedNonSimpleProperties(mbd, bw);for (String propertyName : propertyNames) {try {PropertyDescriptor pd  bw.getPropertyDescriptor(propertyName);// Dont try autowiring by type for type Object: never makes sense,// even if it technically is a unsatisfied, non-simple property.if (Object.class ! pd.getPropertyType()) {MethodParameter methodParam  BeanUtils.getWriteMethodParameter(pd);// Do not allow eager init for type matching in case of a prioritized post-processor.boolean eager  !(bw.getWrappedInstance() instanceof PriorityOrdered);DependencyDescriptor desc  new AutowireByTypeDependencyDescriptor(methodParam, eager);// 解析依赖值Object autowiredArgument  resolveDependency(desc, beanName, autowiredBeanNames, converter);if (autowiredArgument ! null) {pvs.add(propertyName, autowiredArgument);}for (String autowiredBeanName : autowiredBeanNames) {registerDependentBean(autowiredBeanName, beanName);if (logger.isTraceEnabled()) {logger.trace(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);}}
}通过类型注入中我们也看到了这个核心函数resolveDependency通过其将属性参数值解析出来并完成注入。 
总结一下setter方法注入有两种方式一是通过名称注入二是通过类型注入。在通过名称注入的方式中框架采用依赖查找完成在通过类型注入的方式中框架采用解析依赖完成。 
依赖来源 
前面我们解释了构造器注入和setter方法注入两种方式的原理追溯到底层我们发现两者都会通过org.springframework.beans.factory.config.AutowireCapableBeanFactory#resolveDependency(xxx)这个函数获取解析后的参数值setter方法通过名称注入的时候采用的依赖查找除外。 
这里我们可以得到一个结论依赖注入的来源主要来源于 getBean(xxx) 和 resolveDependency(xxx) 两处接下来我们将深入探究这两个来源。 
getBean(xxx)的来源 
getBean就是依赖查找追溯getBean(xxx)的来源等价于追溯依赖查找的来源。 
依赖查找的来源包括 
BeanDefinition 用户配置Spring 内建 单例对象 用户使用 API 注册Spring 内建  
用户配置的 BeanDefinition 元信息我们就不介绍了对于 Spring 内建 BeanDefinition 的注册如下图所示 org.springframework.context.annotation.AnnotationConfigUtils#registerAnnotationConfigProcessors(org.springframework.beans.factory.support.BeanDefinitionRegistry, java.lang.Object) 我们再来看下 Spring 内建单例对象 org.springframework.context.support.AbstractApplicationContext#prepareBeanFactory org.springframework.context.support.AbstractApplicationContext#initMessageSource org.springframework.context.support.AbstractApplicationContext#initApplicationEventMulticaster org.springframework.context.support.AbstractApplicationContext#initLifecycleProcessor 最终依赖查找的来源这两项 
org.springframework.beans.factory.support.BeanDefinitionRegistry#registerBeanDefinitionorg.springframework.beans.factory.config.SingletonBeanRegistry#registerSingleton 
resolveDependency(xxx)的来源 
针对 resolveDependency 依赖来源我们直接从这个入口开始 
// org.springframework.beans.factory.support.DefaultListableBeanFactory#doResolveDependency
public Object doResolveDependency(DependencyDescriptor descriptor, Nullable String beanName,Nullable SetString autowiredBeanNames, Nullable TypeConverter typeConverter) throws BeansException {InjectionPoint previousInjectionPoint  ConstructorResolver.setCurrentInjectionPoint(descriptor);try {// 针对 Value 注解的使用场景例如 Value(${xxx:defaultValue})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) {// A custom TypeConverter which does not support TypeDescriptor resolution...return (descriptor.getField() ! null ?converter.convertIfNecessary(value, type, descriptor.getField()) :converter.convertIfNecessary(value, type, descriptor.getMethodParameter()));}}// 解析 字段类型为 Array、Collection、Map等的场景Object multipleBeans  resolveMultipleBeans(descriptor, beanName, autowiredBeanNames, typeConverter);if (multipleBeans ! null) {return multipleBeans;}// 按照类型从 数据源中进行 查找MapString, Object matchingBeans  findAutowireCandidates(beanName, type, descriptor);if (matchingBeans.isEmpty()) {if (isRequired(descriptor)) {raiseNoMatchingBeanFound(type, descriptor.getResolvableType(), descriptor);}return null;}String autowiredBeanName;Object instanceCandidate;// 当有多个 匹配到的 Bean 情况决定选择哪个作为首选的 Bean 进行注入if (matchingBeans.size()  1) {autowiredBeanName  determineAutowireCandidate(matchingBeans, descriptor);if (autowiredBeanName  null) {if (isRequired(descriptor) || !indicatesMultipleBeans(type)) {return descriptor.resolveNotUnique(descriptor.getResolvableType(), matchingBeans);}else {// In case of an optional Collection/Map, silently ignore a non-unique case:// possibly it was meant to be an empty collection of multiple regular beans// (before 4.3 in particular when we didnt even look for collection beans).return null;}}instanceCandidate  matchingBeans.get(autowiredBeanName);}else {// We have exactly one match.Map.EntryString, Object entry  matchingBeans.entrySet().iterator().next();autowiredBeanName  entry.getKey();instanceCandidate  entry.getValue();}if (autowiredBeanNames ! null) {autowiredBeanNames.add(autowiredBeanName);}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());}return result;}finally {ConstructorResolver.setCurrentInjectionPoint(previousInjectionPoint);}
}总结一下这个函数主要做了一下事情 
解析字段被 Value 标注时做一个解析并返回解析的过程是如果有显示的属性配置则采用配置值没有配置则采用默认值解析字段为数组、集合或者Map的场景从数据源中按照类型查找出来并设置到当前字段中去解析字段非上述情况时从数据源中同样按照类型查找出来并选择出首选的依赖返回。 
上面说的数据源比较神秘我们就深入到 determineAutowireCandidate 方法来一探究竟解开其神秘的面纱 
protected MapString, Object findAutowireCandidates(Nullable String beanName, Class? requiredType, DependencyDescriptor descriptor) {// 按照类型从容器中查找相关的候选 Bean 名称String[] candidateNames  BeanFactoryUtils.beanNamesForTypeIncludingAncestors(this, requiredType, true, descriptor.isEager());MapString, Object result  new LinkedHashMap(candidateNames.length);// 从 可解析依赖 中 查找是否有该 类型的 依赖如果有也被考虑进 resultfor (Map.EntryClass?, Object classObjectEntry : this.resolvableDependencies.entrySet()) {Class? autowiringType  classObjectEntry.getKey();if (autowiringType.isAssignableFrom(requiredType)) {Object autowiringValue  classObjectEntry.getValue();autowiringValue  AutowireUtils.resolveAutowiringValue(autowiringValue, requiredType);if (requiredType.isInstance(autowiringValue)) {result.put(ObjectUtils.identityToString(autowiringValue), autowiringValue);break;}}}// 根据候选的 Bean 名称通过其 BeanDefinition 判断是否可以加入到 resultfor (String candidate : candidateNames) {if (!isSelfReference(beanName, candidate)  isAutowireCandidate(candidate, descriptor)) {addCandidateEntry(result, candidate, descriptor, requiredType);}}// 结果为空if (result.isEmpty()) {// 判断字段不是多 Bean 的场景boolean multiple  indicatesMultipleBeans(requiredType);// Consider fallback matches if the first pass failed to find anything...DependencyDescriptor fallbackDescriptor  descriptor.forFallbackMatch();for (String candidate : candidateNames) {if (!isSelfReference(beanName, candidate)  isAutowireCandidate(candidate, fallbackDescriptor) (!multiple || getAutowireCandidateResolver().hasQualifier(descriptor))) {addCandidateEntry(result, candidate, descriptor, requiredType);}}// 还为空 并且 字段不为多 Bean 的场景if (result.isEmpty()  !multiple) {// Consider self references as a final pass...// but in the case of a dependency collection, not the very same bean itself.for (String candidate : candidateNames) {if (isSelfReference(beanName, candidate) (!(descriptor instanceof MultiElementDescriptor) || !beanName.equals(candidate)) isAutowireCandidate(candidate, fallbackDescriptor)) {addCandidateEntry(result, candidate, descriptor, requiredType);}}}}return result;
}总结一下这个函数主要做了以下事情 
先从 IoC 容器中查找指定类型的候选 Bean 集合实例化一个 MapString,Object 的集合result用来存储该类型对应的 候选依赖从 可解析依赖 里查找符合条件的候选并添加进 result 中从 候选 Bean 集合中找到 非自引用候选Bean 指向 当前Bean 或者 候选Bean 的 工厂Bean 执行当前Bean、并且BeanDefinition#autowire-candidate为true的候选Bean加入到result中结果为空的兜底经符合一定条件的候选 Bean 加入到 result 中将 result 返回得到最终的依赖源 
综上我们可以得出一个结论依赖注入的来源包括两方面分别如下 
依赖查找的来源可解析依赖 resolvableDependencies源码位于 org.springframework.beans.factory.support.DefaultListableBeanFactory#resolvableDependencies 
本文总结 
本篇我们介绍了依赖注入的使用方式和其注入原理并追根溯源定位的依赖的来源分析了依赖查找的来源以及依赖注入的来源。大家可以结合本篇文章进入到源码进行研读印象会更深刻。针对 Autowired 注解的使用和原理分析我放在了另一篇一文搞懂Spring Autowired注解的使用及其原理有兴趣的也可以去了解阅读下。