@Autowired和@Resource 解析
准备
| 1.通过前面部分的spring源码解析, 我们知道BeanPostProcessor, 会在普通bean实例化之前实例化并初始化完成!并在bean的整个实例化和初始化过程前后执行其加强的方法; |
| 2.@Autowired和@Resource都是通过BeanPostProcessor进行处理的, 处理的时机是在bean实例化后, 属性注入时执行, 即AbstractAutowireCapableBeanFactory#populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw)方法中 |
| 3.@Autowired的实现是通过AutowiredAnnotationBeanPostProcessor后置处理器完成的 |
启动类
| public class AutowireStarter { |
| public static void main(String[] args) { |
| ApplicationContext applicationContext = new AnnotationConfigApplicationContext(AutowireConfig.class); |
| } |
| } |
配置类
| @Configuration |
| @ComponentScan("com.tca.spring.framework.learning.ioc.autowire") |
| public class AutowireConfig { |
| } |
普通bean
| @Component |
| public class A { |
| @Autowired |
| private B b; |
| } |
| @Component |
| public class B { |
| } |
AbstractAutowireCapableBeanFactory#populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw)
| |
| |
| |
| |
| |
| |
| |
| |
| @SuppressWarnings("deprecation") |
| protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) { |
| |
| if (bw == null) { |
| if (mbd.hasPropertyValues()) { |
| throw new BeanCreationException( |
| mbd.getResourceDescription(), beanName, "Cannot apply property values to null instance"); |
| } |
| else { |
| |
| return; |
| } |
| } |
| |
| |
| |
| |
| |
| boolean continueWithPropertyPopulation = true; |
| |
| |
| |
| |
| |
| |
| if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) { |
| for (BeanPostProcessor bp : getBeanPostProcessors()) { |
| if (bp instanceof InstantiationAwareBeanPostProcessor) { |
| InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp; |
| if (!ibp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) { |
| continueWithPropertyPopulation = false; |
| break; |
| } |
| } |
| } |
| } |
| |
| if (!continueWithPropertyPopulation) { |
| return; |
| } |
| |
| PropertyValues pvs = (mbd.hasPropertyValues() ? mbd.getPropertyValues() : null); |
| |
| if (mbd.getResolvedAutowireMode() == AUTOWIRE_BY_NAME || mbd.getResolvedAutowireMode() == AUTOWIRE_BY_TYPE) { |
| MutablePropertyValues newPvs = new MutablePropertyValues(pvs); |
| |
| if (mbd.getResolvedAutowireMode() == AUTOWIRE_BY_NAME) { |
| autowireByName(beanName, mbd, bw, newPvs); |
| } |
| |
| if (mbd.getResolvedAutowireMode() == AUTOWIRE_BY_TYPE) { |
| autowireByType(beanName, mbd, bw, newPvs); |
| } |
| pvs = newPvs; |
| } |
| |
| boolean hasInstAwareBpps = hasInstantiationAwareBeanPostProcessors(); |
| |
| boolean needsDepCheck = (mbd.getDependencyCheck() != AbstractBeanDefinition.DEPENDENCY_CHECK_NONE); |
| |
| PropertyDescriptor[] filteredPds = null; |
| if (hasInstAwareBpps) { |
| if (pvs == null) { |
| pvs = mbd.getPropertyValues(); |
| } |
| |
| |
| |
| |
| |
| for (BeanPostProcessor bp : getBeanPostProcessors()) { |
| if (bp instanceof InstantiationAwareBeanPostProcessor) { |
| InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp; |
| PropertyValues pvsToUse = ibp.postProcessProperties(pvs, bw.getWrappedInstance(), beanName); |
| if (pvsToUse == null) { |
| if (filteredPds == null) { |
| filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching); |
| } |
| pvsToUse = ibp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName); |
| if (pvsToUse == null) { |
| return; |
| } |
| } |
| pvs = pvsToUse; |
| } |
| } |
| } |
| |
| if (needsDepCheck) { |
| if (filteredPds == null) { |
| filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching); |
| } |
| checkDependencies(beanName, mbd, filteredPds, pvs); |
| } |
| |
| if (pvs != null) { |
| applyPropertyValues(beanName, mbd, bw, pvs); |
| } |
| } |
问题解答:
1.如何让@Autowired, @Resource等注解同时失效, 即不能实现注入
自定义InstantiationAwareBeanPostProcessor接口实现类并注入到容器中,重写方法postProcessAfterInstantiation(),这个方法默认返回true,我们自定义的将其返回false即可【原理:第五次使用bpp时,会调用所有InstantiationAwareBeanPostProcessor的postProcessAfterInstantiation方法,判断是否需要属性注入】
| @Component |
| public class CustomInstantiationAwareBeanPostProcessor implements InstantiationAwareBeanPostProcessor { |
| |
| @Override |
| public boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException { |
| return false; |
| } |
| } |
1.@Autowired解析
1.1 AutowiredAnnotationBeanPostProcessor#postProcessProperties(PropertyValues pvs, Object bean, String beanName)
| |
| |
| |
| @Override |
| public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) { |
| |
| InjectionMetadata metadata = findAutowiringMetadata(beanName, bean.getClass(), pvs); |
| try { |
| |
| metadata.inject(bean, beanName, pvs); |
| } |
| catch (BeanCreationException ex) { |
| throw ex; |
| } |
| catch (Throwable ex) { |
| throw new BeanCreationException(beanName, "Injection of autowired dependencies failed", ex); |
| } |
| return pvs; |
| } |
1.2 AutowiredAnnotationBeanPostProcessor#findAutowiringMetadata(String beanName, Class<?> clazz, @Nullable PropertyValues pvs)
| private InjectionMetadata findAutowiringMetadata(String beanName, Class<?> clazz, @Nullable PropertyValues pvs) { |
| |
| |
| String cacheKey = (StringUtils.hasLength(beanName) ? beanName : clazz.getName()); |
| |
| |
| InjectionMetadata metadata = this.injectionMetadataCache.get(cacheKey); |
| if (InjectionMetadata.needsRefresh(metadata, clazz)) { |
| synchronized (this.injectionMetadataCache) { |
| metadata = this.injectionMetadataCache.get(cacheKey); |
| if (InjectionMetadata.needsRefresh(metadata, clazz)) { |
| if (metadata != null) { |
| metadata.clear(pvs); |
| } |
| |
| metadata = buildAutowiringMetadata(clazz); |
| this.injectionMetadataCache.put(cacheKey, metadata); |
| } |
| } |
| } |
| return metadata; |
| } |
问题解答:
1.普通bean的metadata是什么时候放入injectionMetadataCache缓存中的?
| 1.在AbstractAutowireCapableBeanFactory |
| instanceWrapper = createBeanInstance(beanName, mbd, args); 方法之后, 会第三次使用BeanPostProcessor, |
| applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName); 在这个方法中, 会调用所有MergedBeanDefinitionPostProcessor对象的postProcessMergedBeanDefinition()方法; |
| 2.我们内置的MergedBeanDefinitionPostProcessor有三个: |
| CommonAnnotationBeanPostProcessor |
| AutowiredAnnotationBeanPostProcessor |
| ApplicationListenerDetector |
| 在 AutowiredAnnotationBeanPostProcessor执行postProcessMergedBeanDefinition()方法时, 会解析当前bean的字段, 封装成metadata放入缓存中, AutowiredAnnotationBeanPostProcessor |
1.3 AutowiredAnnotationBeanPostProcessor#buildAutowiringMetadata(final Class<?> clazz)
| private InjectionMetadata buildAutowiringMetadata(final Class<?> clazz) { |
| List<InjectionMetadata.InjectedElement> elements = new ArrayList<>(); |
| Class<?> targetClass = clazz; |
| |
| do { |
| final List<InjectionMetadata.InjectedElement> currElements = new ArrayList<>(); |
| |
| ReflectionUtils.doWithLocalFields(targetClass, field -> { |
| |
| AnnotationAttributes ann = findAutowiredAnnotation(field); |
| if (ann != null) { |
| if (Modifier.isStatic(field.getModifiers())) { |
| if (logger.isInfoEnabled()) { |
| logger.info("Autowired annotation is not supported on static fields: " + field); |
| } |
| return; |
| } |
| |
| boolean required = determineRequiredStatus(ann); |
| |
| currElements.add(new AutowiredFieldElement(field, required)); |
| } |
| }); |
| |
| |
| ReflectionUtils.doWithLocalMethods(targetClass, method -> { |
| Method bridgedMethod = BridgeMethodResolver.findBridgedMethod(method); |
| if (!BridgeMethodResolver.isVisibilityBridgeMethodPair(method, bridgedMethod)) { |
| return; |
| } |
| AnnotationAttributes ann = findAutowiredAnnotation(bridgedMethod); |
| if (ann != null && method.equals(ClassUtils.getMostSpecificMethod(method, clazz))) { |
| if (Modifier.isStatic(method.getModifiers())) { |
| if (logger.isInfoEnabled()) { |
| logger.info("Autowired annotation is not supported on static methods: " + method); |
| } |
| return; |
| } |
| if (method.getParameterCount() == 0) { |
| if (logger.isInfoEnabled()) { |
| logger.info("Autowired annotation should only be used on methods with parameters: " + method); |
| } |
| } |
| boolean required = determineRequiredStatus(ann); |
| PropertyDescriptor pd = BeanUtils.findPropertyForMethod(bridgedMethod, clazz); |
| currElements.add(new AutowiredMethodElement(method, required, pd)); |
| } |
| }); |
| |
| elements.addAll(0, currElements); |
| targetClass = targetClass.getSuperclass(); |
| } |
| while (targetClass != null && targetClass != Object.class); |
| |
| return new InjectionMetadata(clazz, elements); |
| } |
| public void inject(Object target, @Nullable String beanName, @Nullable PropertyValues pvs) throws Throwable { |
| Collection<InjectedElement> checkedElements = this.checkedElements; |
| Collection<InjectedElement> elementsToIterate = |
| (checkedElements != null ? checkedElements : this.injectedElements); |
| if (!elementsToIterate.isEmpty()) { |
| for (InjectedElement element : elementsToIterate) { |
| if (logger.isTraceEnabled()) { |
| logger.trace("Processing injected element of bean '" + beanName + "': " + element); |
| } |
| |
| |
| element.inject(target, beanName, pvs); |
| } |
| } |
| } |
| protected void inject(Object bean, @Nullable String beanName, @Nullable PropertyValues pvs) throws Throwable { |
| |
| |
| Field field = (Field) this.member; |
| Object value; |
| |
| if (this.cached) { |
| value = resolvedCachedArgument(beanName, this.cachedFieldValue); |
| } |
| else { |
| |
| DependencyDescriptor desc = new DependencyDescriptor(field, this.required); |
| desc.setContainingClass(bean.getClass()); |
| Set<String> autowiredBeanNames = new LinkedHashSet<>(1); |
| Assert.state(beanFactory != null, "No BeanFactory available"); |
| |
| TypeConverter typeConverter = beanFactory.getTypeConverter(); |
| try { |
| |
| value = beanFactory.resolveDependency(desc, beanName, autowiredBeanNames, typeConverter); |
| } |
| catch (BeansException ex) { |
| throw new UnsatisfiedDependencyException(null, beanName, new InjectionPoint(field), ex); |
| } |
| synchronized (this) { |
| if (!this.cached) { |
| if (value != null || this.required) { |
| this.cachedFieldValue = desc; |
| registerDependentBeans(beanName, autowiredBeanNames); |
| if (autowiredBeanNames.size() == 1) { |
| String autowiredBeanName = autowiredBeanNames.iterator().next(); |
| if (beanFactory.containsBean(autowiredBeanName) && |
| beanFactory.isTypeMatch(autowiredBeanName, field.getType())) { |
| this.cachedFieldValue = new ShortcutDependencyDescriptor( |
| desc, autowiredBeanName, field.getType()); |
| } |
| } |
| } |
| else { |
| this.cachedFieldValue = null; |
| } |
| this.cached = true; |
| } |
| } |
| } |
| |
| if (value != null) { |
| ReflectionUtils.makeAccessible(field); |
| field.set(bean, value); |
| } |
| } |
1.6 DefaultListableBeanFactory#resolveDependency(DependencyDescriptor descriptor, @Nullable String requestingBeanName,
@Nullable Set<String> autowiredBeanNames, @Nullable TypeConverter typeConverter)
| @Override |
| @Nullable |
| public Object resolveDependency(DependencyDescriptor descriptor, @Nullable String requestingBeanName, |
| @Nullable Set<String> autowiredBeanNames, @Nullable TypeConverter typeConverter) throws BeansException { |
| |
| descriptor.initParameterNameDiscovery(getParameterNameDiscoverer()); |
| if (Optional.class == descriptor.getDependencyType()) { |
| return createOptionalDependency(descriptor, requestingBeanName); |
| } |
| else if (ObjectFactory.class == descriptor.getDependencyType() || |
| ObjectProvider.class == descriptor.getDependencyType()) { |
| return new DependencyObjectProvider(descriptor, requestingBeanName); |
| } |
| else if (javaxInjectProviderClass == descriptor.getDependencyType()) { |
| return new Jsr330Factory().createDependencyProvider(descriptor, requestingBeanName); |
| } |
| else { |
| |
| Object result = getAutowireCandidateResolver().getLazyResolutionProxyIfNecessary( |
| descriptor, requestingBeanName); |
| if (result == null) { |
| |
| |
| result = doResolveDependency(descriptor, requestingBeanName, autowiredBeanNames, typeConverter); |
| } |
| return result; |
| } |
| } |
1.7 DefaultListableBeanFactory#doResolveDependency(DependencyDescriptor descriptor, @Nullable String beanName,
@Nullable Set<String> autowiredBeanNames, @Nullable TypeConverter typeConverter)
| @Nullable |
| public Object doResolveDependency(DependencyDescriptor descriptor, @Nullable String beanName, |
| @Nullable Set<String> autowiredBeanNames, @Nullable TypeConverter typeConverter) throws BeansException { |
| |
| InjectionPoint previousInjectionPoint = ConstructorResolver.setCurrentInjectionPoint(descriptor); |
| try { |
| |
| Object shortcut = descriptor.resolveShortcut(this); |
| if (shortcut != null) { |
| return shortcut; |
| } |
| |
| Class<?> type = descriptor.getDependencyType(); |
| Object value = getAutowireCandidateResolver().getSuggestedValue(descriptor); |
| |
| if (value != null) { |
| if (value instanceof String) { |
| String strVal = resolveEmbeddedValue((String) value); |
| BeanDefinition bd = (beanName != null && containsBean(beanName) ? |
| getMergedBeanDefinition(beanName) : null); |
| value = evaluateBeanDefinitionString(strVal, bd); |
| } |
| TypeConverter converter = (typeConverter != null ? typeConverter : getTypeConverter()); |
| try { |
| return converter.convertIfNecessary(value, type, descriptor.getTypeDescriptor()); |
| } |
| catch (UnsupportedOperationException ex) { |
| |
| return (descriptor.getField() != null ? |
| converter.convertIfNecessary(value, type, descriptor.getField()) : |
| converter.convertIfNecessary(value, type, descriptor.getMethodParameter())); |
| } |
| } |
| |
| Object multipleBeans = resolveMultipleBeans(descriptor, beanName, autowiredBeanNames, typeConverter); |
| if (multipleBeans != null) { |
| return multipleBeans; |
| } |
| |
| Map<String, Object> matchingBeans = findAutowireCandidates(beanName, type, descriptor); |
| if (matchingBeans.isEmpty()) { |
| if (isRequired(descriptor)) { |
| raiseNoMatchingBeanFound(type, descriptor.getResolvableType(), descriptor); |
| } |
| return null; |
| } |
| |
| String autowiredBeanName; |
| Object instanceCandidate; |
| |
| if (matchingBeans.size() > 1) { |
| |
| autowiredBeanName = determineAutowireCandidate(matchingBeans, descriptor); |
| if (autowiredBeanName == null) { |
| if (isRequired(descriptor) || !indicatesMultipleBeans(type)) { |
| return descriptor.resolveNotUnique(descriptor.getResolvableType(), matchingBeans); |
| } |
| else { |
| |
| |
| |
| return null; |
| } |
| } |
| instanceCandidate = matchingBeans.get(autowiredBeanName); |
| } |
| else { |
| |
| |
| Map.Entry<String, Object> entry = matchingBeans.entrySet().iterator().next(); |
| |
| autowiredBeanName = entry.getKey(); |
| |
| instanceCandidate = entry.getValue(); |
| } |
| |
| if (autowiredBeanNames != null) { |
| autowiredBeanNames.add(autowiredBeanName); |
| } |
| if (instanceCandidate instanceof Class) { |
| |
| instanceCandidate = descriptor.resolveCandidate(autowiredBeanName, type, this); |
| } |
| Object result = instanceCandidate; |
| if (result instanceof NullBean) { |
| if (isRequired(descriptor)) { |
| raiseNoMatchingBeanFound(type, descriptor.getResolvableType(), descriptor); |
| } |
| result = null; |
| } |
| if (!ClassUtils.isAssignableValue(type, result)) { |
| throw new BeanNotOfRequiredTypeException(autowiredBeanName, type, instanceCandidate.getClass()); |
| } |
| return result; |
| } |
| finally { |
| ConstructorResolver.setCurrentInjectionPoint(previousInjectionPoint); |
| } |
| } |
1.8 DefaultListableBeanFactory#findAutowireCandidates(@Nullable String beanName, Class<?> requiredType, DependencyDescriptor descriptor)
| protected Map<String, Object> findAutowireCandidates( |
| @Nullable String beanName, Class<?> requiredType, DependencyDescriptor descriptor) { |
| |
| String[] candidateNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors( |
| this, requiredType, true, descriptor.isEager()); |
| Map<String, Object> result = new LinkedHashMap<>(candidateNames.length); |
| |
| |
| for (Map.Entry<Class<?>, Object> classObjectEntry : this.resolvableDependencies.entrySet()) { |
| Class<?> autowiringType = classObjectEntry.getKey(); |
| if (autowiringType.isAssignableFrom(requiredType)) { |
| Object autowiringValue = classObjectEntry.getValue(); |
| autowiringValue = AutowireUtils.resolveAutowiringValue(autowiringValue, requiredType); |
| if (requiredType.isInstance(autowiringValue)) { |
| result.put(ObjectUtils.identityToString(autowiringValue), autowiringValue); |
| break; |
| } |
| } |
| } |
| |
| for (String candidate : candidateNames) { |
| |
| if (!isSelfReference(beanName, candidate) && isAutowireCandidate(candidate, descriptor)) { |
| |
| addCandidateEntry(result, candidate, descriptor, requiredType); |
| } |
| } |
| |
| if (result.isEmpty()) { |
| boolean multiple = indicatesMultipleBeans(requiredType); |
| |
| DependencyDescriptor fallbackDescriptor = descriptor.forFallbackMatch(); |
| for (String candidate : candidateNames) { |
| if (!isSelfReference(beanName, candidate) && isAutowireCandidate(candidate, fallbackDescriptor) && |
| (!multiple || getAutowireCandidateResolver().hasQualifier(descriptor))) { |
| addCandidateEntry(result, candidate, descriptor, requiredType); |
| } |
| } |
| if (result.isEmpty() && !multiple) { |
| |
| |
| for (String candidate : candidateNames) { |
| if (isSelfReference(beanName, candidate) && |
| (!(descriptor instanceof MultiElementDescriptor) || !beanName.equals(candidate)) && |
| isAutowireCandidate(candidate, fallbackDescriptor)) { |
| addCandidateEntry(result, candidate, descriptor, requiredType); |
| } |
| } |
| } |
| } |
| return result; |
| } |
评论