Spring中autowired主要用于装配树形值,其关键类为BeanWrapperImpl,阅读代码发现其关键方法setPropertyValue有如下一段代码。

 1 PropertyHandler ph = getLocalPropertyHandler(actualName);
 2             if (ph == null || !ph.isWritable()) {
 3                 if (pv.isOptional()) {
 4                     if (logger.isDebugEnabled()) {
 5                         logger.debug("Ignoring optional value for property '" + actualName +
 6                                 "' - property not found on bean class [" + getRootClass().getName() + "]");
 7                     }
 8                     return;
 9                 }
10                 else {
11                     throw createNotWritablePropertyException(propertyName);
12                 }
13             }
14             Object oldValue = null;
15             try {
16                 Object originalValue = pv.getValue();
17                 Object valueToApply = originalValue;
18                 if (!Boolean.FALSE.equals(pv.conversionNecessary)) {
19                     if (pv.isConverted()) {
20                         valueToApply = pv.getConvertedValue();
21                     }
22                     else {
23                         if (isExtractOldValueForEditor() && ph.isReadable()) {
24                             try {
25                                 oldValue = ph.getValue();
26                             }
27                             catch (Exception ex) {
28                                 if (ex instanceof PrivilegedActionException) {
29                                     ex = ((PrivilegedActionException) ex).getException();
30                                 }
31                                 if (logger.isDebugEnabled()) {
32                                     logger.debug("Could not read previous value of property '" +
33                                             this.nestedPath + propertyName + "'", ex);
34                                 }
35                             }
36                         }
37                         valueToApply = convertForProperty(
38                                 propertyName, oldValue, originalValue, ph.toTypeDescriptor());
39                     }
40                     pv.getOriginalPropertyValue().conversionNecessary = (valueToApply != originalValue);
41                 }
42                 ph.setValue(this.wrappedObject, valueToApply);

View Code

显然最终都是调用setPropertyValue来设置属性值的。真实注入的时候是发生在getBean的时候,在实例化完成后会调用populateBean方法。查看populateBean方法发现如下代码:

 1 protected void populateBean(String beanName, RootBeanDefinition mbd, BeanWrapper bw) {
 2         PropertyValues pvs = mbd.getPropertyValues();
 3
 4         if (bw == null) {
 5             if (!pvs.isEmpty()) {
 6                 throw new BeanCreationException(
 7                         mbd.getResourceDescription(), beanName, "Cannot apply property values to null instance");
 8             }
 9             else {
10                 // Skip property population phase for null instance.
11                 return;
12             }
13         }
14
15         // Give any InstantiationAwareBeanPostProcessors the opportunity to modify the
16         // state of the bean before properties are set. This can be used, for example,
17         // to support styles of field injection.
18         boolean continueWithPropertyPopulation = true;
19
20         if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
21             for (BeanPostProcessor bp : getBeanPostProcessors()) {
22                 if (bp instanceof InstantiationAwareBeanPostProcessor) {
23                     InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
24                     if (!ibp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) {
25                         continueWithPropertyPopulation = false;
26                         break;
27                     }
28                 }
29             }
30         }
31
32         if (!continueWithPropertyPopulation) {
33             return;
34         }
35
36         if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_NAME ||
37                 mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_TYPE) {
38             MutablePropertyValues newPvs = new MutablePropertyValues(pvs);
39
40             // Add property values based on autowire by name if applicable.
41             if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_NAME) {
42                 autowireByName(beanName, mbd, bw, newPvs);
43             }
44
45             // Add property values based on autowire by type if applicable.
46             if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_TYPE) {
47                 autowireByType(beanName, mbd, bw, newPvs);
48             }
49
50             pvs = newPvs;
51         }
52
53         boolean hasInstAwareBpps = hasInstantiationAwareBeanPostProcessors();
54         boolean needsDepCheck = (mbd.getDependencyCheck() != RootBeanDefinition.DEPENDENCY_CHECK_NONE);
55
56         if (hasInstAwareBpps || needsDepCheck) {
57             PropertyDescriptor[] filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
58             if (hasInstAwareBpps) {
59                 for (BeanPostProcessor bp : getBeanPostProcessors()) {
60                     if (bp instanceof InstantiationAwareBeanPostProcessor) {
61                         InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
62                         pvs = ibp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName);
63                         if (pvs == null) {
64                             return;
65                         }
66                     }
67                 }
68             }
69             if (needsDepCheck) {
70                 checkDependencies(beanName, mbd, filteredPds, pvs);
71             }
72         }
73
74         applyPropertyValues(beanName, mbd, bw, pvs);
75     }

