代碼片段: org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#populateBean boolean hasInstAwareBpps = hasInstantiationAwareBeanPo ...
代碼片段:
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#populateBean
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; //這裡也是調用的實例化後的後置處理器, 只是調用的方法不一樣
//這裡會進行 @Autowired 和 @Resource 的註入工作 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; } } }
同樣的, 通過調試的方式, 來確定這裡使用了那些後置處理器:
ConfigurationClassPostProcessor$ImportAwareBeanPostProcessor
@Override public PropertyValues postProcessProperties(@Nullable PropertyValues pvs, Object bean, String beanName) { // Inject the BeanFactory before AutowiredAnnotationBeanPostProcessor's // postProcessProperties method attempts to autowire other configuration beans. if (bean instanceof EnhancedConfiguration) { ((EnhancedConfiguration) bean).setBeanFactory(this.beanFactory); } return pvs; }
這裡是對 EnhancedConfiguration 提供支持. 其實他繼承了 BeanFactoryAware 介面, 並且什麼都沒乾
public interface EnhancedConfiguration extends BeanFactoryAware {}
EnhancedConfiguration 是 ConfigurationClassEnhancer 的一個內部介面, 是給 spring 自己內部使用的, 開發人員用不了這個, 也沒必要
CommonAnnotationBeanPostProcessor
@Override public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) { //找出類中標註了@Resource註解的屬性和方法 //else if (field.isAnnotationPresent(Resource.class)) InjectionMetadata metadata = findResourceMetadata(beanName, bean.getClass(), pvs); try { metadata.inject(bean, beanName, pvs); } catch (Throwable ex) { throw new BeanCreationException(beanName, "Injection of resource dependencies failed", ex); } return pvs; }
這裡主要是對 @Resource 進行註入
findResourceMetadata在MergedBeanDefinitionPostProcessor#postProcessMergedBeanDefinition的時候執行過.
所以這裡, 大概率是從緩存中拿取結果, 然後進行註入操作. 事實上, 也確實如此.
inject 最終會調用
org.springframework.beans.factory.annotation.InjectionMetadata.InjectedElement#inject 方法
protected void inject(Object target, @Nullable String requestingBeanName, @Nullable PropertyValues pvs) throws Throwable { if (this.isField) { Field field = (Field) this.member; ReflectionUtils.makeAccessible(field); field.set(target, getResourceToInject(target, requestingBeanName)); } else { if (checkPropertySkipping(pvs)) { return; } try { Method method = (Method) this.member; ReflectionUtils.makeAccessible(method); method.invoke(target, getResourceToInject(target, requestingBeanName)); } catch (InvocationTargetException ex) { throw ex.getTargetException(); } } }
這裡分兩種情況進行處理, 一種是 通過欄位註入, 另一種是通過方法註入.
欄位註入的方式是比較多見的.
getResourceToInject() 方法是一個被重寫了的方法:
org.springframework.context.annotation.CommonAnnotationBeanPostProcessor.ResourceElement#getResourceToInject
他是在一個內部類中被重寫的方法.
@Override protected Object getResourceToInject(Object target, @Nullable String requestingBeanName) { return (this.lazyLookup ? buildLazyResourceProxy(this, requestingBeanName) : getResource(this, requestingBeanName)); }
預設情況下, lazy = false, 所以會走 getResource() 方法
org.springframework.context.annotation.CommonAnnotationBeanPostProcessor#getResource
protected Object getResource(LookupElement element, @Nullable String requestingBeanName) throws NoSuchBeanDefinitionException { if (StringUtils.hasLength(element.mappedName)) { return this.jndiFactory.getBean(element.mappedName, element.lookupType); } if (this.alwaysUseJndiLookup) { return this.jndiFactory.getBean(element.name, element.lookupType); } if (this.resourceFactory == null) { throw new NoSuchBeanDefinitionException(element.lookupType, "No resource factory configured - specify the 'resourceFactory' property"); } return autowireResource(this.resourceFactory, element, requestingBeanName); }
根據設置的不同屬性, 進不同的方法, 這裡主要看 autowireResource , 因為一般情況是不需要去設置這些屬性的
protected Object autowireResource(BeanFactory factory, LookupElement element, @Nullable String requestingBeanName) throws NoSuchBeanDefinitionException { Object resource; Set<String> autowiredBeanNames; String name = element.name; if (factory instanceof AutowireCapableBeanFactory) { AutowireCapableBeanFactory beanFactory = (AutowireCapableBeanFactory) factory; DependencyDescriptor descriptor = element.getDependencyDescriptor(); //優先使用 根據 name 註入, 這個 name 就是 beanName //當 beanName 找不到時, 才就會去根據 type 來註入 //依據是 !factory.containsBean(name) if (this.fallbackToDefaultTypeMatch && element.isDefaultName && !factory.containsBean(name)) { autowiredBeanNames = new LinkedHashSet<>(); //根據type(類型)來進行依賴註入 resource = beanFactory.resolveDependency(descriptor, requestingBeanName, autowiredBeanNames, null); if (resource == null) { //如果返回時 resource , 則表明, spring容器中找不到, 也創建不了 這個依賴的bean throw new NoSuchBeanDefinitionException(element.getLookupType(), "No resolvable resource object"); } } else { //根據name(名稱)來進行依賴註入 resource = beanFactory.resolveBeanByName(name, descriptor); autowiredBeanNames = Collections.singleton(name); } } else { resource = factory.getBean(name, element.lookupType); autowiredBeanNames = Collections.singleton(name); } if (factory instanceof ConfigurableBeanFactory) { ConfigurableBeanFactory beanFactory = (ConfigurableBeanFactory) factory; for (String autowiredBeanName : autowiredBeanNames) { if (requestingBeanName != null && beanFactory.containsBean(autowiredBeanName)) { beanFactory.registerDependentBean(autowiredBeanName, requestingBeanName); } } } return resource; }
都說, @Resource 在不設置 name 和 type 的情況下, 是優先使用 name 去 獲取/創建 依賴的 bean , 如果name找不到, 才會使用 type.
這段代碼, 就是支撐的依據.
AutowiredAnnotationBeanPostProcessor
@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; }
這裡主要是對 @Autowired 和 @Value 進行註入的. findAutowiringMetadata
findAutowiringMetadata在MergedBeanDefinitionPostProcessor#postProcessMergedBeanDefinition的時候執行過.
所以此處, 是從緩存中拿取結果, 然後進行註入操作.
最終會調用本類中的方法:
org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.AutowiredFieldElement#inject
@Override 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 { //根據 type 進行依賴註入 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); } }
這裡有一個隱藏的後置處理器: SmartInstantiationAwareBeanPostProcessor
留到下一篇看