Spring 之autowired

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);
        ......//省略部分代码      
        }
}
  

 

posted @ 2016-10-23 17:09  dragonfei  阅读(949)  评论(0编辑  收藏  举报