View Code

注意如下代码:

InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
pvs = ibp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName);

在给属性赋值之前会调用InstantiationAwareBeanPostProcessor的postProcessPropertyValues方法,获取最终的PropertyValues。

在Spring注入的InstantionAwaireBeanPostProcessor中比较关键的子类就是处理@Autowired的子类,AutowiredAnnotationBeanPostProcessor。下如战士postProcessPropertyValues的实现过程,只列出了几个关键的方法。

(1) findAutowiringMetadata方法的主要功能是对InjectMetadata添加了本地缓存,真实的解析InjectMetadata会使用反射,添加缓存可以名小减少对反射的依赖。真实的生成InjectMetadata是buildAutowiringMetadata方法。

 1     private InjectionMetadata buildAutowiringMetadata(final Class<?> clazz) {
 2         LinkedList<InjectionMetadata.InjectedElement> elements = new LinkedList<InjectionMetadata.InjectedElement>();
 3         Class<?> targetClass = clazz;
 4
 5         do {
 6             final LinkedList<InjectionMetadata.InjectedElement> currElements =
 7                     new LinkedList<InjectionMetadata.InjectedElement>();
 8
 9             ReflectionUtils.doWithLocalFields(targetClass, new ReflectionUtils.FieldCallback() {
10                 @Override
11                 public void doWith(Field field) throws IllegalArgumentException, IllegalAccessException {
12                     AnnotationAttributes ann = findAutowiredAnnotation(field);
13                     if (ann != null) {
14                         if (Modifier.isStatic(field.getModifiers())) {
15                             if (logger.isWarnEnabled()) {
16                                 logger.warn("Autowired annotation is not supported on static fields: " + field);
17                             }
18                             return;
19                         }
20                         boolean required = determineRequiredStatus(ann);
21                         currElements.add(new AutowiredFieldElement(field, required));
22                     }
23                 }
24             });
25
26             ReflectionUtils.doWithLocalMethods(targetClass, new ReflectionUtils.MethodCallback() {
27                 @Override
28                 public void doWith(Method method) throws IllegalArgumentException, IllegalAccessException {
29                     Method bridgedMethod = BridgeMethodResolver.findBridgedMethod(method);
30                     if (!BridgeMethodResolver.isVisibilityBridgeMethodPair(method, bridgedMethod)) {
31                         return;
32                     }
33                     AnnotationAttributes ann = findAutowiredAnnotation(bridgedMethod);
34                     if (ann != null && method.equals(ClassUtils.getMostSpecificMethod(method, clazz))) {
35                         if (Modifier.isStatic(method.getModifiers())) {
36                             if (logger.isWarnEnabled()) {
37                                 logger.warn("Autowired annotation is not supported on static methods: " + method);
38                             }
39                             return;
40                         }
41                         if (method.getParameterTypes().length == 0) {
42                             if (logger.isWarnEnabled()) {
43                                 logger.warn("Autowired annotation should be used on methods with parameters: " + method);
44                             }
45                         }
46                         boolean required = determineRequiredStatus(ann);
47                         PropertyDescriptor pd = BeanUtils.findPropertyForMethod(bridgedMethod, clazz);
48                         currElements.add(new AutowiredMethodElement(method, required, pd));
49                     }
50                 }
51             });
52
53             elements.addAll(0, currElements);
54             targetClass = targetClass.getSuperclass();
55         }
56         while (targetClass != null && targetClass != Object.class);
57
58         return new InjectionMetadata(clazz, elements);
59     }

buildAutowiringMetadata

