• Spring-依赖注入


    Spring中到底有几种依赖注入的方式?

    • 手动注入

      a)set方式注入

      b)构造方法注入

    • 自动注入

      a)XML的autowire自动注入

      b) @Autowired注解的自动注入

    属性填充部分源码:

    1. /**
    2. * Populate the bean instance in the given BeanWrapper with the property values
    3. * from the bean definition.
    4. * @param beanName the name of the bean
    5. * @param mbd the bean definition for the bean
    6. * @param bw the BeanWrapper with bean instance
    7. */
    8. @SuppressWarnings("deprecation") // for postProcessPropertyValues
    9. protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) {
    10. if (bw == null) {
    11. if (mbd.hasPropertyValues()) {
    12. throw new BeanCreationException(
    13. mbd.getResourceDescription(), beanName, "Cannot apply property values to null instance");
    14. }
    15. else {
    16. // Skip property population phase for null instance.
    17. return;
    18. }
    19. }
    20. // Give any InstantiationAwareBeanPostProcessors the opportunity to modify the
    21. // state of the bean before properties are set. This can be used, for example,
    22. // to support styles of field injection.
    23. // 实例化之后,属性设置之前
    24. if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
    25. for (InstantiationAwareBeanPostProcessor bp : getBeanPostProcessorCache().instantiationAware) {
    26. if (!bp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) {
    27. return;
    28. }
    29. }
    30. }
    31. PropertyValues pvs = (mbd.hasPropertyValues() ? mbd.getPropertyValues() : null);
    32. int resolvedAutowireMode = mbd.getResolvedAutowireMode();
    33. if (resolvedAutowireMode == AUTOWIRE_BY_NAME || resolvedAutowireMode == AUTOWIRE_BY_TYPE) {
    34. // MutablePropertyValues是PropertyValues具体的实现类
    35. MutablePropertyValues newPvs = new MutablePropertyValues(pvs);
    36. // Add property values based on autowire by name if applicable.
    37. if (resolvedAutowireMode == AUTOWIRE_BY_NAME) {
    38. autowireByName(beanName, mbd, bw, newPvs);
    39. }
    40. // Add property values based on autowire by type if applicable.
    41. if (resolvedAutowireMode == AUTOWIRE_BY_TYPE) {
    42. autowireByType(beanName, mbd, bw, newPvs);
    43. }
    44. pvs = newPvs;
    45. }
    46. boolean hasInstAwareBpps = hasInstantiationAwareBeanPostProcessors();
    47. boolean needsDepCheck = (mbd.getDependencyCheck() != AbstractBeanDefinition.DEPENDENCY_CHECK_NONE);
    48. PropertyDescriptor[] filteredPds = null;
    49. if (hasInstAwareBpps) {
    50. if (pvs == null) {
    51. pvs = mbd.getPropertyValues();
    52. }
    53. for (InstantiationAwareBeanPostProcessor bp : getBeanPostProcessorCache().instantiationAware) {
    54. // 这里会调用AutowiredAnnotationBeanPostProcessor的postProcessProperties()方法,会直接给对象中的属性赋值
    55. // AutowiredAnnotationBeanPostProcessor内部并不会处理pvs,直接返回了
    56. PropertyValues pvsToUse = bp.postProcessProperties(pvs, bw.getWrappedInstance(), beanName);
    57. if (pvsToUse == null) {
    58. if (filteredPds == null) {
    59. filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
    60. }
    61. pvsToUse = bp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName);
    62. if (pvsToUse == null) {
    63. return;
    64. }
    65. }
    66. pvs = pvsToUse;
    67. }
    68. }
    69. if (needsDepCheck) {
    70. if (filteredPds == null) {
    71. filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
    72. }
    73. checkDependencies(beanName, mbd, filteredPds, pvs);
    74. }
    75. // 如果当前Bean中的BeanDefinition中设置了PropertyValues,那么最终将是PropertyValues中的值,覆盖@Autowired
    76. if (pvs != null) {
    77. applyPropertyValues(beanName, mbd, bw, pvs);
    78. }
    79. }
    80. /**
    81. * Fill in any missing property values with references to
    82. * other beans in this factory if autowire is set to "byName".
    83. * @param beanName the name of the bean we're wiring up.
    84. * Useful for debugging messages; not used functionally.
    85. * @param mbd bean definition to update through autowiring
    86. * @param bw the BeanWrapper from which we can obtain information about the bean
    87. * @param pvs the PropertyValues to register wired objects with
    88. */
    89. protected void autowireByName(
    90. String beanName, AbstractBeanDefinition mbd, BeanWrapper bw, MutablePropertyValues pvs) {
    91. // 当前Bean中能进行自动注入的属性名
    92. String[] propertyNames = unsatisfiedNonSimpleProperties(mbd, bw);
    93. // 遍历每个属性名,并去获取Bean对象,并设置到pvs中
    94. for (String propertyName : propertyNames) {
    95. if (containsBean(propertyName)) {
    96. Object bean = getBean(propertyName);
    97. pvs.add(propertyName, bean);
    98. // 记录一下propertyName对应的Bean被beanName给依赖了
    99. registerDependentBean(propertyName, beanName);
    100. if (logger.isTraceEnabled()) {
    101. logger.trace("Added autowiring by name from bean name '" + beanName +
    102. "' via property '" + propertyName + "' to bean named '" + propertyName + "'");
    103. }
    104. }
    105. else {
    106. if (logger.isTraceEnabled()) {
    107. logger.trace("Not autowiring property '" + propertyName + "' of bean '" + beanName +
    108. "' by name: no matching bean found");
    109. }
    110. }
    111. }
    112. }
    113. /**
    114. * Abstract method defining "autowire by type" (bean properties by type) behavior.
    115. *

      This is like PicoContainer default, in which there must be exactly one bean

    116. * of the property type in the bean factory. This makes bean factories simple to
    117. * configure for small namespaces, but doesn't work as well as standard Spring
    118. * behavior for bigger applications.
    119. * @param beanName the name of the bean to autowire by type
    120. * @param mbd the merged bean definition to update through autowiring
    121. * @param bw the BeanWrapper from which we can obtain information about the bean
    122. * @param pvs the PropertyValues to register wired objects with
    123. */
    124. protected void autowireByType(
    125. String beanName, AbstractBeanDefinition mbd, BeanWrapper bw, MutablePropertyValues pvs) {
    126. TypeConverter converter = getCustomTypeConverter();
    127. if (converter == null) {
    128. converter = bw;
    129. }
    130. Set autowiredBeanNames = new LinkedHashSet<>(4);
    131. // 当前Bean中能进行自动注入的属性名
    132. String[] propertyNames = unsatisfiedNonSimpleProperties(mbd, bw);
    133. for (String propertyName : propertyNames) {
    134. try {
    135. PropertyDescriptor pd = bw.getPropertyDescriptor(propertyName);
    136. // Don't try autowiring by type for type Object: never makes sense,
    137. // even if it technically is a unsatisfied, non-simple property.
    138. if (Object.class != pd.getPropertyType()) {
    139. MethodParameter methodParam = BeanUtils.getWriteMethodParameter(pd);
    140. // Do not allow eager init for type matching in case of a prioritized post-processor.
    141. // eager表示立即初始化,表示在根据类型查找Bean时,允不允许进行Bean的创建,如果当前bean实现了PriorityOrdered,那么则不允许
    142. // 为什么不允许,因为我自己是PriorityOrdered,是优先级最高的,不能有比我创建得更早的
    143. boolean eager = !(bw.getWrappedInstance() instanceof PriorityOrdered);
    144. DependencyDescriptor desc = new AutowireByTypeDependencyDescriptor(methodParam, eager);
    145. // 根据类型找到的结果
    146. Object autowiredArgument = resolveDependency(desc, beanName, autowiredBeanNames, converter);
    147. if (autowiredArgument != null) {
    148. pvs.add(propertyName, autowiredArgument);
    149. }
    150. for (String autowiredBeanName : autowiredBeanNames) {
    151. registerDependentBean(autowiredBeanName, beanName);
    152. if (logger.isTraceEnabled()) {
    153. logger.trace("Autowiring by type from bean name '" + beanName + "' via property '" +
    154. propertyName + "' to bean named '" + autowiredBeanName + "'");
    155. }
    156. }
    157. autowiredBeanNames.clear();
    158. }
    159. }
    160. catch (BeansException ex) {
    161. throw new UnsatisfiedDependencyException(mbd.getResourceDescription(), beanName, propertyName, ex);
    162. }
    163. }
    164. }
    165. /**
    166. * Return an array of non-simple bean properties that are unsatisfied.
    167. * These are probably unsatisfied references to other beans in the
    168. * factory. Does not include simple properties like primitives or Strings.
    169. * @param mbd the merged bean definition the bean was created with
    170. * @param bw the BeanWrapper the bean was created with
    171. * @return an array of bean property names
    172. * @see org.springframework.beans.BeanUtils#isSimpleProperty
    173. */
    174. protected String[] unsatisfiedNonSimpleProperties(AbstractBeanDefinition mbd, BeanWrapper bw) {
    175. Set result = new TreeSet<>();
    176. PropertyValues pvs = mbd.getPropertyValues();
    177. PropertyDescriptor[] pds = bw.getPropertyDescriptors();
    178. // 什么样的属性能进行自动注入?
    179. // 1.该属性有对应的set方法
    180. // 2.没有在ignoredDependencyTypes中
    181. // 3.如果该属性对应的set方法是实现的某个接口中所定义的,那么接口没有在ignoredDependencyInterfaces中
    182. // 4.属性类型不是简单类型,比如int、Integer、int[]
    183. for (PropertyDescriptor pd : pds) {
    184. if (pd.getWriteMethod() != null && !isExcludedFromDependencyCheck(pd) && !pvs.contains(pd.getName()) &&
    185. !BeanUtils.isSimpleProperty(pd.getPropertyType())) {
    186. result.add(pd.getName());
    187. }
    188. }
    189. return StringUtils.toStringArray(result);
    190. }

    XML的autowire自动注入

    1. // Bean的自动注入模式包括:byType、byName、constructor、default、no

    注意:上面这种写法Spring会自动给所有属性赋值,不需要在属性上添加@Autowired注解,但是需要属性对应的set方法

    get方法的定义: 方法参数个数为0个,并且(方法名字以"get"开头或者方法名字以"is"开头并且方法的返回类型为boolean)

    set方法的定义:方法参数个数为1个,并且(方法名字以"set"开头并且方法返回类型为void)

    在创建Bean的过程-填充属性时,Spring会去解析当前类,把当前类的所有方法都解析出来,解析每个方法得到对应的PropertyDescriptor对象(属性描述器)

    1. public class PropertyDescriptor extends FeatureDescriptor
    2. {
    3. // get方法对应返回值类型,set方法对应唯一参数类型
    4. private Reference> propertyTypeRef;
    5. // get方法的Method对象的引用
    6. private final MethodRef readMethodRef = new MethodRef();
    7. // set方法的Method对象的引用
    8. private final MethodRef writeMethodRef = new MethodRef();
    9. private Reference> propertyEditorClassRef;
    10. private boolean bound;
    11. private boolean constrained;
    12. // The base name of the method name which will be prefixed with the
    13. // read and write method. If name == "foo" then the baseName is "Foo"
    14. private String baseName;
    15. // set方法的名字
    16. private String writeMethodName;
    17. // get方法的名字
    18. private String readMethodName;
    19. ... ...
    20. }

    Spring通过byName自动填充属性流程:

    1、找到所有set方法所对应的XXX部分的名字

    (public void setXXX(XXX xxx){ ... ...})

    2、根据XXX部分的名字去获取bean

    Spring通过byType自动填充属性流程:

    1、获取到set方法中的唯一参数的类型,并且根据该类型去容器中获取bean

    (public void setXXX(XXX xxx){ ... ...})

    2、如果找到多个会报错

    Spring通过constructor自动填充属性流程:因为推断构造方法,所以只考虑一个有参构造方法的情况

    1、利用构造方法的参数信息从Spring容器中去找bean

    2、找到bean之后作为参数传给构造方法,从而实例化得到一个bean对象,并完成属性赋值

    (属性赋值的代码得程序员来写,this.XXX = XXX)

    构造方法注入相当于byType+byName,普通的byType是根据set方法中的参数类型去找bean,找到多个会报错,而constructor就是通过构造方法中的参数类型去找bean,如果找到多个会根据参数名确定。

    no,表示关闭autowire

    default,表示默认值 标签可以定义在里面,此时设置的autowire属性为default,就会去使用标签中设置的注入方式,作为默认

    为什么平时都是用的@Autowired注解?而没有用XML自动注入方式呢?

    官方描述:

    Essentially, the @Autowired annotation provides the same capabilities as described in Autowiring Collaborators but with more fine‐grained control and wider applicability

    翻译:从本质上讲,@Autowired注解提供了与autowire相同的功能,但是拥有更细粒度的控制和更广泛的适用性。

    XML中的autowire控制的是整个bean的所有属性,而@Autowired注解是直接写在某个属性、某个set方法、某个构造方法上的。

    @Autowired注解的自动注入

    @Autowired注解,是byType和byName的结合

    @Autowired注解可以写在:

    1、属性上:先根据属性类型去找Bean,如果找到多个再根据属性名确定一个

    2、构造方法上:先根据方法参数类型去找Bean,如果找到多个再根据参数名确定一个

    3、set方法上:先根据方法参数类型去找Bean,如果找到多个再根据参数名确定一个

    底层用到:属性注入、set方法注入、构造方法注入

  • 相关阅读:
    MySQL:基本查询 | 表的增删改查
    玩转数组高级技法,成为JS高手
    股票的涨跌答案
    V831——车牌识别
    实战经验分享FastAPI 是什么
    GPO:在 Start/Logon 中使用 PowerShell 脚本
    Centos8安装docker并配置Kali Linux图形化界面
    2022年中科磐云——服务器内部信息获取 解析flag
    Java 1.8引入StringJoiner,用与字符串拼接
    NIFI实现JSON转SQL并插入到数据库表中
  • 原文地址:https://blog.csdn.net/weixin_58482311/article/details/134236924