0


spring自动装配原理

为了搞明白自动装配原理,需要知道spring容器管理bean的生命周期

Spring Bean 生命周期流程图

在这里插入图片描述

bean自身方法的生命周期

分为四步:

  1. //执行此段代码,spring容器的bean执行实例化、属性赋值、初始化
  2. ClassPathXmlApplicationContext classPathXmlApplicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
  3. //关闭容器,执行销毁
  4. classPathXmlApplicationContext.close();

1、实例化

  • 读取spring配置文件
  • 通过反射进行bean的实例化(eg:通过BeanFactory实例化)

2、属性赋值

  • 解析自动装配(byName、byType、constractor、default)DI的体现
  • 循环依赖

3、初始化

  • 调用XXXAware回调方法
  • 调用初始化生命周期回调(三种)
  • 如果bean实现aop创建动态代理

4、销毁

  • 在spring容器关闭的时候进行调用
  • 调用初始化生命周期回调

对应上述文字,下图展示了bean装载到spring应用上下文种的一个典型的生命周期过程

@Autowired注解的自动装配过程

先说结论:

@Autowired是在Bean属性赋值阶段进行装配,通过Bean的后置处理器进行解析

1、在创建一个spring上下文的时候在构造函数中注册AutowiredAnnotationBeanPostProcessor

2、在Bean的创建过程中进行解析

  1. 1、在实例化后预解析(解析@Autowired标注的属性、方法,比如:把属性的类型、名称、属性所在的类...元数据缓存)
  2. 2、**在属性赋值阶段真正的注入**(拿到上一步缓存的元数据去ioc容器进行查找,并且返回注入)
  3. a.首先根据解析的元数据拿到类型去容器种查找
  4. *如果查询结果刚好为一个,就将该bean装配给@Autowired指定的数据;
  5. *如果查询的结果不止一个,那么@Autowired会根据名称来查找
  6. *如果上述查找结果为空,那么就会抛出异常。

大致流程图如下:

@Autowired字段注入源码分析

  1. /* ......源码注解过多,只贴一部分有用的
  2. * <h3>Not supported in {@code BeanPostProcessor} or {@code BeanFactoryPostProcessor}</h3>
  3. * <p>Note that actual injection is performed through a
  4. * {@link org.springframework.beans.factory.config.BeanPostProcessor
  5. * BeanPostProcessor} which in turn means that you <em>cannot</em>
  6. * use {@code @Autowired} to inject references into
  7. * {@link org.springframework.beans.factory.config.BeanPostProcessor
  8. * BeanPostProcessor} or
  9. * {@link org.springframework.beans.factory.config.BeanFactoryPostProcessor BeanFactoryPostProcessor}
  10. * types. Please consult the javadoc for the {@link AutowiredAnnotationBeanPostProcessor}
  11. * class (which, by default, checks for the presence of this annotation).
  12. *
  13. * @author Juergen Hoeller
  14. * @author Mark Fisher
  15. * @author Sam Brannen
  16. * @since 2.5
  17. * @see AutowiredAnnotationBeanPostProcessor
  18. * @see Qualifier
  19. * @see Value
  20. */
  21. @Target({ElementType.CONSTRUCTOR, ElementType.METHOD, ElementType.PARAMETER, ElementType.FIELD, ElementType.ANNOTATION_TYPE})
  22. @Retention(RetentionPolicy.RUNTIME)
  23. @Documented
  24. public @interface Autowired {
  25. /**
  26. * Declares whether the annotated dependency is required.
  27. * <p>Defaults to {@code true}.
  28. */
  29. boolean required() default true;
  30. }

1、重点在注释里的一句:

  1. Please consult the javadoc for the {@link AutowiredAnnotationBeanPostProcessor}

