【知识库】--spring ApplicationContext 扩展起始点-prepareBeanFactory-registerResolvableDependency(241)

来源:互联网 发布:52kkm软件下载 编辑:程序博客网 时间:2024/06/07 22:07

1 扩展点开始的地方 有registerResolvableDependency方法

问题:做什么用?在哪里用?

// BeanFactory interface not registered as resolvable type in a plain factory.// MessageSource registered (and found for autowiring) as a bean.beanFactory.registerResolvableDependency(BeanFactory.class, beanFactory);beanFactory.registerResolvableDependency(ResourceLoader.class, this);beanFactory.registerResolvableDependency(ApplicationEventPublisher.class, this);beanFactory.registerResolvableDependency(ApplicationContext.class, this);

注册 将类型对应的对象注册到 DefaultListableBeanFactory中的缓存中:

         /** Map from dependency type to corresponding autowired value */

private final Map<Class<?>, Object>resolvableDependencies = new HashMap<Class<?>, Object>(16);



@Overridepublic void registerResolvableDependency(Class<?> dependencyType, Object autowiredValue) {Assert.notNull(dependencyType, "Type must not be null");if (autowiredValue != null) {Assert.isTrue((autowiredValue instanceof ObjectFactory || dependencyType.isInstance(autowiredValue)),"Value [" + autowiredValue + "] does not implement specified type [" + dependencyType.getName() + "]");                        //看这里!this.resolvableDependencies.put(dependencyType, autowiredValue);}}

使用 DefaultListableBeanFactory 中有两个方法如下:

/** * Determine the autowire candidate in the given set of beans. * <p>Looks for {@code @Primary} and {@code @Priority} (in that order). * @param candidateBeans a Map of candidate names and candidate instances * that match the required type, as returned by {@link #findAutowireCandidates} * @param descriptor the target dependency to match against * @return the name of the autowire candidate, or {@code null} if none found */protected String determineAutowireCandidate(Map<String, Object> candidateBeans, DependencyDescriptor descriptor) {Class<?> requiredType = descriptor.getDependencyType();String primaryCandidate = determinePrimaryCandidate(candidateBeans, requiredType);if (primaryCandidate != null) {return primaryCandidate;}String priorityCandidate = determineHighestPriorityCandidate(candidateBeans, requiredType);if (priorityCandidate != null) {return priorityCandidate;}// Fallbackfor (Map.Entry<String, Object> entry : candidateBeans.entrySet()) {String candidateBeanName = entry.getKey();Object beanInstance = entry.getValue();                        // 看这里!!if (this.resolvableDependencies.values().contains(beanInstance) ||matchesBeanName(candidateBeanName, descriptor.getDependencyName())) {return candidateBeanName;}}return null;}
/** * Find bean instances that match the required type. * Called during autowiring for the specified bean. * @param beanName the name of the bean that is about to be wired * @param requiredType the actual type of bean to look for * (may be an array component type or collection element type) * @param descriptor the descriptor of the dependency to resolve * @return a Map of candidate names and candidate instances that match * the required type (never {@code null}) * @throws BeansException in case of errors * @see #autowireByType * @see #autowireConstructor */protected Map<String, Object> findAutowireCandidates(String beanName, Class<?> requiredType, DependencyDescriptor descriptor) {String[] candidateNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(this, requiredType, true, descriptor.isEager());Map<String, Object> result = new LinkedHashMap<String, Object>(candidateNames.length);for (Class<?> autowiringType : this.resolvableDependencies.keySet()) {if (autowiringType.isAssignableFrom(requiredType)) {                                //这里!!Object autowiringValue = this.resolvableDependencies.get(autowiringType);autowiringValue = AutowireUtils.resolveAutowiringValue(autowiringValue, requiredType);if (requiredType.isInstance(autowiringValue)) {result.put(ObjectUtils.identityToString(autowiringValue), autowiringValue);break;}}}for (String candidateName : candidateNames) {if (!isSelfReference(beanName, candidateName) && isAutowireCandidate(candidateName, descriptor)) {result.put(candidateName, getBean(candidateName));}}if (result.isEmpty()) {DependencyDescriptor fallbackDescriptor = descriptor.forFallbackMatch();for (String candidateName : candidateNames) {if (!candidateName.equals(beanName) && isAutowireCandidate(candidateName, fallbackDescriptor)) {result.put(candidateName, getBean(candidateName));}}}return result;}

调用方 DefaultListableBeanFactory 

public Object doResolveDependency(DependencyDescriptor descriptor, String beanName,Set<String> autowiredBeanNames, TypeConverter typeConverter) throws BeansException {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());return (descriptor.getField() != null ?converter.convertIfNecessary(value, type, descriptor.getField()) :converter.convertIfNecessary(value, type, descriptor.getMethodParameter()));}if (type.isArray()) {Class<?> componentType = type.getComponentType();DependencyDescriptor targetDesc = new DependencyDescriptor(descriptor);targetDesc.increaseNestingLevel();                        //看这里!!!Map<String, Object> matchingBeans = findAutowireCandidates(beanName, componentType, targetDesc);if (matchingBeans.isEmpty()) {if (descriptor.isRequired()) {raiseNoSuchBeanDefinitionException(componentType, "array of " + componentType.getName(), descriptor);}return null;}             ...}

继续找调用方 DefaultListableBeanFactory

//---------------------------------------------------------------------// Dependency resolution functionality//---------------------------------------------------------------------@Overridepublic Object resolveDependency(DependencyDescriptor descriptor, String beanName,Set<String> autowiredBeanNames, TypeConverter typeConverter) throws BeansException {descriptor.initParameterNameDiscovery(getParameterNameDiscoverer());if (descriptor.getDependencyType().equals(javaUtilOptionalClass)) {return new OptionalDependencyFactory().createOptionalDependency(descriptor, beanName);}else if (ObjectFactory.class == descriptor.getDependencyType()) {return new DependencyObjectFactory(descriptor, beanName);}else if (javaxInjectProviderClass == descriptor.getDependencyType()) {return new DependencyProviderFactory().createDependencyProvider(descriptor, beanName);}else {Object result = getAutowireCandidateResolver().getLazyResolutionProxyIfNecessary(descriptor, beanName);if (result == null) {result = doResolveDependency(descriptor, beanName, autowiredBeanNames, typeConverter);}return result;}}



找到调用方  AbstractAutowireCapableBeanFactory

/** * Abstract method defining "autowire by type" (bean properties by type) behavior. * <p>This is like PicoContainer default, in which there must be exactly one bean * of the property type in the bean factory. This makes bean factories simple to * configure for small namespaces, but doesn't work as well as standard Spring * behavior for bigger applications. * @param beanName the name of the bean to autowire by type * @param mbd the merged bean definition to update through autowiring * @param bw BeanWrapper from which we can obtain information about the bean * @param pvs the PropertyValues to register wired objects with */protected void autowireByType(String beanName, AbstractBeanDefinition mbd, BeanWrapper bw, MutablePropertyValues pvs) {TypeConverter converter = getCustomTypeConverter();if (converter == null) {converter = bw;}Set<String> autowiredBeanNames = new LinkedHashSet<String>(4);String[] propertyNames = unsatisfiedNonSimpleProperties(mbd, bw);for (String propertyName : propertyNames) {try {PropertyDescriptor pd = bw.getPropertyDescriptor(propertyName);// Don't try autowiring by type for type Object: never makes sense,// even if it technically is a unsatisfied, non-simple property.if (Object.class != pd.getPropertyType()) {MethodParameter methodParam = BeanUtils.getWriteMethodParameter(pd);// Do not allow eager init for type matching in case of a prioritized post-processor.boolean eager = !PriorityOrdered.class.isAssignableFrom(bw.getWrappedClass());DependencyDescriptor desc = new AutowireByTypeDependencyDescriptor(methodParam, eager);Object autowiredArgument = resolveDependency(desc, beanName, autowiredBeanNames, converter);if (autowiredArgument != null) {pvs.add(propertyName, autowiredArgument);}for (String autowiredBeanName : autowiredBeanNames) {registerDependentBean(autowiredBeanName, beanName);if (logger.isDebugEnabled()) {logger.debug("Autowiring by type from bean name '" + beanName + "' via property '" +propertyName + "' to bean named '" + autowiredBeanName + "'");}}autowiredBeanNames.clear();}}catch (BeansException ex) {throw new UnsatisfiedDependencyException(mbd.getResourceDescription(), beanName, propertyName, ex);}}}

找到调用方 AbstractAutowireCapableBeanFactory:

/** * Populate the bean instance in the given BeanWrapper with the property values * from the bean definition. * @param beanName the name of the bean * @param mbd the bean definition for the bean * @param bw BeanWrapper with bean instance */protected void populateBean(String beanName, RootBeanDefinition mbd, BeanWrapper bw) {PropertyValues pvs = mbd.getPropertyValues();if (bw == null) {if (!pvs.isEmpty()) {throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Cannot apply property values to null instance");}else {// Skip property population phase for null instance.return;}}// Give any InstantiationAwareBeanPostProcessors the opportunity to modify the// state of the bean before properties are set. This can be used, for example,// to support styles of field injection.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;}if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_NAME ||mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_TYPE) {MutablePropertyValues newPvs = new MutablePropertyValues(pvs);// Add property values based on autowire by name if applicable.if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_NAME) {autowireByName(beanName, mbd, bw, newPvs);}// Add property values based on autowire by type if applicable.if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_TYPE) {autowireByType(beanName, mbd, bw, newPvs);}pvs = newPvs;}boolean hasInstAwareBpps = hasInstantiationAwareBeanPostProcessors();boolean needsDepCheck = (mbd.getDependencyCheck() != RootBeanDefinition.DEPENDENCY_CHECK_NONE);if (hasInstAwareBpps || needsDepCheck) {PropertyDescriptor[] filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);if (hasInstAwareBpps) {for (BeanPostProcessor bp : getBeanPostProcessors()) {if (bp instanceof InstantiationAwareBeanPostProcessor) {InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;pvs = ibp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName);if (pvs == null) {return;}}}}if (needsDepCheck) {checkDependencies(beanName, mbd, filteredPds, pvs);}}applyPropertyValues(beanName, mbd, bw, pvs);}


继续调用方AbstractAutowireCapableBeanFactory

/** * Actually create the specified bean. Pre-creation processing has already happened * at this point, e.g. checking {@code postProcessBeforeInstantiation} callbacks. * <p>Differentiates between default bean instantiation, use of a * factory method, and autowiring a constructor. * @param beanName the name of the bean * @param mbd the merged bean definition for the bean * @param args explicit arguments to use for constructor or factory method invocation * @return a new instance of the bean * @throws BeanCreationException if the bean could not be created * @see #instantiateBean * @see #instantiateUsingFactoryMethod * @see #autowireConstructor */protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final Object[] args) {// Instantiate the bean.BeanWrapper instanceWrapper = null;if (mbd.isSingleton()) {instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);}if (instanceWrapper == null) {instanceWrapper = createBeanInstance(beanName, mbd, args);}final Object bean = (instanceWrapper != null ? instanceWrapper.getWrappedInstance() : null);Class<?> beanType = (instanceWrapper != null ? instanceWrapper.getWrappedClass() : null);// Allow post-processors to modify the merged bean definition.synchronized (mbd.postProcessingLock) {if (!mbd.postProcessed) {applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);mbd.postProcessed = true;}}// Eagerly cache singletons to be able to resolve circular references// even when triggered by lifecycle interfaces like BeanFactoryAware.boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&isSingletonCurrentlyInCreation(beanName));if (earlySingletonExposure) {if (logger.isDebugEnabled()) {logger.debug("Eagerly caching bean '" + beanName +"' to allow for resolving potential circular references");}addSingletonFactory(beanName, new ObjectFactory<Object>() {@Overridepublic Object getObject() throws BeansException {return getEarlyBeanReference(beanName, mbd, bean);}});}// Initialize the bean instance.Object exposedObject = bean;try {populateBean(beanName, mbd, instanceWrapper);if (exposedObject != null) {exposedObject = initializeBean(beanName, exposedObject, mbd);}}catch (Throwable ex) {if (ex instanceof BeanCreationException && beanName.equals(((BeanCreationException) ex).getBeanName())) {throw (BeanCreationException) ex;}else {throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Initialization of bean failed", ex);}}if (earlySingletonExposure) {Object earlySingletonReference = getSingleton(beanName, false);if (earlySingletonReference != null) {if (exposedObject == bean) {exposedObject = earlySingletonReference;}else if (!this.allowRawInjectionDespiteWrapping && hasDependentBean(beanName)) {String[] dependentBeans = getDependentBeans(beanName);Set<String> actualDependentBeans = new LinkedHashSet<String>(dependentBeans.length);for (String dependentBean : dependentBeans) {if (!removeSingletonIfCreatedForTypeCheckOnly(dependentBean)) {actualDependentBeans.add(dependentBean);}}if (!actualDependentBeans.isEmpty()) {throw new BeanCurrentlyInCreationException(beanName,"Bean with name '" + beanName + "' has been injected into other beans [" +StringUtils.collectionToCommaDelimitedString(actualDependentBeans) +"] in its raw version as part of a circular reference, but has eventually been " +"wrapped. This means that said other beans do not use the final version of the " +"bean. This is often the result of over-eager type matching - consider using " +"'getBeanNamesOfType' with the 'allowEagerInit' flag turned off, for example.");}}}}// Register bean as disposable.try {registerDisposableBeanIfNecessary(beanName, bean, mbd);}catch (BeanDefinitionValidationException ex) {throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Invalid destruction signature", ex);}return exposedObject;}

其实最终看到了就是:

protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final Object[] args) 
创建bean时调用时出发。


总结:

项目中实现了

如ApplicationContextAware 之类Aware的接口都会在创建bean时set完成。






阅读全文
0 0
原创粉丝点击