其实doWithLocalFields和doWithLocalMethods比较类似,都使用策略模式的实现回调方法来实现。这种回调方式是常用的方法。

 1     ReflectionUtils.doWithLocalFields(targetClass, new ReflectionUtils.FieldCallback() {
 2                 @Override
 3                 public void doWith(Field field) throws IllegalArgumentException, IllegalAccessException {
 4                     AnnotationAttributes ann = findAutowiredAnnotation(field);
 5                     if (ann != null) {
 6                         if (Modifier.isStatic(field.getModifiers())) {
 7                             if (logger.isWarnEnabled()) {
 8                                 logger.warn("Autowired annotation is not supported on static fields: " + field);
 9                             }
10                             return;
11                         }
12                         boolean required = determineRequiredStatus(ann);
13                         currElements.add(new AutowiredFieldElement(field, required));
14                     }
15                 }
16             });

doWithLocalFields

 1     public static void doWithLocalFields(Class<?> clazz, FieldCallback fc) {
 2         for (Field field : getDeclaredFields(clazz)) {
 3             try {
 4                 fc.doWith(field);
 5             }
 6             catch (IllegalAccessException ex) {
 7                 throw new IllegalStateException("Not allowed to access field '" + field.getName() + "': " + ex);
 8             }
 9         }
10     }

doWithLocalFields

注意到@Autowired不支持静态注入的原因,就是增加了判断签名为static的时候,并没有解析。

InjectElement有两个关键子类,AutowiredMethodElement主要解决method上面的注解,AutowiredFieldElement主要解决field上面的注解。不同之处就是field会从容器查找filed对应的bean,method会将每一个参数都注入。其最关键的方法均为resolveDependency方法。其中观察resolveDependency方法的调用中有个关键方法findAutowireCandidates。

 1     protected Map<String, Object> findAutowireCandidates(
 2             String beanName, Class<?> requiredType, DependencyDescriptor descriptor) {
 3
 4         String[] candidateNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(
 5                 this, requiredType, true, descriptor.isEager());
 6         Map<String, Object> result = new LinkedHashMap<String, Object>(candidateNames.length);
 7         for (Class<?> autowiringType : this.resolvableDependencies.keySet()) {
 8             if (autowiringType.isAssignableFrom(requiredType)) {
 9                 Object autowiringValue = this.resolvableDependencies.get(autowiringType);
10                 autowiringValue = AutowireUtils.resolveAutowiringValue(autowiringValue, requiredType);
11                 if (requiredType.isInstance(autowiringValue)) {
12                     result.put(ObjectUtils.identityToString(autowiringValue), autowiringValue);
13                     break;
14                 }
15             }
16         }
17         for (String candidateName : candidateNames) {
18             if (!isSelfReference(beanName, candidateName) && isAutowireCandidate(candidateName, descriptor)) {
19                 addCandidateEntry(result, candidateName, descriptor, requiredType);
20             }
21         }
22         if (result.isEmpty() && !indicatesMultipleBeans(requiredType)) {
23             // Consider fallback matches if the first pass failed to find anything...
24             DependencyDescriptor fallbackDescriptor = descriptor.forFallbackMatch();
25             for (String candidateName : candidateNames) {
26                 if (!isSelfReference(beanName, candidateName) && isAutowireCandidate(candidateName, fallbackDescriptor)) {
27                     addCandidateEntry(result, candidateName, descriptor, requiredType);
28                 }
29             }
30             if (result.isEmpty()) {
31                 // Consider self references before as a final pass
32                 for (String candidateName : candidateNames) {
33                     if (isSelfReference(beanName, candidateName) && isAutowireCandidate(candidateName, fallbackDescriptor)) {
34                         addCandidateEntry(result, candidateName, descriptor, requiredType);
35                     }
36                 }
37             }
38         }
39         return result;
40     }

View Code

首先处理的是resolevableDependencies,如果已经注册依赖,直接从注册的依赖中提取。否则直接调用getType方法获取bean。注册依赖可能是容易被忽略的。

在refresh中就有直接注册依赖的调用:

    protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory) {....//省略部分代码beanFactory.registerResolvableDependency(BeanFactory.class, beanFactory);beanFactory.registerResolvableDependency(ResourceLoader.class, this);beanFactory.registerResolvableDependency(ApplicationEventPublisher.class, this);beanFactory.registerResolvableDependency(ApplicationContext.class, this);......//省略部分代码
        }
}

转载于:https://www.cnblogs.com/dragonfei/p/5973855.html