2、AutowiredAnnotationBeanPostProcessor是Spring的后置处理器,专门处理@Autowired和@Value注解。查看AutowiredAnnotationBeanPostProcessor类,关注**postProcessMergedBeanDefinition()方法、postProcessPropertyValues()**方法和构造器;

  1. //Spring在每个Bean实例化的时候,调用populateBean进行属性注入的时候,即调用postProcessPropertyValues方法。
  2. @Deprecated
  3. @Override
  4. public PropertyValues postProcessPropertyValues(PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName) {
  5. return postProcessProperties(pvs, bean, beanName);
  6. }
  7. //​Spring容器在每个Bean实例化之后,调用AutowiredAnnotationBeanPostProcessor的postProcessMergedBeanDefinition方法。
  8. @Override
  9. public void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName) {
  10. InjectionMetadata metadata = findAutowiringMetadata(beanName, beanType, null);
  11. metadata.checkConfigMembers(beanDefinition);
  12. }
  13. //AutowiredAnnotationBeanPostProcessor构造器
  14. public AutowiredAnnotationBeanPostProcessor() {
  15. //后置处理器将处理@Autowire注解
  16. this.autowiredAnnotationTypes.add(Autowired.class);
  17. //后置处理器将处理@Value注解
  18. this.autowiredAnnotationTypes.add(Value.class);
  19. try {
  20. //后置处理器将处理javax.inject.Inject JSR-330注解
  21. this.autowiredAnnotationTypes.add((Class<? extends Annotation>)
  22. ClassUtils.forName("javax.inject.Inject", AutowiredAnnotationBeanPostProcessor.class.getClassLoader()));
  23. logger.info("JSR-330 'javax.inject.Inject' annotation found and supported for autowiring");
  24. }
  25. catch (ClassNotFoundException ex) {
  26. // JSR-330 API not available - simply skip.
  27. }
  28. }
  29. @Override
  30. public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) {
  31. //获取指定类中autowire相关注解的元信息
  32. InjectionMetadata metadata = findAutowiringMetadata(beanName, bean.getClass(), pvs);
  33. try {
  34. //对Bean的属性进行自动注入
  35. metadata.inject(bean, beanName, pvs);
  36. }
  37. catch (BeanCreationException ex) {
  38. throw ex;
  39. }
  40. catch (Throwable ex) {
  41. throw new BeanCreationException(beanName, "Injection of autowired dependencies failed", ex);
  42. }
  43. return pvs;
  44. }

3、查看对Bean的属性进行自动注入metadata.inject(bean, beanName, pvs);方法

  1. public void inject(Object target, @Nullable String beanName, @Nullable PropertyValues pvs) throws Throwable {
  2. Collection<InjectedElement> checkedElements = this.checkedElements;
  3. //要注入的字段集合
  4. Collection<InjectedElement> elementsToIterate = (checkedElements != null ? checkedElements : this.injectedElements);
  5. if (!elementsToIterate.isEmpty()) {
  6. for (InjectedElement element : elementsToIterate) {
  7. element.inject(target, beanName, pvs);
  8. }
  9. }
  10. }

4、查看element.inject(target, beanName, pvs);方法

  1. protected void inject(Object target, @Nullable String requestingBeanName, @Nullable PropertyValues pvs)throws Throwable {
  2. if (this.isField) {
  3. Field field = (Field) this.member;
  4. ReflectionUtils.makeAccessible(field);
  5. field.set(target, getResourceToInject(target, requestingBeanName));
  6. }
  7. else {
  8. if (checkPropertySkipping(pvs)) {
  9. return;
  10. }
  11. try {
  12. Method method = (Method) this.member;
  13. ReflectionUtils.makeAccessible(method);
  14. method.invoke(target, getResourceToInject(target, requestingBeanName));
  15. }
  16. catch (InvocationTargetException ex) {
  17. throw ex.getTargetException();
  18. }
  19. }
  20. }

这是element.inject(target, beanName, pvs);的原始方法,它还有两个子类自己实现的方法,如图:

