可以看到除了 ImportBeanConfigMain 在扫描的时候就被注册到 spring 容器里面来,后面的都是走的 AbstractApplicationContext#invokeBeanFactoryPostProcessors 方法给注册到 Spring 容器中来了. 是不是应该详细分析下 invokeBeanFactoryPostProcessors 方法到了做了什么或者说用了什么,将我们定义的对象给注册到 Spring 容器中来了呢?
// Do not initialize FactoryBeans here: We need to leave all regular beans // uninitialized to let the bean factory post-processors apply to them! // Separate between BeanDefinitionRegistryPostProcessors that implement // PriorityOrdered, Ordered, and the rest. List<BeanDefinitionRegistryPostProcessor> currentRegistryProcessors = newArrayList<>();
// Next, invoke the BeanDefinitionRegistryPostProcessors that implement Ordered. postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false); for (String ppName : postProcessorNames) { if (!processedBeans.contains(ppName) && beanFactory.isTypeMatch(ppName, Ordered.class)) { currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class)); processedBeans.add(ppName); } } sortPostProcessors(currentRegistryProcessors, beanFactory); registryProcessors.addAll(currentRegistryProcessors); invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry); currentRegistryProcessors.clear();
// Finally, invoke all other BeanDefinitionRegistryPostProcessors until no further ones appear. booleanreiterate=true; while (reiterate) { reiterate = false; postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false); for (String ppName : postProcessorNames) { if (!processedBeans.contains(ppName)) { currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class)); processedBeans.add(ppName); reiterate = true; } } sortPostProcessors(currentRegistryProcessors, beanFactory); registryProcessors.addAll(currentRegistryProcessors); invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry); currentRegistryProcessors.clear(); }
// Now, invoke the postProcessBeanFactory callback of all processors handled so far. invokeBeanFactoryPostProcessors(registryProcessors, beanFactory); invokeBeanFactoryPostProcessors(regularPostProcessors, beanFactory); }
else { // Invoke factory processors registered with the context instance. invokeBeanFactoryPostProcessors(beanFactoryPostProcessors, beanFactory); }
// Do not initialize FactoryBeans here: We need to leave all regular beans // uninitialized to let the bean factory post-processors apply to them! String[] postProcessorNames = beanFactory.getBeanNamesForType(BeanFactoryPostProcessor.class, true, false);
// Separate between BeanFactoryPostProcessors that implement PriorityOrdered, // Ordered, and the rest. List<BeanFactoryPostProcessor> priorityOrderedPostProcessors = newArrayList<>(); List<String> orderedPostProcessorNames = newArrayList<>(); List<String> nonOrderedPostProcessorNames = newArrayList<>(); for (String ppName : postProcessorNames) { if (processedBeans.contains(ppName)) { // skip - already processed in first phase above } elseif (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) { priorityOrderedPostProcessors.add(beanFactory.getBean(ppName, BeanFactoryPostProcessor.class)); } elseif (beanFactory.isTypeMatch(ppName, Ordered.class)) { orderedPostProcessorNames.add(ppName); } else { nonOrderedPostProcessorNames.add(ppName); } }
// First, invoke the BeanFactoryPostProcessors that implement PriorityOrdered. sortPostProcessors(priorityOrderedPostProcessors, beanFactory); invokeBeanFactoryPostProcessors(priorityOrderedPostProcessors, beanFactory);
// Next, invoke the BeanFactoryPostProcessors that implement Ordered. List<BeanFactoryPostProcessor> orderedPostProcessors = newArrayList<>(orderedPostProcessorNames.size()); for (String postProcessorName : orderedPostProcessorNames) { orderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class)); } sortPostProcessors(orderedPostProcessors, beanFactory); invokeBeanFactoryPostProcessors(orderedPostProcessors, beanFactory);
// Finally, invoke all other BeanFactoryPostProcessors. List<BeanFactoryPostProcessor> nonOrderedPostProcessors = newArrayList<>(nonOrderedPostProcessorNames.size()); for (String postProcessorName : nonOrderedPostProcessorNames) { nonOrderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class)); } invokeBeanFactoryPostProcessors(nonOrderedPostProcessors, beanFactory);
// Clear cached merged bean definitions since the post-processors might have // modified the original metadata, e.g. replacing placeholders in values... beanFactory.clearMetadataCache(); }
/** * Build and validate a configuration model based on the registry of * {@link Configuration} classes. */ publicvoidprocessConfigBeanDefinitions(BeanDefinitionRegistry registry) { List<BeanDefinitionHolder> configCandidates = newArrayList<>(); String[] candidateNames = registry.getBeanDefinitionNames();
for (String beanName : candidateNames) { BeanDefinitionbeanDef= registry.getBeanDefinition(beanName); if (beanDef.getAttribute(ConfigurationClassUtils.CONFIGURATION_CLASS_ATTRIBUTE) != null) { if (logger.isDebugEnabled()) { logger.debug("Bean definition has already been processed as a configuration class: " + beanDef); } } // 对是否满足配置类进行检查, 这里我们的bean是importBeanConfigMain,满足条件的,具体可以看下面该方法的分析.然后会构建一个 bdHolder,添加到集合中来. elseif (ConfigurationClassUtils.checkConfigurationClassCandidate(beanDef, this.metadataReaderFactory)) { configCandidates.add(newBeanDefinitionHolder(beanDef, beanName)); } }
// Return immediately if no @Configuration classes were found if (configCandidates.isEmpty()) { return; }
// Register the ImportRegistry as a bean in order to support ImportAware @Configuration classes // org.springframework.context.annotation.ConfigurationClassPostProcessor.importRegistry sbr不包含importRegistry的话,就会注册一个进去. if (sbr != null && !sbr.containsSingleton(IMPORT_REGISTRY_BEAN_NAME)) { sbr.registerSingleton(IMPORT_REGISTRY_BEAN_NAME, parser.getImportRegistry()); }
if (this.metadataReaderFactory instanceof CachingMetadataReaderFactory) { // Clear cache in externally provided MetadataReaderFactory; this is a no-op // for a shared cache since it'll be cleared by the ApplicationContext. // 这里是清除缓存,也是清除一些集合. ((CachingMetadataReaderFactory) this.metadataReaderFactory).clearCache(); } }
/** * Apply processing and build a complete {@link ConfigurationClass} by reading the * annotations, members and methods from the source class. This method can be called * multiple times as relevant sources are discovered. * @param configClass the configuration class being build * @param sourceClass a source class * @return the superclass, or {@code null} if none found or previously processed */ @Nullable protectedfinal SourceClass doProcessConfigurationClass(ConfigurationClass configClass, SourceClass sourceClass) throws IOException {
// 判断是不是有 @Component 注解. if (configClass.getMetadata().isAnnotated(Component.class.getName())) { // Recursively process any member (nested) classes first processMemberClasses(configClass, sourceClass); }
// Process any @PropertySource annotations // 接着再处理 @PropertySources 注解. 可以看到这个注解貌似是和 Environment 有关系. for (AnnotationAttributes propertySource : AnnotationConfigUtils.attributesForRepeatable( sourceClass.getMetadata(), PropertySources.class, org.springframework.context.annotation.PropertySource.class)) { if (this.environment instanceof ConfigurableEnvironment) { processPropertySource(propertySource); } else { logger.info("Ignoring @PropertySource annotation on [" + sourceClass.getMetadata().getClassName() + "]. Reason: Environment must implement ConfigurableEnvironment"); } }
// Process any @ComponentScan annotations // 获取@ComponentScan 注解,我们这里是有的. Set<AnnotationAttributes> componentScans = AnnotationConfigUtils.attributesForRepeatable( sourceClass.getMetadata(), ComponentScans.class, ComponentScan.class); if (!componentScans.isEmpty() && !this.conditionEvaluator.shouldSkip(sourceClass.getMetadata(), ConfigurationPhase.REGISTER_BEAN)) { for (AnnotationAttributes componentScan : componentScans) { // The config class is annotated with @ComponentScan -> perform the scan immediately // org.springframework.context.annotation.ComponentScanAnnotationParser#parse // parse 方法内部是使用 ClassPathBeanDefinitionScanner 扫描器的,对resourcePattern/includeFilters/excludeFilters/lazyInit 是否有进行处理. // 获取注解上的属性 basePackages/basePackageClasses的值,添加一个AbstractTypeHierarchyTraversingFilter,这个是ExcludeFilter //最后来org.springframework.context.annotation.ClassPathBeanDefinitionScanner#doScan做扫描操作. //doScan做了什么事情呢? 显示通过传入进来的包,调用findCandidateComponents获取出bd的集合来,ScopeMetadata设置也是默认的,用beanNameGenerator生成bean对应的beanName //如果bd是AbstractBeanDefinition,再走一下postProcessBeanDefinition方法 //如果bd是AnnotatedBeanDefinition,会走AnnotationConfigUtils.processCommonDefinitionAnnotations()方法,也是对一些注解的属性进行设置值操作. 走个checkCandidat检查方法,确保bd再registry中不存在的,如果存在的话,那就说明是已经注册过了的. //如果是不存在的话,就会new一个BeanDefinitionHolder来,然后走registerBeanDefinition给注册到Spring容器中来. 最后返回扫描获取到的bdHolder集合来. Set<BeanDefinitionHolder> scannedBeanDefinitions = this.componentScanParser.parse(componentScan, sourceClass.getMetadata().getClassName()); // Check the set of scanned definitions for any further config classes and parse recursively if needed for (BeanDefinitionHolder holder : scannedBeanDefinitions) { BeanDefinitionbdCand= holder.getBeanDefinition().getOriginatingBeanDefinition(); if (bdCand == null) { bdCand = holder.getBeanDefinition(); } // 可以看到这里, 我们在最初进入到processConfigBeanDefinitions来的时候,其实就已经是调用了这个方法,那么我们这里扫描获取的bean在此调用这个方法. 也就是确保,扫描获取的bean,也是有一些配置的注解并且也是需要解析的. if (ConfigurationClassUtils.checkConfigurationClassCandidate(bdCand, this.metadataReaderFactory)) { // org.springframework.context.annotation.ConfigurationClassParser#processConfigurationClass这里最后也是走到这里了. // 最初我们是从parse.parse() 进来的,也是走的ConfigurationClassParser#processConfigurationClas,这里又走到了该方法. // 也就说我们是调用这个方法,只要满足条件的话,就会一直调用这个方法,直到不满足条件为止. parse(bdCand.getBeanClassName(), holder.getBeanName()); } } } }
// Process any @Import annotations // 这里是对 @Import 注解进行处理. 该方法是有利用 importStack 来控制, // 其内部又分为 @ImportSelector/@ImportBeanDefinitionRegistrar/无注解这三种情况. // 获取完 bean 信息后,就又走到了org.springframework.context.annotation.ConfigurationClassParser#processConfigurationClass方法来. // 最后importStack 调用 pop 给数据给弹出来. processImports(configClass, sourceClass, getImports(sourceClass), true);
// Process any @ImportResource annotations // 对@ImportResource是否有进行判断. AnnotationAttributesimportResource= AnnotationConfigUtils.attributesFor(sourceClass.getMetadata(), ImportResource.class); if (importResource != null) { String[] resources = importResource.getStringArray("locations"); Class<? extendsBeanDefinitionReader> readerClass = importResource.getClass("reader"); for (String resource : resources) { StringresolvedResource=this.environment.resolveRequiredPlaceholders(resource); configClass.addImportedResource(resolvedResource, readerClass); } }
/** * Check whether the given bean definition is a candidate for a configuration class * (or a nested component class declared within a configuration/component class, * to be auto-registered as well), and mark it accordingly. * @param beanDef the bean definition to check * @param metadataReaderFactory the current factory in use by the caller * @return whether the candidate qualifies as (any kind of) configuration class */ publicstaticbooleancheckConfigurationClassCandidate( BeanDefinition beanDef, MetadataReaderFactory metadataReaderFactory) { // 先获取 beanName 出来 StringclassName= beanDef.getBeanClassName(); if (className == null || beanDef.getFactoryMethodName() != null) { returnfalse; }
AnnotationMetadata metadata; // 判断 bd 是不是AnnotatedBeanDefinition 并且 确认 beanName是不是与前面获取出来的classsName是一样的. if (beanDef instanceof AnnotatedBeanDefinition && className.equals(((AnnotatedBeanDefinition) beanDef).getMetadata().getClassName())) { // Can reuse the pre-parsed metadata from the given BeanDefinition... // 获取类上的注解.我们这里获取出来的是 @Import 和 @ComponentScan metadata = ((AnnotatedBeanDefinition) beanDef).getMetadata(); } elseif (beanDef instanceof AbstractBeanDefinition && ((AbstractBeanDefinition) beanDef).hasBeanClass()) { // Check already loaded Class if present... // since we possibly can't even load the class file for this Class. Class<?> beanClass = ((AbstractBeanDefinition) beanDef).getBeanClass(); if (BeanFactoryPostProcessor.class.isAssignableFrom(beanClass) || BeanPostProcessor.class.isAssignableFrom(beanClass) || AopInfrastructureBean.class.isAssignableFrom(beanClass) || EventListenerFactory.class.isAssignableFrom(beanClass)) { returnfalse; } metadata = AnnotationMetadata.introspect(beanClass); } else { try { MetadataReadermetadataReader= metadataReaderFactory.getMetadataReader(className); metadata = metadataReader.getAnnotationMetadata(); } catch (IOException ex) { if (logger.isDebugEnabled()) { logger.debug("Could not find class file for introspecting configuration annotations: " + className, ex); } returnfalse; } }
// It's a full or lite configuration candidate... Let's determine the order value, if any. // 获取 order,如果有的话,就会set进去. Integerorder= getOrder(metadata); if (order != null) { beanDef.setAttribute(ORDER_ATTRIBUTE, order); }
@Override publicvoidpreInstantiateSingletons()throws BeansException { if (logger.isTraceEnabled()) { logger.trace("Pre-instantiating singletons in " + this); }
// Iterate over a copy to allow for init methods which in turn register new bean definitions. // While this may not be part of the regular factory bootstrap, it does otherwise work fine. // 从 beanDefinitionNames 中获取出 beanName的集合. // 这里获取出来的 beanNameList 不仅仅有Spring内部的,还有我们自己的. List<String> beanNames = newArrayList<>(this.beanDefinitionNames);
/** * Return an instance, which may be shared or independent, of the specified bean. * @param name the name of the bean to retrieve * @param requiredType the required type of the bean to retrieve * @param args arguments to use when creating a bean instance using explicit arguments * (only applied when creating a new instance as opposed to retrieving an existing one) * @param typeCheckOnly whether the instance is obtained for a type check, * not for actual use * @return an instance of the bean * @throws BeansException if the bean could not be created */ @SuppressWarnings("unchecked") protected <T> T doGetBean(final String name, @Nullablefinal Class<T> requiredType, @Nullablefinal Object[] args, boolean typeCheckOnly)throws BeansException { // 获取beanName finalStringbeanName= transformedBeanName(name); Object bean;
// Eagerly check singleton cache for manually registered singletons. // 这里是判断是不是手动给添加到单例池里面去的. ObjectsharedInstance= getSingleton(beanName); if (sharedInstance != null && args == null) { if (logger.isTraceEnabled()) { if (isSingletonCurrentlyInCreation(beanName)) { logger.trace("Returning eagerly cached instance of singleton bean '" + beanName + "' that is not fully initialized yet - a consequence of a circular reference"); } else { logger.trace("Returning cached instance of singleton bean '" + beanName + "'"); } } // 如果是从单例池里面获取出来的,就走这个方法. bean = getObjectForBeanInstance(sharedInstance, name, beanName, null); }
else { // Fail if we're already creating this bean instance: // We're assumably within a circular reference. // 判断这个bean当前是不是已经在注册了,如果是的话,就会抛出异常来. //org.springframework.beans.factory.support.AbstractBeanFactory#prototypesCurrentlyInCreation,利用ThreadLocal来记录值,如果beanName是相同的话就会返回ture,否则就返回flase,这里返回的是false. if (isPrototypeCurrentlyInCreation(beanName)) { thrownewBeanCurrentlyInCreationException(beanName); }
// Check if bean definition exists in this factory. // org.springframework.beans.factory.support.AbstractBeanFactory#getParentBeanFactory获取父工厂,这里返回的是null,也就是说是没有的.所以下面的if条件也就不会进去. BeanFactoryparentBeanFactory= getParentBeanFactory(); if (parentBeanFactory != null && !containsBeanDefinition(beanName)) { // Not found -> check parent. StringnameToLookup= originalBeanName(name); if (parentBeanFactory instanceof AbstractBeanFactory) { return ((AbstractBeanFactory) parentBeanFactory).doGetBean( nameToLookup, requiredType, args, typeCheckOnly); } elseif (args != null) { // Delegation to parent with explicit args. return (T) parentBeanFactory.getBean(nameToLookup, args); } elseif (requiredType != null) { // No args -> delegate to standard getBean method. return parentBeanFactory.getBean(nameToLookup, requiredType); } else { return (T) parentBeanFactory.getBean(nameToLookup); } }
// Guarantee initialization of beans that the current bean depends on. // 获取 @DependsOn 注解.并且对 @Depends进行处理. String[] dependsOn = mbd.getDependsOn(); if (dependsOn != null) { for (String dep : dependsOn) { if (isDependent(beanName, dep)) { thrownewBeanCreationException(mbd.getResourceDescription(), beanName, "Circular depends-on relationship between '" + beanName + "' and '" + dep + "'"); } registerDependentBean(dep, beanName); try { getBean(dep); } catch (NoSuchBeanDefinitionException ex) { thrownewBeanCreationException(mbd.getResourceDescription(), beanName, "'" + beanName + "' depends on missing bean '" + dep + "'", ex); } } }
// Create bean instance. // 确保 bd 是单例的. if (mbd.isSingleton()) { sharedInstance = getSingleton(beanName, () -> { try { return createBean(beanName, mbd, args); } catch (BeansException ex) { // Explicitly remove instance from singleton cache: It might have been put there // eagerly by the creation process, to allow for circular reference resolution. // Also remove any beans that received a temporary reference to the bean. destroySingleton(beanName); throw ex; } }); // 获取bean实例 bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd); } // 这里是实例化一个 多列的 bean elseif (mbd.isPrototype()) { // It's a prototype -> create a new instance. ObjectprototypeInstance=null; try { beforePrototypeCreation(beanName); prototypeInstance = createBean(beanName, mbd, args); } finally { afterPrototypeCreation(beanName); } bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd); }
else { // 这里操作的,不仅单列也不是多列. StringscopeName= mbd.getScope(); finalScopescope=this.scopes.get(scopeName); if (scope == null) { thrownewIllegalStateException("No Scope registered for scope name '" + scopeName + "'"); } try { ObjectscopedInstance= scope.get(beanName, () -> { beforePrototypeCreation(beanName); try { return createBean(beanName, mbd, args); } finally { afterPrototypeCreation(beanName); } }); bean = getObjectForBeanInstance(scopedInstance, name, beanName, mbd); } catch (IllegalStateException ex) { thrownewBeanCreationException(beanName, "Scope '" + scopeName + "' is not active for the current thread; consider " + "defining a scoped proxy for this bean if you intend to refer to it from a singleton", ex); } } } catch (BeansException ex) { cleanupAfterBeanCreationFailure(beanName); throw ex; } }
// Check if required type matches the type of the actual bean instance. // 不满足条件,所以没进入到这里. if (requiredType != null && !requiredType.isInstance(bean)) { try { TconvertedBean= getTypeConverter().convertIfNecessary(bean, requiredType); if (convertedBean == null) { thrownewBeanNotOfRequiredTypeException(name, requiredType, bean.getClass()); } return convertedBean; } catch (TypeMismatchException ex) { if (logger.isTraceEnabled()) { logger.trace("Failed to convert bean '" + name + "' to required type '" + ClassUtils.getQualifiedName(requiredType) + "'", ex); } thrownewBeanNotOfRequiredTypeException(name, requiredType, bean.getClass()); } }
/** * Central method of this class: creates a bean instance, * populates the bean instance, applies post-processors, etc. * @see #doCreateBean */ @Override protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) throws BeanCreationException {
if (logger.isTraceEnabled()) { logger.trace("Creating instance of bean '" + beanName + "'"); } RootBeanDefinitionmbdToUse= mbd;
// Make sure bean class is actually resolved at this point, and // clone the bean definition in case of a dynamically resolved Class // which cannot be stored in the shared merged bean definition. // 确定bean的class, 如果bd有beanClass的信息,就会直接返回. Class<?> resolvedClass = resolveBeanClass(mbd, beanName); //如果这里从bd获取出来的class是有值的,然后bd是没有beanCalss,获取出来的beanClassName也是null的话,那么这里就会重新来构建出一个bd,并且设置上 beanClass信息. if (resolvedClass != null && !mbd.hasBeanClass() && mbd.getBeanClassName() != null) { mbdToUse = newRootBeanDefinition(mbd); mbdToUse.setBeanClass(resolvedClass); }
可以感觉到 doCreateBean 就是真正实例化bean的方法, 是不是Spring 加上了 do 开头的方法,才是真正干活的.
/** * 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@Nullable Object[] args) throws BeanCreationException {
// earlySingletonExposure is true. if (earlySingletonExposure) { // 从单例池中根据 beanName 来获取对象. ObjectearlySingletonReference= getSingleton(beanName, false); // 获取出来的对象不是null的话,就会进入到这里来. if (earlySingletonReference != null) { if (exposedObject == bean) { exposedObject = earlySingletonReference; } elseif (!this.allowRawInjectionDespiteWrapping && hasDependentBean(beanName)) { String[] dependentBeans = getDependentBeans(beanName); Set<String> actualDependentBeans = newLinkedHashSet<>(dependentBeans.length); for (String dependentBean : dependentBeans) { if (!removeSingletonIfCreatedForTypeCheckOnly(dependentBean)) { actualDependentBeans.add(dependentBean); } } if (!actualDependentBeans.isEmpty()) { thrownewBeanCurrentlyInCreationException(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."); } } } }