Spring 之autowired相关推荐

  1. Spring中@Autowired、@Qualifier、@Resource的区别

    转自: Spring中@Autowired.@Qualifier.@Resource的区别_老周聊架构的博客-CSDN博客_qualifier和resource区别1.@Autowired@Autow ...

  2. Spring的@Autowired和@Resource

    @Autowired 当Spring发现@Autowired注解时,将自动在代码上下文中找到和其匹配(默认是类型匹配)的Bean,并自动注入到相应的地方去. 必须确保该类型在IOC容器中只有一个对象: ...

  3. Spring注解@Autowired

    Spring注解@Autowired 一.@Autowired注解作用 1.@Autowired 注解@Autowired是Spring对组件自动装配的一种方式.常用于在一个组件中引入其他组件. // ...

  4. Spring之autowired

    spring提供@autowired注解来对组件进行注入初始化,其底层机制是利用java反射来控制组件的访问, 这简化了我们的编程,省掉了一堆毫无业务逻辑的set方法. 但是我们需要注意的是,auto ...

  5. Spring中@Autowired注解、@Resource注解的区别

    Spring不但支持自己定义的@Autowired注解,还支持几个由JSR-250规范定义的注解,它们分别是@Resource.@PostConstruct以及@PreDestroy. @Resour ...

  6. 使用Spring的@Autowired 实现DAO, Service, Controller三层的注入(转)

    简述: 结合Spring和Hibernate进行开发 使用@Autowired实现依赖注入, 实现一个学生注册的功能,做一个技术原型 从DAO(Repository) -> Service -& ...

  7. Spring中@Autowired和@Resource区别

    Spring可以基于注解方式配置并注入依赖.在Java代码中使用@Resource或者@Autowired注解方式注入. 1. @Resource: 1)默认按照名称装配注入,只有当找不到与名称nam ...

  8. Spring中 @Autowired注解与@Resource注解的区别

    相同点: @Resource的作用相当于@Autowired,均可标注在字段或属性的setter方法上. 不同点: (1)提供方:@Autowired是由org.springframework.bea ...

  9. 为什么使用Spring的@autowired注解后就不用写setter了

    问题: 在java中如果属性或者方法的标识符是private的话,是不能直接访问这个属性的,必须通过setter和getter方法才能够访问这个属性,那么使用@autowired注解来完成属性的依赖注 ...

  10. spring的Autowired和@Resource的区别是什么

    2019独角兽企业重金招聘Python工程师标准>>> @Resource默认按照名称方式进行bean匹配,@Autowired默认按照类型方式进行bean匹配 @Resource( ...

最新文章

  1. 我的Java开发学习之旅------Java经典排序算法之希尔排序
  2. nginx请求频率限制模块ngx_http_limit_req_module
  3. 【Linux】一步一步学Linux——as命令(260)
  4. 01-spring配置详解
  5. DPDK网络处理模块划分
  6. 【入门教程】无人机烧录过程
  7. linux 桥接stp原理,Linux操作系统网桥源码框架初步分析
  8. Python入门--文件的读写,相对路径,绝对路径
  9. android之隐藏状态栏、图标、布局
  10. html音乐if代码如何使用,关于html:如何在带有JavaScript代码的if条件中使用函数方法?...
  11. linux shell 脚本 pdf,Shell脚本学习指南 中文PDF版
  12. 微信定时自动发消息。每天和你的obj准时说晚安
  13. Excel中如何将列数据转换为行数据
  14. 高中计算机课听课记录表,信息技术课听课记录
  15. 渗透tools之Lizard
  16. php百度网盘登录,php登陆状态百度网盘获取文件下载链接【思路|部分代码】
  17. 公众号头条文章数据接口 API
  18. 为什么计算机无法读取u盘,电脑无法识别读取U盘怎么办?逐一排查解决问题
  19. aws的eks平滑删除work节点实现降配
  20. 驼峰命名法和下划线命名法互转

热门文章

  1. 计算机逻辑运算进位,二进位数进行逻辑运算1010AND1001的运算结果
  2. 索引组织表:万物皆索引
  3. Hbase shell练习题
  4. spark与Hive的整合入门
  5. 常见的云计算安全问题
  6. LeetCode:Path Sum
  7. Qt编程之QtScript
  8. IIS 发布的FTP提供下载时的转码问题
  9. Hi,我们的代码重构了
  10. DHTML【11】--DOM