此案例是字段注入分析,查看AutowiredFieldElement

  1. //AutowiredAnnotationBeanPostProcessor.java
  2. @Override
  3. protected void inject(Object bean, @Nullable String beanName, @Nullable PropertyValues pvs) throws Throwable {
  4. //获取要注入的字段
  5. Field field = (Field) this.member;
  6. Object value;
  7. //如果字段的值有缓存
  8. if (this.cached) {
  9. //从缓存中获取字段值value
  10. value = resolvedCachedArgument(beanName, this.cachedFieldValue);
  11. }
  12. //没有缓存
  13. else {
  14. //创建一个字段依赖描述符
  15. DependencyDescriptor desc = new DependencyDescriptor(field, this.required);
  16. desc.setContainingClass(bean.getClass());
  17. Set<String> autowiredBeanNames = new LinkedHashSet<>(1);
  18. Assert.state(beanFactory != null, "No BeanFactory available");
  19. //获取容器中的类型转换器
  20. TypeConverter typeConverter = beanFactory.getTypeConverter();
  21. try {
  22. //核心!获取注入的值
  23. value = beanFactory.resolveDependency(desc, beanName, autowiredBeanNames, typeConverter);
  24. }
  25. catch (BeansException ex) {
  26. throw new UnsatisfiedDependencyException(null, beanName, new InjectionPoint(field), ex);
  27. }
  28. //线程同步,确保容器中数据一致性
  29. synchronized (this) {
  30. //如果字段的值没有缓存
  31. if (!this.cached) {
  32. //字段值不为null,并且required属性为true
  33. if (value != null || this.required) {
  34. this.cachedFieldValue = desc;
  35. //为指定Bean注册依赖Bean
  36. registerDependentBeans(beanName, autowiredBeanNames);
  37. if (autowiredBeanNames.size() == 1) {
  38. String autowiredBeanName = autowiredBeanNames.iterator().next();
  39. //如果容器中有指定名称的Bean对象
  40. if (beanFactory.containsBean(autowiredBeanName)) {
  41. //依赖对象类型和字段类型匹配,默认按类型注入
  42. if (beanFactory.isTypeMatch(autowiredBeanName, field.getType())) {
  43. //创建一个依赖对象的引用,同时缓存
  44. this.cachedFieldValue = new ShortcutDependencyDescriptor(
  45. desc, autowiredBeanName, field.getType());
  46. }
  47. }
  48. }
  49. }
  50. //如果获取的依赖关系为null,且获取required属性为false
  51. else {
  52. //将字段值的缓存设置为null
  53. this.cachedFieldValue = null;
  54. }
  55. //容器已经对当前字段的值缓存
  56. this.cached = true;
  57. }
  58. }
  59. }
  60. //如果字段值不为null
  61. if (value != null) {
  62. //显式使用JDK的反射机制,设置自动的访问控制权限为允许访问
  63. ReflectionUtils.makeAccessible(field);
  64. //为字段赋值
  65. field.set(bean, value);
  66. }
  67. }

从注解@Value/@Autowired中获取要注入的值,之后利用反射set到字段中。 重点就是怎么从注解中获取要注入的值,我们来看核心代码

  1. value = beanFactory.resolveDependency(desc, beanName, autowiredBeanNames, typeConverter);
  1. //DefaultListableBeanFactory.java
  2. public Object resolveDependency(DependencyDescriptor descriptor, @Nullable String requestingBeanName,
  3. @Nullable Set<String> autowiredBeanNames, @Nullable TypeConverter typeConverter) throws BeansException {
  4. descriptor.initParameterNameDiscovery(getParameterNameDiscoverer());
  5. if (Optional.class == descriptor.getDependencyType()) {
  6. return createOptionalDependency(descriptor, requestingBeanName);
  7. }
  8. else if (ObjectFactory.class == descriptor.getDependencyType() ||
  9. ObjectProvider.class == descriptor.getDependencyType()) {
  10. return new DependencyObjectProvider(descriptor, requestingBeanName);
  11. }
  12. else if (javaxInjectProviderClass == descriptor.getDependencyType()) {
  13. return new Jsr330ProviderFactory().createDependencyProvider(descriptor, requestingBeanName);
  14. }
  15. else {
  16. Object result = getAutowireCandidateResolver().getLazyResolutionProxyIfNecessary(
  17. descriptor, requestingBeanName);
  18. if (result == null) {
  19. //真正获取值的代码
  20. result = doResolveDependency(descriptor, requestingBeanName, autowiredBeanNames, typeConverter);
  21. }
  22. return result;
  23. }
  24. }

