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);
显然最终都是调用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 }
注意如下代码:
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 }
其实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 });
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 }
注意到@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 }
首先处理的是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); ......//省略部分代码 } }