进行跟踪:

  1. //DefaultListableBeanFactory.java
  2. public Object doResolveDependency(DependencyDescriptor descriptor, @Nullable String beanName,
  3. @Nullable Set<String> autowiredBeanNames, @Nullable TypeConverter typeConverter) throws BeansException {
  4. InjectionPoint previousInjectionPoint = ConstructorResolver.setCurrentInjectionPoint(descriptor);
  5. try {
  6. Object shortcut = descriptor.resolveShortcut(this);
  7. if (shortcut != null) {
  8. return shortcut;
  9. }
  10. //获取字段属性的类型
  11. Class<?> type = descriptor.getDependencyType();
  12. //拿到@Value里的值
  13. Object value = getAutowireCandidateResolver().getSuggestedValue(descriptor);
  14. if (value != null) {
  15. if (value instanceof String) {
  16. String strVal = resolveEmbeddedValue((String) value);
  17. BeanDefinition bd = (beanName != null && containsBean(beanName) ? getMergedBeanDefinition(beanName) : null);
  18. value = evaluateBeanDefinitionString(strVal, bd);
  19. }
  20. TypeConverter converter = (typeConverter != null ? typeConverter : getTypeConverter());
  21. return (descriptor.getField() != null ?
  22. converter.convertIfNecessary(value, type, descriptor.getField()) :
  23. converter.convertIfNecessary(value, type, descriptor.getMethodParameter()));
  24. }
  25. //如果标识@Autowired注解的属性是集合类型,Array,Collection,Map,
  26. // 从这个方法获取@Autowired里的值
  27. <1> Object multipleBeans = resolveMultipleBeans(descriptor, beanName, autowiredBeanNames, typeConverter);
  28. if (multipleBeans != null) {
  29. return multipleBeans;
  30. }
  31. //如果标识@Autowired注解的属性是非集合类型,
  32. // 从这个方法获取@Autowired里的值
  33. <2> Map<String, Object> matchingBeans = findAutowireCandidates(beanName, type, descriptor);
  34. //如果没有符合该类型的Bean
  35. if (matchingBeans.isEmpty()) {
  36. //是否是必须的
  37. if (isRequired(descriptor)) {
  38. //抛出异常
  39. raiseNoMatchingBeanFound(type, descriptor.getResolvableType(), descriptor);
  40. }
  41. return null;
  42. }
  43. String autowiredBeanName;
  44. Object instanceCandidate;
  45. //如果符合该类型的Bean有多个
  46. if (matchingBeans.size() > 1) {
  47. //挑选出最优解
  48. <3> autowiredBeanName = determineAutowireCandidate(matchingBeans, descriptor);
  49. if (autowiredBeanName == null) {
  50. if (isRequired(descriptor) || !indicatesMultipleBeans(type)) {
  51. //抛出异常
  52. return descriptor.resolveNotUnique(type, matchingBeans);
  53. }
  54. else {
  55. // In case of an optional Collection/Map, silently ignore a non-unique case:
  56. // possibly it was meant to be an empty collection of multiple regular beans
  57. // (before 4.3 in particular when we didn't even look for collection beans).
  58. return null;
  59. }
  60. }
  61. instanceCandidate = matchingBeans.get(autowiredBeanName);
  62. }
  63. else {
  64. // We have exactly one match.
  65. Map.Entry<String, Object> entry = matchingBeans.entrySet().iterator().next();
  66. autowiredBeanName = entry.getKey();
  67. instanceCandidate = entry.getValue();
  68. }
  69. if (autowiredBeanNames != null) {
  70. autowiredBeanNames.add(autowiredBeanName);
  71. }
  72. if (instanceCandidate instanceof Class) {
  73. instanceCandidate = descriptor.resolveCandidate(autowiredBeanName, type, this);
  74. }
  75. Object result = instanceCandidate;
  76. if (result instanceof NullBean) {
  77. if (isRequired(descriptor)) {
  78. raiseNoMatchingBeanFound(type, descriptor.getResolvableType(), descriptor);
  79. }
  80. result = null;
  81. }
  82. if (!ClassUtils.isAssignableValue(type, result)) {
  83. throw new BeanNotOfRequiredTypeException(autowiredBeanName, type, instanceCandidate.getClass());
  84. }
  85. return result;
  86. }
  87. finally {
  88. ConstructorResolver.setCurrentInjectionPoint(previousInjectionPoint);
  89. }
  90. }

大致流程就是: 根据字段类型从IOC容器中获取符合的Bean,如果有多个,则挑选出最优的那一个。

<1>处:@Autowired注入集合数组,如Map.List。

<2>处:@Autowired注入非集合数组,即普通的类如Service

<3>处:多个同类型的bean中挑选出最优解

总结:

  1. 在容器启动,**为bean属性赋值**的时候,spring会用后置处理器**AutowiredAnnotationBeanPostProcessor**解析@Autowired注解,来创建属性的实例,然后从IOC容器中根据@Primary@Order@PriorityOrderSpring默认规则挑选出最符合的Bean,利用反射注入到字段中完成赋值;
标签: spring java

本文转载自: https://blog.csdn.net/DQWERww/article/details/125953179
版权归原作者 HarrisDong 所有, 如有侵权,请联系我们删除。

“spring自动装配原理”的评论:

还没有评论