欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

spring启动简析

程序员文章站 2022-05-21 22:21:18
...

spring类结构

beanFactory结构

todo

applicationContext结构

todo

beanDefinition结构

BeanDefinition是顶层接口,定义了bean的各种属性,包括是否懒加载,类名称等等,所有bean的基本属性都是应该通过这个接口获取。BeanDefinition直接继承的是接口AnnotatedBeanDefinition与AbstractBeanDefinition抽象类,AnnotatedBeanDefinition是在BeanDefinition基础上增加了AnnotationMetadata属性数据,这个接口可以理解为带注解的BeanDefinition;AbstractBeanDefinition是对BeanDefinition的基本实现,把BeanDefinition中大部分方法都实现了,然后这个抽象类有三个子类RootBeanDefinition、ChildBeanDefinition、GenericBeanDefinition,对于前面两个父子类,是因为我们定义bean的时候,是可以有parent关系的,RootBeanDefinition是一种merged过的BeanDefinition,是完整的BeanDefinition,而childBeanDefinition是不完整的BeanDefinition,必须要包含parent的BeanDefinition;GenericBeanDefinition是新的BeanDefinition,是用来替换那个root跟child的,后面新的beandefinition都是基于GenericBeanDefinition实现的。再来看下AnnotatedBeanDefinition的子类有两个ScannedGenericBeanDefinition跟AnnotatedGenericBeanDefinition,这两个子类都是基于GenericBeanDefinition实现的,看下这两个类的实现是差不多的,这两个类的区别在与ScannedGenericBeanDefinition是在component-scan的场景下定义的,就是我们注解@ComponentScan或者<context: component-scan>而AnnotatedGenericBeanDefinition应用的场景是springboot的AnnotationConfigApplicationContext里面以及处理@Configuration注解的bean对象的时候用的。而普通的GenericBeanDefinition注解在xml中定义的bean应用

metadata结构

todo

namespaceHandler结构

todo

spring中的数据结构

todo

spring 的初始化----refresh

spring启动过程是以ApplicationContext对象的定义来完成bean的初始化与管理的。然后就可以通过这个context的getbean方法获取对应bean对象。以ClassPathXmlApplicationContext为例,当我们new一个ClassPathXmlApplicationContext对象的时候,其spring的bean对象已经被加载好了。

public ClassPathXmlApplicationContext(String[] configLocations, boolean refresh, ApplicationContext parent)
      throws BeansException {

   super(parent);
   setConfigLocations(configLocations);
   if (refresh) {
      refresh();
   }
}

上面代码中是ClassPathXmlApplicationContext的构造函数,configLocations是用户指定的配置项路径地址,不是重点,重点在refresh函数

public void refresh() throws BeansException, IllegalStateException {
   synchronized (this.startupShutdownMonitor) {
      // Prepare this context for refreshing.
      prepareRefresh();
      // Tell the subclass to refresh the internal bean factory.
      ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
      // Prepare the bean factory for use in this context.
      prepareBeanFactory(beanFactory);
      try {
         // Allows post-processing of the bean factory in context subclasses.
         postProcessBeanFactory(beanFactory);
         // Invoke factory processors registered as beans in the context.
         invokeBeanFactoryPostProcessors(beanFactory);
         // Register bean processors that intercept bean creation.
         registerBeanPostProcessors(beanFactory);
         // Initialize message source for this context.
         initMessageSource();
         // Initialize event multicaster for this context.
         initApplicationEventMulticaster();
         // Initialize other special beans in specific context subclasses.
         onRefresh();
         // Check for listener beans and register them.
         registerListeners();
         // Instantiate all remaining (non-lazy-init) singletons.
         finishBeanFactoryInitialization(beanFactory);
         // Last step: publish corresponding event.
         finishRefresh();
      }
      catch (BeansException ex) {
         if (logger.isWarnEnabled()) {
            logger.warn("Exception encountered during context initialization - " +
                  "cancelling refresh attempt: " + ex);
         }
         // Destroy already created singletons to avoid dangling resources.
         destroyBeans();
         // Reset 'active' flag.
         cancelRefresh(ex);
         // Propagate exception to caller.
         throw ex;
      }
      finally {
         // Reset common introspection caches in Spring's core, since we
         // might not ever need metadata for singleton beans anymore...
         resetCommonCaches();
      }
   }
}

prepareRefresh()方法做准备工作,实现中没有做什么事。

bean的加载----obtainFreshBeanFactory

obtainFreshBeanFactory是核心方法步骤,这个方法主要就是构建beanFactory以及加载所有需要定义成bean的对象,创建对应的beanDefinition。跟踪obtainFreshBeanFactory的方法,发现springcontext中定义的beanfactory是DefaultListableBeanFactory,这个是spring提供的一个默认的bean工厂实现类。

protected final void refreshBeanFactory() throws BeansException {
   if (hasBeanFactory()) {
      destroyBeans();
      closeBeanFactory();
   }
   try {
      DefaultListableBeanFactory beanFactory = createBeanFactory();
      beanFactory.setSerializationId(getId());
      customizeBeanFactory(beanFactory);
      loadBeanDefinitions(beanFactory);
      synchronized (this.beanFactoryMonitor) {
         this.beanFactory = beanFactory;
      }
   }
   catch (IOException ex) {
      throw new ApplicationContextException("I/O error parsing bean definition source for " + getDisplayName(), ex);
   }
}

customizeBeanFactory是对这个beanfactory的定制,这里定制了两个属性,一个是allowBeanDefinitionOverriding,就是是否允许bean覆盖定义,默认是允许的,当有两个相同名字的bean定义时,后者会覆盖前者;另一个是allowCircularReferences,就是是否允许bean的循环引用,默认是允许的,后面会讲spring是如何解决bean的循环引用的。默认的DefaultListableBeanFactory这两个配置项是true,不需要修改。

loadBeanDefinitions方法是核心方法,这个方法就是把spring里面所有需要其管理的bean对象给加载起来(只是定义,没有初始化)

protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) throws BeansException, IOException {
   // Create a new XmlBeanDefinitionReader for the given BeanFactory.
   XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory);
   // Configure the bean definition reader with this context's
   // resource loading environment.
   beanDefinitionReader.setEnvironment(this.getEnvironment());
   beanDefinitionReader.setResourceLoader(this);
   beanDefinitionReader.setEntityResolver(new ResourceEntityResolver(this));
   // Allow a subclass to provide custom initialization of the reader,
   // then proceed with actually loading the bean definitions.
   initBeanDefinitionReader(beanDefinitionReader);
   loadBeanDefinitions(beanDefinitionReader);
}

这个XmlBeanDefinitionReader是xml文件的bean解析器,代码到这里,beanfactory的bean的定义模型beanDefinition的读取实际是交给beanDefinitionReader这个对象来做的,因为我们开始选择的是ClassPathXmlApplicationContext,所以这里加载beandefinition是加载的xml形式定义的,所以实际上所有的xml中定义的bean的读取的就是这个对象XmlBeanDefinitionReader完成的。上面的核心代码在于loadBeanDefinitions(beanDefinitionReader)这个方法,这个方法里面就把applicationContext的loadBeanDefinition动作交给了XmlBeanDefinitionReader去完成,实际上就是XmlBeanDefinitionReader进行loadBeanDefinitions

protected void loadBeanDefinitions(XmlBeanDefinitionReader reader) throws BeansException, IOException {
   Resource[] configResources = getConfigResources();
   if (configResources != null) {
      reader.loadBeanDefinitions(configResources);
   }
   String[] configLocations = getConfigLocations();
   if (configLocations != null) {
      reader.loadBeanDefinitions(configLocations);
   }
}

这个方法里面是加载bean对象,getConfigResources获取资源配置,这个资源配置就是我们在定义ClassPathXmlApplicationContext对象的时候传入的,如果为空,则加载默认的配置文件/WEB-INF/applicationContext.xml(用的云服务nuwa容器启动时候,会将相关的配置资源加载进去),跟踪这个loadBeanDefinitions方法可以看到,reader是遍历加载configLocations,由于applicationcontext继承ResourcePatternResolver,说明applicationcontext的resourceLoader是通配符匹配resource路径,然后把每个resourcelocation下正则匹配的resource文件进行解析,继续跟踪代码走到doLoadBeanDefinitions

protected int doLoadBeanDefinitions(InputSource inputSource, Resource resource)
      throws BeanDefinitionStoreException {
   try {
      Document doc = doLoadDocument(inputSource, resource);
      return registerBeanDefinitions(doc, resource);
   }
   catch (BeanDefinitionStoreException ex) {
      throw ex;
   }
   ...
}

doLoadBeanDefinitions里面有两行有效代码,一个doLoadDocument就是从resource资源文件读取出来,加载到Document对象中,这里主要是DOM的解析,不做分析,另外一个registerBeanDefinitions就是真正将doc中定义的bean解析成beanDefinition对象,注册到beanfactory中。

public int registerBeanDefinitions(Document doc, Resource resource) throws BeanDefinitionStoreException {
		BeanDefinitionDocumentReader documentReader = createBeanDefinitionDocumentReader();
		int countBefore = getRegistry().getBeanDefinitionCount();
		documentReader.registerBeanDefinitions(doc, createReaderContext(resource));
		return getRegistry().getBeanDefinitionCount() - countBefore;
	}

这里BeanDefinitionDocumentReader 对象是用来读取一个doc文件中的beandefinition的,每一个resource都被封装成一个xmlreaderContext (注意这个xmlreaderContext 里面会指定一个NamespaceHandlerResolver,这个resolver是用来解析我们配置的xml的)。调用的方法registerBeanDefinitions

protected void doRegisterBeanDefinitions(Element root) {
		BeanDefinitionParserDelegate parent = this.delegate;
		this.delegate = createDelegate(getReaderContext(), root, parent);
		if (this.delegate.isDefaultNamespace(root)) {
			String profileSpec = root.getAttribute(PROFILE_ATTRIBUTE);
			if (StringUtils.hasText(profileSpec)) {
				String[] specifiedProfiles = StringUtils.tokenizeToStringArray(
						profileSpec, BeanDefinitionParserDelegate.MULTI_VALUE_ATTRIBUTE_DELIMITERS);
				if (!getReaderContext().getEnvironment().acceptsProfiles(specifiedProfiles)) {
					if (logger.isInfoEnabled()) {
						logger.info("Skipped XML bean definition file due to specified profiles [" + profileSpec +
								"] not matching: " + getReaderContext().getResource());
					}
					return;
				}
			}
		}
		preProcessXml(root);
		parseBeanDefinitions(root, this.delegate);
		postProcessXml(root);
		this.delegate = parent;
	}

但是这里用了一个BeanDefinitionParserDelegate,这个delegate是readerContext的代理,这个方法中,核心代码是parseBeanDefinitions

protected void parseBeanDefinitions(Element root, BeanDefinitionParserDelegate delegate) {
   if (delegate.isDefaultNamespace(root)) {
      NodeList nl = root.getChildNodes();
      for (int i = 0; i < nl.getLength(); i++) {
         Node node = nl.item(i);
         if (node instanceof Element) {
            Element ele = (Element) node;
            if (delegate.isDefaultNamespace(ele)) {
               parseDefaultElement(ele, delegate);
            }
            else {
               delegate.parseCustomElement(ele);
            }
         }
      }
   }
   else {
      delegate.parseCustomElement(root);
   }
}

解析过程是从root开始的,每个元素进行解析,根据元素的命名空间区分是自带的还是用户自定义的,先看下系统自带的元素

public static final String ALIAS_ATTRIBUTE = "alias";
public static final String IMPORT_ELEMENT = "import";
public static final String RESOURCE_ATTRIBUTE = "resource";
public static final String NESTED_BEANS_ELEMENT = "beans";
private void parseDefaultElement(Element ele, BeanDefinitionParserDelegate delegate) {
   if (delegate.nodeNameEquals(ele, IMPORT_ELEMENT)) {
      importBeanDefinitionResource(ele);
   }
   else if (delegate.nodeNameEquals(ele, ALIAS_ELEMENT)) {
      processAliasRegistration(ele);
   }
   else if (delegate.nodeNameEquals(ele, BEAN_ELEMENT)) {
      processBeanDefinition(ele, delegate);
   }
   else if (delegate.nodeNameEquals(ele, NESTED_BEANS_ELEMENT)) {
      // recurse
      doRegisterBeanDefinitions(ele);
   }
}

可以看出这里就是解析几种常见的配置bean的元素,注意在处理beans的时候,是用递归的方式处理bean的加载。下面看下custom的方式,在配置xml中有很多是自定义的,比如,等等,这里讲下这些自定义格式的bean的加载与解析。

自定义标签----元素解析

public BeanDefinition parseCustomElement(Element ele, BeanDefinition containingBd) {
   String namespaceUri = getNamespaceURI(ele);
   NamespaceHandler handler = this.readerContext.getNamespaceHandlerResolver().resolve(namespaceUri);
   if (handler == null) {
      error("Unable to locate Spring NamespaceHandler for XML schema namespace [" + namespaceUri + "]", ele);
      return null;
   }
   return handler.parse(ele, new ParserContext(this.readerContext, this, containingBd));
}

首先获取元素的命名空间,根据命名空间获取对应的解析器,然后用解析器去执行元素的解析工作,这里看下handler对象是从readerContext中获取的,分析下这个handler代码,getNamespaceHandlerResolver获取命名空间对应的处理器的解析器,spring中提供了一个默认的解析器DefaultNamespaceHandlerResolver,维护namespace跟handler的解析关系,核心点在于维护一个map,key就是namespace,value就是对应的handler

public NamespaceHandler resolve(String namespaceUri) {
   Map<String, Object> handlerMappings = getHandlerMappings();
   Object handlerOrClassName = handlerMappings.get(namespaceUri);
   if (handlerOrClassName == null) {
      return null;
   }
   else if (handlerOrClassName instanceof NamespaceHandler) {
      return (NamespaceHandler) handlerOrClassName;
   }
   else {
      String className = (String) handlerOrClassName;
      try {
         Class<?> handlerClass = ClassUtils.forName(className, this.classLoader);
         if (!NamespaceHandler.class.isAssignableFrom(handlerClass)) {
            throw new FatalBeanException("Class [" + className + "] for namespace [" + namespaceUri +
                  "] does not implement the [" + NamespaceHandler.class.getName() + "] interface");
         }
         NamespaceHandler namespaceHandler = (NamespaceHandler) BeanUtils.instantiateClass(handlerClass);
         namespaceHandler.init();
         handlerMappings.put(namespaceUri, namespaceHandler);
         return namespaceHandler;
      }
      catch (ClassNotFoundException ex) {
         throw new FatalBeanException("NamespaceHandler class [" + className + "] for namespace [" +
               namespaceUri + "] not found", ex);
      }
      catch (LinkageError err) {
         throw new FatalBeanException("Invalid NamespaceHandler class [" + className + "] for namespace [" +
               namespaceUri + "]: problem with handler class file or dependent class", err);
      }
   }
}

上面的代码逻辑比较简单,就是从一个map中获取这个namespace对应的handler,这个handler对象可以是handler实例本身,也可以是类名称,如果是类名称的话,就类加载器加载,NamespaceHandler是一个接口,spring提供了一个适配器类NamespaceHandlerSupport,实现了NamespaceHandler接口的通用方法,把配置解析绑定到BeanDefinitionParser上,一个配置对应一个BeanDefinitionParser,维护到一个map里面,那么NamespaceHandler的parse接口,就是获取对应parser来处理。

public BeanDefinition parse(Element element, ParserContext parserContext) {
   return findParserForElement(element, parserContext).parse(element, parserContext);
}
private BeanDefinitionParser findParserForElement(Element element, ParserContext parserContext) {
   String localName = parserContext.getDelegate().getLocalName(element);
   BeanDefinitionParser parser = this.parsers.get(localName);
   if (parser == null) {
      parserContext.getReaderContext().fatal(
            "Cannot locate BeanDefinitionParser for element [" + localName + "]", element);
   }
   return parser;
}

所以我们可以看到一个NamespaceHandler对应的是一种namespace处理器,一般也是一个xml里面,比如我们说的对应的就一个DubboNamespaceHandler,而一个xml里面可以有多种配置前缀,比如里面有、等,里面每一个小的配置类型对应的是一个parser,这个parser做的事情就是把对应的配置定义转换成beanDefinition,注册到beanfactory中(这个beanfactory在对应的readerContext里面)所以我们看下dubbo的DubboNamespaceHandler的类的定义

public class DubboNamespaceHandler extends NamespaceHandlerSupport {
    static {
        Version.checkDuplicate(DubboNamespaceHandler.class);
    }
    @Override
    public void init() {
        registerBeanDefinitionParser("application", new DubboBeanDefinitionParser(ApplicationConfig.class, true));
        registerBeanDefinitionParser("module", new DubboBeanDefinitionParser(ModuleConfig.class, true));
        registerBeanDefinitionParser("registry", new DubboBeanDefinitionParser(RegistryConfig.class, true));
        registerBeanDefinitionParser("monitor", new DubboBeanDefinitionParser(MonitorConfig.class, true));
        registerBeanDefinitionParser("provider", new DubboBeanDefinitionParser(ProviderConfig.class, true));
        registerBeanDefinitionParser("consumer", new DubboBeanDefinitionParser(ConsumerConfig.class, true));
        registerBeanDefinitionParser("protocol", new DubboBeanDefinitionParser(ProtocolConfig.class, true));
        registerBeanDefinitionParser("service", new DubboBeanDefinitionParser(ServiceBean.class, true));
        registerBeanDefinitionParser("reference", new DubboBeanDefinitionParser(ReferenceBean.class, false));
        registerBeanDefinitionParser("annotation", new AnnotationBeanDefinitionParser());
    }

在init方法地方把每个配置类型以及对应的parser注册到namespaceHandler里面,然后这个DubboNamespaceHandler又通过SPI方式注册到NamespaceHandlerResolver里面,我们看下前面提到的DefaultNamespaceHandlerResolver里面如何加载这些定义的namespaceHandler的。

private Map<String, Object> getHandlerMappings() {
   if (this.handlerMappings == null) {
      synchronized (this) {
         if (this.handlerMappings == null) {
            try {
               Properties mappings =
                     PropertiesLoaderUtils.loadAllProperties(this.handlerMappingsLocation, this.classLoader);
               if (logger.isDebugEnabled()) {
                  logger.debug("Loaded NamespaceHandler mappings: " + mappings);
               }
               Map<String, Object> handlerMappings = new ConcurrentHashMap<String, Object>(mappings.size());
               CollectionUtils.mergePropertiesIntoMap(mappings, handlerMappings);
               this.handlerMappings = handlerMappings;
            }
            catch (IOException ex) {
               throw new IllegalStateException(
                     "Unable to load NamespaceHandler mappings from location [" + this.handlerMappingsLocation + "]", ex);
            }
         }
      }
   }
   return this.handlerMappings;
}
public static final String DEFAULT_HANDLER_MAPPINGS_LOCATION = "META-INF/spring.handlers";

里面的PropertiesLoaderUtils.loadAllProperties就是用来加载namespaceHandler,这里的this.handlerMappingsLocation 最终初始化的是META-INF/spring.handlers。至于自定义的parser如何解析这里就不分析了。
里面的PropertiesLoaderUtils.loadAllProperties就是用来加载namespaceHandler,这里的this.handlerMappingsLocation 最终初始化的是META-INF/spring.handlers。至于自定义的parser如何解析这里就不分析了。

小结

spring对bean的解析(xml)有两种,原生定义了几种标签,比如、、等,这些spring提供默认的处理,还可以支持拓展的,spring中也拓展了很多bean格式,比如context标签,dubbo也拓展了,拓展bean的标签的目的是用户自定义bean的创建方式。对应的步骤如下:

  1. 首先要定义dtd文件,定义自己要用的标签元素、属性以及对应的子元素等等
  2. 自定义NamespaceHandler子类,可以继承NamespaceHandlerSupport,然后对于每个子配置类型,需要自定义对应的BeanDefinitionParser,每个parser就是对我们自定义标签的解析。
  3. 然后在对应的NamespaceHandler类里面进行注册----在init方法中调用registerBeanDefinitionParser方法,把每个parser注册进去。
  4. 在META-INF/spring.handlers文件里面按照SPI配置自定义的NamespaceHandler由DefaultNamespaceHandlerResolver加载。

自定义配置案例分析----componant-scan、annotation-config配置解析

component-scan配置就是自定义配置的一种,就是xml配置中配置,他的作用是用来扫描包路径下所有的类文件,对表明@Component注解的类加载成bean对象。对应的NamespaceHandler是ContextNamespaceHandler,举例一个配置

<context:component-scan base-package="com.vrv.paw.dao,com.vrv.paw.service,com.vrv.paw.action" />

代码如下

public class ContextNamespaceHandler extends NamespaceHandlerSupport {
   @Override
   public void init() {
      registerBeanDefinitionParser("property-placeholder", new PropertyPlaceholderBeanDefinitionParser());
      registerBeanDefinitionParser("property-override", new PropertyOverrideBeanDefinitionParser());
      registerBeanDefinitionParser("annotation-config", new AnnotationConfigBeanDefinitionParser());
      registerBeanDefinitionParser("component-scan", new ComponentScanBeanDefinitionParser());
      registerBeanDefinitionParser("load-time-weaver", new LoadTimeWeaverBeanDefinitionParser());
      registerBeanDefinitionParser("spring-configured", new SpringConfiguredBeanDefinitionParser());
      registerBeanDefinitionParser("mbean-export", new MBeanExportBeanDefinitionParser());
      registerBeanDefinitionParser("mbean-server", new MBeanServerBeanDefinitionParser());
   }
}

看到component-scan子配置对应的解析类为ComponentScanBeanDefinitionParser,查看对应的parse实现

public BeanDefinition parse(Element element, ParserContext parserContext) {
   String basePackage = element.getAttribute(BASE_PACKAGE_ATTRIBUTE);
   basePackage = parserContext.getReaderContext().getEnvironment().resolvePlaceholders(basePackage);
   String[] basePackages = StringUtils.tokenizeToStringArray(basePackage,
         ConfigurableApplicationContext.CONFIG_LOCATION_DELIMITERS);

   // Actually scan for bean definitions and register them.
   ClassPathBeanDefinitionScanner scanner = configureScanner(parserContext, element);
   Set<BeanDefinitionHolder> beanDefinitions = scanner.doScan(basePackages);
   registerComponents(parserContext.getReaderContext(), beanDefinitions, element);

   return null;
}

BASE_PACKAGE_ATTRIBUTE对应的配置项就是 base-package,解析获取对应的package列表,创建ClassPathBeanDefinitionScanner对象scanner,来扫描这些base-packages下的bean注解定义,然后把扫描出来的beanDefinitions注册到beanfactory中,这里的核心方法就是doScan。注意下在doScan之前的方法configureScanner,这个就是为了获取一个scanner,后面会讲到这个方法。

protected Set<BeanDefinitionHolder> doScan(String... basePackages) {
   Assert.notEmpty(basePackages, "At least one base package must be specified");
   Set<BeanDefinitionHolder> beanDefinitions = new LinkedHashSet<BeanDefinitionHolder>();
   for (String basePackage : basePackages) {
      Set<BeanDefinition> candidates = findCandidateComponents(basePackage);
      for (BeanDefinition candidate : candidates) {
         ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(candidate);
         candidate.setScope(scopeMetadata.getScopeName());
         String beanName = this.beanNameGenerator.generateBeanName(candidate, this.registry);
         if (candidate instanceof AbstractBeanDefinition) {
            postProcessBeanDefinition((AbstractBeanDefinition) candidate, beanName);
         }
         if (candidate instanceof AnnotatedBeanDefinition) {
            AnnotationConfigUtils.processCommonDefinitionAnnotations((AnnotatedBeanDefinition) candidate);
         }
         if (checkCandidate(beanName, candidate)) {
            BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(candidate, beanName);
            definitionHolder =
                  AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);
            beanDefinitions.add(definitionHolder);
            registerBeanDefinition(definitionHolder, this.registry);
         }
      }
   }
   return beanDefinitions;
}

这个方法就是遍历所有的basePackage,把对应package下的bean都加载起来,扫描的方法是findCandidateComponents,进入这个方法(筛选主要部分)

public Set<BeanDefinition> findCandidateComponents(String basePackage) {
   Set<BeanDefinition> candidates = new LinkedHashSet<BeanDefinition>();
   try {
      String packageSearchPath = ResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX +
            resolveBasePackage(basePackage) + '/' + this.resourcePattern;
      Resource[] resources = this.resourcePatternResolver.getResources(packageSearchPath);
      boolean traceEnabled = logger.isTraceEnabled();
      boolean debugEnabled = logger.isDebugEnabled();
      for (Resource resource : resources) {
         if (traceEnabled) {
            logger.trace("Scanning " + resource);
         }
         if (resource.isReadable()) {
            try {
               MetadataReader metadataReader = this.metadataReaderFactory.getMetadataReader(resource);
               if (isCandidateComponent(metadataReader)) {
                  ScannedGenericBeanDefinition sbd = new ScannedGenericBeanDefinition(metadataReader);
                  sbd.setResource(resource);
                  sbd.setSource(resource);
                  if (isCandidateComponent(sbd)) {
                     candidates.add(sbd);
                  }
             ...
   return candidates;
}

从上面代码可以看出先用resourcePatternResolver获取这个basePackage下的class文件,加载成resource,这个resourcePatternResolver对应的类是PathMatchingResourcePatternResolver,就是类路径资源解析器,不进入分析。下面是对每个resource获取对应的MetadataReader,这个MetadataReader对象是用来获取class类文件的元数据的,包括注解、Class类元数据等。然后isCandidateComponent方法就是判断这个类是否有注解

protected boolean isCandidateComponent(MetadataReader metadataReader) throws IOException {
   for (TypeFilter tf : this.excludeFilters) {
      if (tf.match(metadataReader, this.metadataReaderFactory)) {
         return false;
      }
   }
   for (TypeFilter tf : this.includeFilters) {
      if (tf.match(metadataReader, this.metadataReaderFactory)) {
         return isConditionMatch(metadataReader);
      }
   }
   return false;
}

这里就是把metadata数据判断是否满足过滤器,也就是我们配置在<context: component-scan/>的子元素<context: include-filter/>中,这个子元素的配置是可以让我们自定义bean注解(比如这里我们配置com.huawei.chj.ChjAnnotation,那么@ChjAnnotation注解的类就会被扫描成bean),一般的我们不会去配置这个值,而是用默认的配置,对应的是属性use-default-filters=true,默认就是true,所以这里的includeFilters就是默认的filter,可以看下对应的定义,就是在前面我们调用configureScanner方法里面,我们回过来看下这个方法实现

protected ClassPathBeanDefinitionScanner configureScanner(ParserContext parserContext, Element element) {
   boolean useDefaultFilters = true;
   if (element.hasAttribute(USE_DEFAULT_FILTERS_ATTRIBUTE)) {
      useDefaultFilters = Boolean.valueOf(element.getAttribute(USE_DEFAULT_FILTERS_ATTRIBUTE));
   }

   // Delegate bean definition registration to scanner class.
   ClassPathBeanDefinitionScanner scanner = createScanner(parserContext.getReaderContext(), useDefaultFilters);
   scanner.setBeanDefinitionDefaults(parserContext.getDelegate().getBeanDefinitionDefaults());
   scanner.setAutowireCandidatePatterns(parserContext.getDelegate().getAutowireCandidatePatterns());

   if (element.hasAttribute(RESOURCE_PATTERN_ATTRIBUTE)) {
      scanner.setResourcePattern(element.getAttribute(RESOURCE_PATTERN_ATTRIBUTE));
   }

   try {
      parseBeanNameGenerator(element, scanner);
   }
   catch (Exception ex) {
      parserContext.getReaderContext().error(ex.getMessage(), parserContext.extractSource(element), ex.getCause());
   }

   try {
      parseScope(element, scanner);
   }
   catch (Exception ex) {
      parserContext.getReaderContext().error(ex.getMessage(), parserContext.extractSource(element), ex.getCause());
   }

   parseTypeFilters(element, scanner, parserContext);

   return scanner;
}

protected ClassPathBeanDefinitionScanner createScanner(XmlReaderContext readerContext, boolean useDefaultFilters) {
		return new ClassPathBeanDefinitionScanner(readerContext.getRegistry(), useDefaultFilters,
				readerContext.getEnvironment(), readerContext.getResourceLoader());
}

在这个方法里面就会调用createScanner方法创建scanner(其他的先不关注),里面就是new一个ClassPathBeanDefinitionScanner,看下这个类的构造函数:

public ClassPathBeanDefinitionScanner(BeanDefinitionRegistry registry, boolean useDefaultFilters,
      Environment environment, ResourceLoader resourceLoader) {

   Assert.notNull(registry, "BeanDefinitionRegistry must not be null");
   this.registry = registry;

   if (useDefaultFilters) {
      registerDefaultFilters();
   }
   setEnvironment(environment);
   setResourceLoader(resourceLoader);
}

到这里可以看到会调用registerDefaultFilters来初始化默认的filter,进入这个方法看下

javaprotected void registerDefaultFilters() {
   this.includeFilters.add(new AnnotationTypeFilter(Component.class));
   ClassLoader cl = ClassPathScanningCandidateComponentProvider.class.getClassLoader();
   try {
      this.includeFilters.add(new AnnotationTypeFilter(
            ((Class<? extends Annotation>) ClassUtils.forName("javax.annotation.ManagedBean", cl)), false));
      logger.debug("JSR-250 'javax.annotation.ManagedBean' found and supported for component scanning");
   }
   catch (ClassNotFoundException ex) {
      // JSR-250 1.1 API (as included in Java EE 6) not available - simply skip.
   }
   try {
      this.includeFilters.add(new AnnotationTypeFilter(
            ((Class<? extends Annotation>) ClassUtils.forName("javax.inject.Named", cl)), false));
      logger.debug("JSR-330 'javax.inject.Named' annotation found and supported for component scanning");
   }
   catch (ClassNotFoundException ex) {
      // JSR-330 API not available - simply skip.
   }
}

到这里我们就看到了这个filters里面把Component注解类加到filter中去了,这就是我们在类上配置@Component注解就会被扫描成bean的原因,当然这里不仅仅添加了Component,还有javax.annotation.ManagedBean跟javax.inject.Named,所以实际上我们在类上配置@ManagedBean跟@Named都是可以被扫描成bean的。

回到前面讲的findCandidateComponents方法,通过这个方法把所有的basePackage里面的类中注解@Component的加载成beandefinition,这些都是“候选”bean对象,接下来要对这些对象进行处理,主要方法是AnnotationConfigUtils.processCommonDefinitionAnnotations,进入这个方法分析下:

static void processCommonDefinitionAnnotations(AnnotatedBeanDefinition abd, AnnotatedTypeMetadata metadata) {
   AnnotationAttributes lazy = attributesFor(metadata, Lazy.class);
   if (lazy != null) {
      abd.setLazyInit(lazy.getBoolean("value"));
   }
   else if (abd.getMetadata() != metadata) {
      lazy = attributesFor(abd.getMetadata(), Lazy.class);
      if (lazy != null) {
         abd.setLazyInit(lazy.getBoolean("value"));
      }
   }

   if (metadata.isAnnotated(Primary.class.getName())) {
      abd.setPrimary(true);
   }
   AnnotationAttributes dependsOn = attributesFor(metadata, DependsOn.class);
   if (dependsOn != null) {
      abd.setDependsOn(dependsOn.getStringArray("value"));
   }

   AnnotationAttributes role = attributesFor(metadata, Role.class);
   if (role != null) {
      abd.setRole(role.getNumber("value").intValue());
   }
   AnnotationAttributes description = attributesFor(metadata, Description.class);
   if (description != null) {
      abd.setDescription(description.getString("value"));
   }
}

这里所说对common属性就是定义bean对属性,包括是否懒加载,是否有依赖的类,是否有描述的注解等等。这些在xml配置中是不要处理的,会在解析xml对时候就处理了。

到此doscan已经完成,此时所有对注解对bean都被扫描到了,但是还没有初始化,接下来的方法registerComponents很重要,网上资料说标签有了就不需要,包含进去了,具体实现就在这个方法中:

protected void registerComponents(
      XmlReaderContext readerContext, Set<BeanDefinitionHolder> beanDefinitions, Element element) {

   Object source = readerContext.extractSource(element);
   CompositeComponentDefinition compositeDef = new CompositeComponentDefinition(element.getTagName(), source);

   for (BeanDefinitionHolder beanDefHolder : beanDefinitions) {
      compositeDef.addNestedComponent(new BeanComponentDefinition(beanDefHolder));
   }

   // Register annotation config processors, if necessary.
   boolean annotationConfig = true;
   if (element.hasAttribute(ANNOTATION_CONFIG_ATTRIBUTE)) {
      annotationConfig = Boolean.parseBoolean(element.getAttribute(ANNOTATION_CONFIG_ATTRIBUTE));
   }
   if (annotationConfig) {
      Set<BeanDefinitionHolder> processorDefinitions =
            AnnotationConfigUtils.registerAnnotationConfigProcessors(readerContext.getRegistry(), source);
      for (BeanDefinitionHolder processorDefinition : processorDefinitions) {
         compositeDef.addNestedComponent(new BeanComponentDefinition(processorDefinition));
      }
   }

   readerContext.fireComponentRegistered(compositeDef);
}

前面的compositeDef先不用管,直接看到annotationConfig,默认这个配置是true,那么就会执行AnnotationConfigUtils.registerAnnotationConfigProcessors,这个方法比较长,但是做对事情比较简单,就是把ConfigurationClassPostProcessor、AutowiredAnnotationBeanPostProcessor、CommonAnnotationBeanPostProcessor(JSR-250)等processor加进来,这几个类ConfigurationClassPostProcessor-----处理@Configuration注解;AutowiredAnnotationBeanPostProcessor-----处理Autowired、value、inject注解;CommonAnnotationBeanPostProcessor----处理JSR-250标准对注解,比如说我们用的@Resource注解。这个注解对应对parser类就不再分析类,核心功能就是上面这个方法。

小结

回顾整个component-scan的流程,首先是我们在解析xml中,发现了有自定义的标签了,然后从用resolver解析器找到这个标签对应的namespaceHandler,这个namespaceHandler是保存在map中,初始化是通过SPI方式加载进来的(namespace-handler配置)。找到这个namespaceHandler后,解析标签,找到ComponentScanBeanDefinitionParser解析类,这个类就会根据component-scan中配置的basePackage来扫描对应的class类,把有注解@Component的类作为候选bean,处理下这些类上的其他的类注解:比如是否懒加载、是否有依赖、是否有描述等等。处理好了后就把这些beandefinition注册到beanfactory中,最后再添加@Configuration、@Autowire 的注解处理器。这样这个scan流程就完成了。

所以可以知道xml中定义的bean跟@Component注解的bean在构建beanfactory的时候就已经加载到beanfactory中,但是@Configuration注解的类以及类里面@Bean注解的方法此时还没有加载,以及每个bean中的IOC都没有做,这些事情是在后面调用

小结

到这里此时完成了方法obtainFreshBeanFactory(),仅仅把所有的xml中定义的bean以及@Component注解的bean都已经加载到beanfatcory中了,流程比较清晰,先创建一个默认的beanfactory,然后把指定location的resource给加载解析,从xml中分析出bean对象来,注册到beanfactory中,这里的beandefinition是无差别的,不管是普通的bean,还是factorybean,还是各种processor。

beanfactory后置处理----invokeBeanFactoryPostProcessors

此时的bean还是一个beanDefinition对象,没有初始化,只是做了构造创建。接下来prepareBeanFactory、postProcessBeanFactory做了初步配置,暂时不做分析,下面是invokeBeanFactoryPostProcessors方法,这个是spring的非常核心的一个方法调用,很多的业务定制都在这里完成的,比如说我们的@Configuration。这个方法是调用所有beanfactoryPostProcessor,执行对应的postProcessBeanFactory方法。

spring提供了beanfactoryPostProcessor接口,这个是spring在加载beandefinition后,初始化bean前,做的操作,用来给给我们对beanfactory中的beandefinition做一些定制。另外还有一个BeanDefinitionRegistryPostProcessor接口,这个接口用来给业务做自定义的beandefinition的注册

这个里面主要是用到对应的代理方法:PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors,这个方法很长,逐步来分析

public static void invokeBeanFactoryPostProcessors(
      ConfigurableListableBeanFactory beanFactory, List<BeanFactoryPostProcessor> beanFactoryPostProcessors) {
   // Invoke BeanDefinitionRegistryPostProcessors first, if any.
   Set<String> processedBeans = new HashSet<String>();

   if (beanFactory instanceof BeanDefinitionRegistry) {
      BeanDefinitionRegistry registry = (BeanDefinitionRegistry) beanFactory;
      List<BeanFactoryPostProcessor> regularPostProcessors = new LinkedList<BeanFactoryPostProcessor>();
      List<BeanDefinitionRegistryPostProcessor> registryProcessors = new LinkedList<BeanDefinitionRegistryPostProcessor>();

      for (BeanFactoryPostProcessor postProcessor : beanFactoryPostProcessors) {
         if (postProcessor instanceof BeanDefinitionRegistryPostProcessor) {
            BeanDefinitionRegistryPostProcessor registryProcessor =
                  (BeanDefinitionRegistryPostProcessor) postProcessor;
            registryProcessor.postProcessBeanDefinitionRegistry(registry);
            registryProcessors.add(registryProcessor);
         }
         else {
            regularPostProcessors.add(postProcessor);
         }
      }
   // 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 = new ArrayList<BeanDefinitionRegistryPostProcessor>();

	// First, invoke the BeanDefinitionRegistryPostProcessors that implement PriorityOrdered.
String[] postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
for (String ppName : postProcessorNames) {
	if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
		currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
		processedBeans.add(ppName);
	}
} 
sortPostProcessors(currentRegistryProcessors, beanFactory);
registryProcessors.addAll(currentRegistryProcessors);
invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
currentRegistryProcessors.clear();
       。。。

这个方法很长,干的事情很清晰,就是把spring容器中BeanFactoryPostProcessor类型的bean单独拿出来处理这个流程整理如下:

  1. 从beanfactory中取出类型BeanDefinitionRegistryPostProcessor的beandefinistion列表
  2. 过滤出实现接口PriorityOrdered的Processors,然后排序
  3. 执行这些BeanDefinitionRegistryPostProcessors的postProcessBeanDefinitionRegistry方法
  4. 重新从beanfactory中取出类型BeanDefinitionRegistryPostProcessor的beandefinistion列表
  5. 过滤出实现接口Ordered的Processors,然后排序
  6. 执行这些BeanDefinitionRegistryPostProcessors的postProcessBeanDefinitionRegistry方法
  7. 重新从beanfactory中取出类型BeanDefinitionRegistryPostProcessor的beandefinistion列表
  8. 执行这些BeanDefinitionRegistryPostProcessors的postProcessBeanDefinitionRegistry方法
  9. 执行上面这些BeanDefinitionRegistryPostProcessors的postProcessBeanFactory方法
  10. 从beanfactory中取出类型BeanFactoryPostProcessor的beandefinistion列表
  11. 按照上面的顺序从PriorityOrdered、Ordered、普通的三种顺序来执行对应的postProcessBeanFactory

说明1:对于步骤4跟步骤7,需要重新从beanfactory中获取beandefinistion列表是因为前面每一次操作都可能会创建新的BeanDefinitionRegistryPostProcessor的beandefinition,所以需要重新获取

说明2:每次处理低优先级的processor时,都会去检查已处理列表,避免被多次执行。

这样整理下流程就比较清晰。前面在处理自定义标签的时候,在对应的namespaceHandler里面,doScan的时候,我们注册了三个processor,其中有一个是ConfigurationClassPostProcessor,这个是处理@Configuration的,以这个为例分析下BeanDefinitionRegistryPostProcessor的具体处理过程

BeanDefinitionRegistryPostProcessor处理分析----ConfigurationClassPostProcessor

ConfigurationClassPostProcessor是用来处理@Configurtaion的,看下对应的处理方法

@Override
public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) {
   int registryId = System.identityHashCode(registry);
   if (this.registriesPostProcessed.contains(registryId)) {
      throw new IllegalStateException(
            "postProcessBeanDefinitionRegistry already called on this post-processor against " + registry);
   }
   if (this.factoriesPostProcessed.contains(registryId)) {
      throw new IllegalStateException(
            "postProcessBeanFactory already called on this post-processor against " + registry);
   }
   this.registriesPostProcessed.add(registryId);
   processConfigBeanDefinitions(registry);
}
public void processConfigBeanDefinitions(BeanDefinitionRegistry registry) {
		List<BeanDefinitionHolder> configCandidates = new ArrayList<>();
		String[] candidateNames = registry.getBeanDefinitionNames();
         // 1、从所有的候选的bean中,筛选出@Configuration注解的bean
		for (String beanName : candidateNames) {
			BeanDefinition beanDef = 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);
				}
			}
			else if (ConfigurationClassUtils.checkConfigurationClassCandidate(beanDef, this.metadataReaderFactory)) {
				configCandidates.add(new BeanDefinitionHolder(beanDef, beanName));
			}
		}
		// Return immediately if no @Configuration classes were found
		if (configCandidates.isEmpty()) {
			return;
		}
		// Sort by previously determined @Order value, if applicable
		configCandidates.sort((bd1, bd2) -> {
			int i1 = ConfigurationClassUtils.getOrder(bd1.getBeanDefinition());
			int i2 = ConfigurationClassUtils.getOrder(bd2.getBeanDefinition());
			return Integer.compare(i1, i2);
		});
		// Detect any custom bean name generation strategy supplied through the enclosing application context
		SingletonBeanRegistry sbr = null;
		if (registry instanceof SingletonBeanRegistry) {
			sbr = (SingletonBeanRegistry) registry;
			if (!this.localBeanNameGeneratorSet) {
				BeanNameGenerator generator = (BeanNameGenerator) sbr.getSingleton(
						AnnotationConfigUtils.CONFIGURATION_BEAN_NAME_GENERATOR);
				if (generator != null) {
					this.componentScanBeanNameGenerator = generator;
					this.importBeanNameGenerator = generator;
				}
			}
		}
		if (this.environment == null) {
			this.environment = new StandardEnvironment();
		}
		// Parse each @Configuration class
		ConfigurationClassParser parser = new ConfigurationClassParser(
				this.metadataReaderFactory, this.problemReporter, this.environment,
				this.resourceLoader, this.componentScanBeanNameGenerator, registry);

		Set<BeanDefinitionHolder> candidates = new LinkedHashSet<>(configCandidates);
		Set<ConfigurationClass> alreadyParsed = new HashSet<>(configCandidates.size());
		do {
			StartupStep processConfig = this.applicationStartup.start("spring.context.config-classes.parse");
            // 解析bean
			parser.parse(candidates);
			parser.validate();

			Set<ConfigurationClass> configClasses = new LinkedHashSet<>(parser.getConfigurationClasses());
			configClasses.removeAll(alreadyParsed);

			// Read the model and create bean definitions based on its content
			if (this.reader == null) {
				this.reader = new ConfigurationClassBeanDefinitionReader(
						registry, this.sourceExtractor, this.resourceLoader, this.environment,
						this.importBeanNameGenerator, parser.getImportRegistry());
			}
			this.reader.loadBeanDefinitions(configClasses);
			alreadyParsed.addAll(configClasses);
			processConfig.tag("classCount", () -> String.valueOf(configClasses.size())).end();

			candidates.clear();
			if (registry.getBeanDefinitionCount() > candidateNames.length) {
				String[] newCandidateNames = registry.getBeanDefinitionNames();
				Set<String> oldCandidateNames = new HashSet<>(Arrays.asList(candidateNames));
				Set<String> alreadyParsedClasses = new HashSet<>();
				for (ConfigurationClass configurationClass : alreadyParsed) {
					alreadyParsedClasses.add(configurationClass.getMetadata().getClassName());
				}
				for (String candidateName : newCandidateNames) {
					if (!oldCandidateNames.contains(candidateName)) {
						BeanDefinition bd = registry.getBeanDefinition(candidateName);
						if (ConfigurationClassUtils.checkConfigurationClassCandidate(bd, this.metadataReaderFactory) &&
								!alreadyParsedClasses.contains(bd.getBeanClassName())) {
							candidates.add(new BeanDefinitionHolder(bd, candidateName));
						}
					}
				}
				candidateNames = newCandidateNames;
			}
		}
		while (!candidates.isEmpty());
		// Register the ImportRegistry as a bean in order to support ImportAware @Configuration classes
		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();
		}
	}
public static boolean checkConfigurationClassCandidate(
      BeanDefinition beanDef, MetadataReaderFactory metadataReaderFactory) {
   String className = beanDef.getBeanClassName();
   if (className == null || beanDef.getFactoryMethodName() != null) {
      return false;
   }
   AnnotationMetadata metadata;
   if (beanDef instanceof AnnotatedBeanDefinition &&
         className.equals(((AnnotatedBeanDefinition) beanDef).getMetadata().getClassName())) {
      // Can reuse the pre-parsed metadata from the given BeanDefinition...
      metadata = ((AnnotatedBeanDefinition) beanDef).getMetadata();
   }
   else if (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)) {
         return false;
      }
      metadata = AnnotationMetadata.introspect(beanClass);
   }
   else {
      try {
         MetadataReader metadataReader = 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);
         }
         return false;
      }
   }
   Map<String, Object> config = metadata.getAnnotationAttributes(Configuration.class.getName());
   if (config != null && !Boolean.FALSE.equals(config.get("proxyBeanMethods"))) {
      beanDef.setAttribute(CONFIGURATION_CLASS_ATTRIBUTE, CONFIGURATION_CLASS_FULL);
   }
   else if (config != null || isConfigurationCandidate(metadata)) {
      beanDef.setAttribute(CONFIGURATION_CLASS_ATTRIBUTE, CONFIGURATION_CLASS_LITE);
   }
   else {
      return false;
   }
   // It's a full or lite configuration candidate... Let's determine the order value, if any.
   Integer order = getOrder(metadata);
   if (order != null) {
      beanDef.setAttribute(ORDER_ATTRIBUTE, order);
   }
   return true;
}
  1. 首先是从所有的beandefinition中获取@configuration注解的bean,主要是方法ConfigurationClassUtils.checkConfigurationClassCandidate,这个检查动作主要就是获取bean的注解是否是@configuration,是就作为注解类
  2. 将待处理的bean进行处理,处理流程主要是在doProcessConfigurationClass方法中完成, 在@Configurtaion中主要处理的事情:
  3. 处理内部类的注解(包含component,import,configuration、@bean等等),这个是一个递归处理
  4. 处理@PropertySource 注解
  5. 处理@Component-scan注解
  6. 处理@import @importSource注解
  7. 处理@Bean注解,注意这里处理bean注解不是直接解析bean,而是把方法加入到beanMethod中,待后面处理

注意下,这里说的各种注解必须是在@Configuration注解下的,否则不会被处理,这是因为这些注解的处理都是在处理@Configuration中处理的。@PropertySource 是导入配置文件,configruationPlaceHolder就是处理各种PropertySource对象,@Import处理导入的对象为bean,@ImportSource处理导入的xml配置

这里有processMemberClasses的方法,可以看下源码,因为是递归调用。所以当我们内部类之间是循环导入的就会出现死循环,报错,一般很少出现这样的问题,而且有个问题待验证:我们在component-scan的时候,会把类以及内部类都扫描到,如果有注解才会成bean,那么对于一个普通的含有内部类的bean,这里的内部类是否不需要再处理了?因为已经被scan了,只有是启动springcontext的那个启动类本身才需要处理内部类?这个待验证

protected final SourceClass doProcessConfigurationClass(
      ConfigurationClass configClass, SourceClass sourceClass, Predicate<String> filter)
      throws IOException {

   if (configClass.getMetadata().isAnnotated(Component.class.getName())) {
      // Recursively process any member (nested) classes first
      processMemberClasses(configClass, sourceClass, filter);
   }

   // Process any @PropertySource annotations
   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
   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
         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) {
            BeanDefinition bdCand = holder.getBeanDefinition().getOriginatingBeanDefinition();
            if (bdCand == null) {
               bdCand = holder.getBeanDefinition();
            }
            if (ConfigurationClassUtils.checkConfigurationClassCandidate(bdCand, this.metadataReaderFactory)) {
               parse(bdCand.getBeanClassName(), holder.getBeanName());
            }
         }
      }
   }

   // Process any @Import annotations
   processImports(configClass, sourceClass, getImports(sourceClass), filter, true);

   // Process any @ImportResource annotations
   AnnotationAttributes importResource =
         AnnotationConfigUtils.attributesFor(sourceClass.getMetadata(), ImportResource.class);
   if (importResource != null) {
      String[] resources = importResource.getStringArray("locations");
      Class<? extends BeanDefinitionReader> readerClass = importResource.getClass("reader");
      for (String resource : resources) {
         String resolvedResource = this.environment.resolveRequiredPlaceholders(resource);
         configClass.addImportedResource(resolvedResource, readerClass);
      }
   }

   // Process individual @Bean methods
   Set<MethodMetadata> beanMethods = retrieveBeanMethodMetadata(sourceClass);
   for (MethodMetadata methodMetadata : beanMethods) {
      configClass.addBeanMethod(new BeanMethod(methodMetadata, configClass));
   }

   // Process default methods on interfaces
   processInterfaces(configClass, sourceClass);

   // Process superclass, if any
   if (sourceClass.getMetadata().hasSuperClass()) {
      String superclass = sourceClass.getMetadata().getSuperClassName();
      if (superclass != null && !superclass.startsWith("java") &&
            !this.knownSuperclasses.containsKey(superclass)) {
         this.knownSuperclasses.put(superclass, configClass);
         // Superclass found, return its annotation metadata and recurse
         return sourceClass.getSuperClass();
      }
   }

   // No superclass -> processing is complete
   return null;
}

bean的初始化–finishBeanFactoryInitialization

经过前面的beanfactorypostprocessor之后,当前spring容器的所有的bean都被加载到容器中,下面就需要进行实例化与初始化了,这部分的代码会比较长。

public void preInstantiateSingletons() 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.
   List<String> beanNames = new ArrayList<>(this.beanDefinitionNames);

   // Trigger initialization of all non-lazy singleton beans...
   for (String beanName : beanNames) {
      RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
      if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
         if (isFactoryBean(beanName)) {
            Object bean = getBean(FACTORY_BEAN_PREFIX + beanName);
            if (bean instanceof FactoryBean) {
               FactoryBean<?> factory = (FactoryBean<?>) bean;
               boolean isEagerInit;
               if (System.getSecurityManager() != null && factory instanceof SmartFactoryBean) {
                  isEagerInit = AccessController.doPrivileged(
                        (PrivilegedAction<Boolean>) ((SmartFactoryBean<?>) factory)::isEagerInit,
                        getAccessControlContext());
               }
               else {
                  isEagerInit = (factory instanceof SmartFactoryBean &&
                        ((SmartFactoryBean<?>) factory).isEagerInit());
               }
               if (isEagerInit) {
                  getBean(beanName);
               }
            }
         }
         else {
            getBean(beanName);
         }
      }
   }

   // Trigger post-initialization callback for all applicable beans...
   for (String beanName : beanNames) {
      Object singletonInstance = getSingleton(beanName);
      if (singletonInstance instanceof SmartInitializingSingleton) {
         StartupStep smartInitialize = this.getApplicationStartup().start("spring.beans.smart-initialize")
               .tag("beanName", beanName);
         SmartInitializingSingleton smartSingleton = (SmartInitializingSingleton) singletonInstance;
         if (System.getSecurityManager() != null) {
            AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
               smartSingleton.afterSingletonsInstantiated();
               return null;
            }, getAccessControlContext());
         }
         else {
            smartSingleton.afterSingletonsInstantiated();
         }
         smartInitialize.end();
      }
   }
}

上面的流程比较清楚,总结流程如下:

  1. 获取加载的beandefinition列表,获取merged过后的beandefinition对象,getMergedLocalBeanDefinition方法下面重点分析
  2. 过滤出非抽象的,单例的,非懒加载的beandefinition进行初始化
  3. 判断是否是factorybean,如果是,按照factorybean的方式处理,如果是普通的bean,则调用getbean方式来初始化
  4. 过滤出实现SmartInitializingSingleton的bean,做一些初始化后的后置处理

这里面 有两个核心方法:getMergedLocalBeanDefinition,getBean

bean的整理–getMergedLocalBeanDefinition

前面加载的beandefinition仅仅是定义了bean以及做了简单的配置,有些bean需要合并些配置,比如说父子bean对象,需要合并后才是一个完整的beandefinition

protected RootBeanDefinition getMergedLocalBeanDefinition(String beanName) throws BeansException {
   // Quick check on the concurrent map first, with minimal locking.
   RootBeanDefinition mbd = this.mergedBeanDefinitions.get(beanName);
   if (mbd != null && !mbd.stale) {
      return mbd;
   }
   return getMergedBeanDefinition(beanName, getBeanDefinition(beanName));
}
protected RootBeanDefinition getMergedBeanDefinition(
			String beanName, BeanDefinition bd, @Nullable BeanDefinition containingBd)
			throws BeanDefinitionStoreException {
		synchronized (this.mergedBeanDefinitions) {
			RootBeanDefinition mbd = null;
			RootBeanDefinition previous = null;
			// Check with full lock now in order to enforce the same merged instance.
			if (containingBd == null) {
				mbd = this.mergedBeanDefinitions.get(beanName);
			}
			if (mbd == null || mbd.stale) {
				previous = mbd;
				if (bd.getParentName() == null) {
					// Use copy of given root bean definition.
					if (bd instanceof RootBeanDefinition) {
						mbd = ((RootBeanDefinition) bd).cloneBeanDefinition();
					}
					else {
						mbd = new RootBeanDefinition(bd);
					}
				}
				else {
					// Child bean definition: needs to be merged with parent.
					BeanDefinition pbd;
					try {
						String parentBeanName = transformedBeanName(bd.getParentName());
						if (!beanName.equals(parentBeanName)) {
							pbd = getMergedBeanDefinition(parentBeanName);
						}
						else {
							BeanFactory parent = getParentBeanFactory();
							if (parent instanceof ConfigurableBeanFactory) {
								pbd = ((ConfigurableBeanFactory) parent).getMergedBeanDefinition(parentBeanName);
							}
							else {
								throw new NoSuchBeanDefinitionException(parentBeanName,
										"Parent name '" + parentBeanName + "' is equal to bean name '" + beanName +
												"': cannot be resolved without a ConfigurableBeanFactory parent");
							}
						}
					}
					catch (NoSuchBeanDefinitionException ex) {
						throw new BeanDefinitionStoreException(bd.getResourceDescription(), beanName,
								"Could not resolve parent bean definition '" + bd.getParentName() + "'", ex);
					}
					// Deep copy with overridden values.
					mbd = new RootBeanDefinition(pbd);
					mbd.overrideFrom(bd);
				}

				// Set default singleton scope, if not configured before.
				if (!StringUtils.hasLength(mbd.getScope())) {
					mbd.setScope(SCOPE_SINGLETON);
				}
				// A bean contained in a non-singleton bean cannot be a singleton itself.
				// Let's correct this on the fly here, since this might be the result of
				// parent-child merging for the outer bean, in which case the original inner bean
				// definition will not have inherited the merged outer bean's singleton status.
				if (containingBd != null && !containingBd.isSingleton() && mbd.isSingleton()) {
					mbd.setScope(containingBd.getScope());
				}
				// Cache the merged bean definition for the time being
				// (it might still get re-merged later on in order to pick up metadata changes)
				if (containingBd == null && isCacheBeanMetadata()) {
					this.mergedBeanDefinitions.put(beanName, mbd);
				}
			}
			if (previous != null) {
				copyRelevantMergedBeanDefinitionCaches(previous, mbd);
			}
			return mbd;
		}
	}

这个方法主要是处理那些不是完整的bean的,因为spring支持bean的继承(类似我们把公共部分提取到parent中),parent不支持实例化,子bean不能直接实例化,所以才有这个方法的,看下方法的逻辑

  1. 从spring容器beandefinitionMap中根据这个beanName获取beandefinition。
  2. 检查这个beandefinition是否有parentdefinition,如果没有,则说明这个bean就是一个完整的beandefinition,直接将其转换成RootBeanDefinition。
  3. 如果这个bean有parentdefinition,则递归去获取parentbeandefinition,然后将子beandefinition 与其合并,调用overrideFrom方法完成。

到此,所有的bean都是完整的了。

bean初始化与获取----getBean

spring容器中,不管是factorybean还是普通的bean,都是通过方法getBean来进行初始化的。这个方法非常长,可以分段分析

protected <T> T doGetBean(
      String name, @Nullable Class<T> requiredType, @Nullable Object[] args, boolean typeCheckOnly)
      throws BeansException {

   String beanName = transformedBeanName(name);
   Object bean;

   // Eagerly check singleton cache for manually registered singletons.
   Object sharedInstance = 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);
   }

首先是transformedBeanName,这个是获取bean的Name,在spring中,对于factorybean,beanname是有前缀&的,这个方法就是把这个&给过滤掉。然后getSingleton方法从map中获取这个bean,因为我们此时初始化bean是单例的,非单例不在这里初始化,获取的时候优先从这个map中获取,没有才考虑去创建。如果map中有的话,直接去取,但是bean有两种,一种是factorybean,一种是普通bean,两种bean的获取方式是不一样的,进入这个方法看下具体的实现getObjectForBeanInstance

protected Object getObjectForBeanInstance(
      Object beanInstance, String name, String beanName, @Nullable RootBeanDefinition mbd) {

   // Don't let calling code try to dereference the factory if the bean isn't a factory.
   if (BeanFactoryUtils.isFactoryDereference(name)) {
      if (beanInstance instanceof NullBean) {
         return beanInstance;
      }
      if (!(beanInstance instanceof FactoryBean)) {
         throw new BeanIsNotAFactoryException(beanName, beanInstance.getClass());
      }
      if (mbd != null) {
         mbd.isFactoryBean = true;
      }
      return beanInstance;
   }

   // Now we have the bean instance, which may be a normal bean or a FactoryBean.
   // If it's a FactoryBean, we use it to create a bean instance, unless the
   // caller actually wants a reference to the factory.
   if (!(beanInstance instanceof FactoryBean)) {
      return beanInstance;
   }

   Object object = null;
   if (mbd != null) {
      mbd.isFactoryBean = true;
   }
   else {
      object = getCachedObjectForFactoryBean(beanName);
   }
   if (object == null) {
      // Return bean instance from factory.
      FactoryBean<?> factory = (FactoryBean<?>) beanInstance;
      // Caches object obtained from FactoryBean if it is a singleton.
      if (mbd == null && containsBeanDefinition(beanName)) {
         mbd = getMergedLocalBeanDefinition(beanName);
      }
      boolean synthetic = (mbd != null && mbd.isSynthetic());
      object = getObjectFromFactoryBean(factory, beanName, !synthetic);
   }
   return object;
}
  1. 这个方法,首先是用BeanFactoryUtils.isFactoryDereference(name)判断是否是factorybean,如果是以&开头,则必须是factorybean(但是这里注意下并不是所有的factorybean的name都是以&开头,对于不去显示配置beanname的bean,spring会给他分配一个beanname,以&开头),然后直接返回这个bean;
  2. 如果查询的name是一个普通的name,对应的bean可能也是factorybean,如果是普通的bean,那么就直接返回
  3. 如果是一个factorybean,先从对应的缓存加载,如果缓存没有,则直接从factorybean中创建

factorybean创建bean

protected Object getObjectFromFactoryBean(FactoryBean<?> factory, String beanName, boolean shouldPostProcess) {
   if (factory.isSingleton() && containsSingleton(beanName)) {
      synchronized (getSingletonMutex()) {
         Object object = this.factoryBeanObjectCache.get(beanName);
         if (object == null) {
            object = doGetObjectFromFactoryBean(factory, beanName);
            // Only post-process and store if not put there already during getObject() call above
            // (e.g. because of circular reference processing triggered by custom getBean calls)
            Object alreadyThere = this.factoryBeanObjectCache.get(beanName);
            if (already There != null) {
               object = alreadyThere;
            }
            else {
               if (shouldPostProcess) {
                  if (isSingletonCurrentlyInCreation(beanName)) {
                     // Temporarily return non-post-processed object, not storing it yet..
                     return object;
                  }
                  beforeSingletonCreation(beanName);
                  try {
                     object = postProcessObjectFromFactoryBean(object, beanName);
                  }
                  catch (Throwable ex) {
                     throw new BeanCreationException(beanName,
                           "Post-processing of FactoryBean's singleton object failed", ex);
                  }
                  finally {
                     afterSingletonCreation(beanName);
                  }
               }
               if (containsSingleton(beanName)) {
                  this.factoryBeanObjectCache.put(beanName, object);
               }
            }
         }
         return object;
      
   }
   else {
      Object object = doGetObjectFromFactoryBean(factory, beanName);
      if (shouldPostProcess) {
         try {
            object = postProcessObjectFromFactoryBean(object, beanName);
         }
         catch (Throwable ex) {
            throw new BeanCreationException(beanName, "Post-processing of FactoryBean's object failed", ex);
         }
      }
      return object;
   }
}
private Object doGetObjectFromFactoryBean(FactoryBean<?> factory, String beanName) throws BeanCreationException {
		Object object;
		try {
			if (System.getSecurityManager() != null) {
				AccessControlContext acc = getAccessControlContext();
				try {
					object = AccessController.doPrivileged((PrivilegedExceptionAction<Object>) factory::getObject, acc);
				}
				catch (PrivilegedActionException pae) {
					throw pae.getException();
				}
			}
			else {
				object = factory.getObject();
			}
		}
		catch (FactoryBeanNotInitializedException ex) {
			throw new BeanCurrentlyInCreationException(beanName, ex.toString());
		}
		catch (Throwable ex) {
			throw new BeanCreationException(beanName, "FactoryBean threw exception on object creation", ex);
		}

		// Do not accept a null value for a FactoryBean that's not fully
		// initialized yet: Many FactoryBeans just return null then.
		if (object == null) {
			if (isSingletonCurrentlyInCreation(beanName)) {
				throw new BeanCurrentlyInCreationException(
						beanName, "FactoryBean which is currently in creation returned null from getObject");
			}
			object = new NullBean();
		}
		return object;
	}

代码里面写的很长,主要的工作就是getObject,从这个方法中获取bean对象,对于factorybean本身,spring容器中也有对应bean,但是获取的时候,只会获取对应的object对象

回到前面说的doGetbean方法的else部分,此时在缓存中并没有对应的bean,需要我们创建

else {
      // Fail if we're already creating this bean instance:
      // We're assumably within a circular reference.
      if (isPrototypeCurrentlyInCreation(beanName)) {
         throw new BeanCurrentlyInCreationException(beanName);
      }

      // Check if bean definition exists in this factory.
      BeanFactory parentBeanFactory = getParentBeanFactory();
      if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
         // Not found -> check parent.
         String nameToLookup = originalBeanName(name);
         if (parentBeanFactory instanceof AbstractBeanFactory) {
            return ((AbstractBeanFactory) parentBeanFactory).doGetBean(
                  nameToLookup, requiredType, args, typeCheckOnly);
         }
         else if (args != null) {
            // Delegation to parent with explicit args.
            return (T) parentBeanFactory.getBean(nameToLookup, args);
         }
         else if (requiredType != null) {
            // No args -> delegate to standard getBean method.
            return parentBeanFactory.getBean(nameToLookup, requiredType);
         }
         else {
            return (T) parentBeanFactory.getBean(nameToLookup);
         }
      }

      if (!typeCheckOnly) {
         markBeanAsCreated(beanName);
      }

      StartupStep beanCreation = this.applicationStartup.start("spring.beans.instantiate")
            .tag("beanName", name);
      try {
         if (requiredType != null) {
            beanCreation.tag("beanType", requiredType::toString);
         }
         RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
         checkMergedBeanDefinition(mbd, beanName, args);

         // Guarantee initialization of beans that the current bean depends on.
         String[] dependsOn = mbd.getDependsOn();
         if (dependsOn != null) {
            for (String dep : dependsOn) {
               if (isDependent(beanName, dep)) {
                  throw new BeanCreationException(mbd.getResourceDescription(), beanName,
                        "Circular depends-on relationship between '" + beanName + "' and '" + dep + "'");
               }
               registerDependentBean(dep, beanName);
               try {
                  getBean(dep);
               }
               catch (NoSuchBeanDefinitionException ex) {
                  throw new BeanCreationException(mbd.getResourceDescription(), beanName,
                        "'" + beanName + "' depends on missing bean '" + dep + "'", ex);
               }
            }
         }

         // Create bean instance.
         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 = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
         }

         else if (mbd.isPrototype()) {
            // It's a prototype -> create a new instance.
            Object prototypeInstance = null;
            try {
               beforePrototypeCreation(beanName);
               prototypeInstance = createBean(beanName, mbd, args);
            }
            finally {
               afterPrototypeCreation(beanName);
            }
            bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
         }

         else {
            String scopeName = mbd.getScope();
            if (!StringUtils.hasLength(scopeName)) {
               throw new IllegalStateException("No scope name defined for bean ´" + beanName + "'");
            }
            Scope scope = this.scopes.get(scopeName);
            if (scope == null) {
               throw new IllegalStateException("No Scope registered for scope name '" + scopeName + "'");
            }
            try {
               Object scopedInstance = scope.get(beanName, () -> {
                  beforePrototypeCreation(beanName);
                  try {
                     return createBean(beanName, mbd, args);
                  }
                  finally {
                     afterPrototypeCreation(beanName);
                  }
               });
               bean = getObjectForBeanInstance(scopedInstance, name, beanName, mbd);
            }
            catch (IllegalStateException ex) {
               throw new ScopeNotActiveException(beanName, scopeName, ex);
            }
         }
      }
      catch (BeansException ex) {
         beanCreation.tag("exception", ex.getClass().toString());
         beanCreation.tag("message", String.valueOf(ex.getMessage()));
         cleanupAfterBeanCreationFailure(beanName);
         throw ex;
      }
      finally {
         beanCreation.end();
      }
   }

   // Check if required type matches the type of the actual bean instance.
   if (requiredType != null && !requiredType.isInstance(bean)) {
      try {
         T convertedBean = getTypeConverter().convertIfNecessary(bean, requiredType);
         if (convertedBean == null) {
            throw new BeanNotOfRequiredTypeException(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);
         }
         throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
      }
   }
   return (T) bean;
}

上面的流程可以归纳为如下:

  1. 检查这个beandefinition有没有对应的parentfactory,如果有的话并且当前beanfactory中也没有对应的beandifinition,就用对应的factory创建。
  2. 检查当前获取bean是否是检查,如果是则直接返回
  3. 检查当前beandefinition的depend-on属性,如果有以来,则先实例化所有的依赖的bean
  4. 根据bean的属性是否是单例调用对应的createbean方法来实例化bean,然后再调用getObjectForBeanInstance来获取bean。

核心的方法在于createbean方法

createbean

@Override
protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
      throws BeanCreationException {

   if (logger.isTraceEnabled()) {
      logger.trace("Creating instance of bean '" + beanName + "'");
   }
   RootBeanDefinition mbdToUse = 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.
   Class<?> resolvedClass = resolveBeanClass(mbd, beanName);
   if (resolvedClass != null && !mbd.hasBeanClass() && mbd.getBeanClassName() != null) {
      mbdToUse = new RootBeanDefinition(mbd);
      mbdToUse.setBeanClass(resolvedClass);
   }

   // Prepare method overrides.
   try {
      mbdToUse.prepareMethodOverrides();
   }
   catch (BeanDefinitionValidationException ex) {
      throw new BeanDefinitionStoreException(mbdToUse.getResourceDescription(),
            beanName, "Validation of method overrides failed", ex);
   }

   try {
      // Give BeanPostProcessors a chance to return a proxy instead of the target bean instance.
      Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
      if (bean != null) {
         return bean;
      }
   }
   catch (Throwable ex) {
      throw new BeanCreationException(mbdToUse.getResourceDescription(), beanName,
            "BeanPostProcessor before instantiation of bean failed", ex);
   }

   try {
      Object beanInstance = doCreateBean(beanName, mbdToUse, args);
      if (logger.isTraceEnabled()) {
         logger.trace("Finished creating instance of bean '" + beanName + "'");
      }
      return beanInstance;
   }
   catch (BeanCreationException | ImplicitlyAppearedSingletonException ex) {
      // A previously detected exception with proper bean creation context already,
      // or illegal singleton state to be communicated up to DefaultSingletonBeanRegistry.
      throw ex;
   }
   catch (Throwable ex) {
      throw new BeanCreationException(
            mbdToUse.getResourceDescription(), beanName, "Unexpected exception during bean creation", ex);
   }
}
protected Object doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
			throws BeanCreationException {

		// Instantiate the bean.
		BeanWrapper instanceWrapper = null;
		if (mbd.isSingleton()) {
			instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
		}
		if (instanceWrapper == null) {
			instanceWrapper = createBeanInstance(beanName, mbd, args);
		}
		Object bean = instanceWrapper.getWrappedInstance();
		Class<?> beanType = instanceWrapper.getWrappedClass();
		if (beanType != NullBean.class) {
			mbd.resolvedTargetType = beanType;
		}

		// Allow post-processors to modify the merged bean definition.
		synchronized (mbd.postProcessingLock) {
			if (!mbd.postProcessed) {
				try {
					applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
				}
				catch (Throwable ex) {
					throw new BeanCreationException(mbd.getResourceDescription(), beanName,
							"Post-processing of merged bean definition failed", ex);
				}
				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.isTraceEnabled()) {
				logger.trace("Eagerly caching bean '" + beanName +
						"' to allow for resolving potential circular references");
			}
			addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
		}

		// Initialize the bean instance.
		Object exposedObject = bean;
		try {
			populateBean(beanName, mbd, instanceWrapper);
			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<>(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 " +
								"'getBeanNamesForType' 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;
	}

整个创建bean的流程还是比较清晰的,主要流程如下:

  1. 首先检查容器中是否有InstantiationAwareBeanPostProcessor,这个接口的实现类是用来给我们提供一个拓展能力,进行定制bean,查看这个接口可以自定义往容器中添加bean,这个是spring在实例化bean之前,最后一次修改bean的机会。
  2. 实例化bean,可以是根据构造函数创建,也可以是工厂方法创建
  3. 获取MergedBeanDefinitionPostProcessor实例,应用到该bean实例上,比如说我们的@PostConstructor的解析,@Resource,@Autowire 在这个阶段都有处理,注意这里只是做简单的检验等处理,并没有解析。
  4. populateBean,这个阶段处理的事情主要是bean的属性设置,包括xml中配置的属性设置,@Autowire方法的注入就是在这里做的,下面会分析源码。
  5. initializebean,初始化bean,这里主要包括Aware接口的调用,@PostConstruct初始化方法,InitializeBean接口的方法,xml中配置的init的处理方法。

先看下populateBean这个方法的源码

populateBean

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 {
         // 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.
   if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
      for (InstantiationAwareBeanPostProcessor bp : getBeanPostProcessorCache().instantiationAware) {
         if (!bp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) {
            return;
         }
      }
   }

   PropertyValues pvs = (mbd.hasPropertyValues() ? mbd.getPropertyValues() : null);

   int resolvedAutowireMode = mbd.getResolvedAutowireMode();
   if (resolvedAutowireMode == AUTOWIRE_BY_NAME || resolvedAutowireMode == AUTOWIRE_BY_TYPE) {
      MutablePropertyValues newPvs = new MutablePropertyValues(pvs);
      // Add property values based on autowire by name if applicable.
      if (resolvedAutowireMode == AUTOWIRE_BY_NAME) {
         autowireByName(beanName, mbd, bw, newPvs);
      }
      // Add property values based on autowire by type if applicable.
      if (resolvedAutowireMode == 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 (InstantiationAwareBeanPostProcessor bp : getBeanPostProcessorCache().instantiationAware) {
         PropertyValues pvsToUse = bp.postProcessProperties(pvs, bw.getWrappedInstance(), beanName);
         if (pvsToUse == null) {
            if (filteredPds == null) {
               filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
            }
            pvsToUse = bp.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. 先处理InstantiationAwareBeanPostProcessor的postProcessAfterInstantiation,这个方法就是用来处理当前的bean的实例化有没有完成,如果完成了,那么就直接返回,目前还没有什么实现类做这个;
  2. 然后是根据Autowiredmode来处理,这里我们代码调试mode为AUTOWIRE_NO=0,什么意思呢,就是不会自动注入,但是显示的@Autowire方式还是会注入的。这里涉及到一个知识点就是AutowireCapableBeanFactory,默认的我们的bean的注入会根据bean中有@Autowire的时候会自动注入进来,没有这个注解的话,我们获取的bean中需要被注入的对象就是null,这个很好理解:A中依赖注入B,必须要显示在属性B对象上设置@Autowire,这样我们getbean A的时候里面的属性B才有,如果没有这个显示注解,属性B是null,但是如果我们getbean的方法换一种的话,我们是可以人为的帮A注入B对象,AutowireCapableBeanFactory beanFactory = context.getAutowireCapableBeanFactory();
    A a = (A) beanFactory.autowire(A.class, AutowireCapableBeanFactory.AUTOWIRE_BY_TYPE, false); B b = a.getB();这样就获取到B属性了。通过这种方式,可以人为的给A这个bean注入属性B了。
  3. 然后就是处理它的postProcessProperties方法,这个方法处理的就包含@Autowire的注入,而且还包含一些属性的设置,比如我们在xml中配置的属性值初始化,就是在这里完成的。

populatebean方法完成后,我们的依赖注入就完成了,前面createbean方法我们创建了bean对象,这里又设置了初始化属性值以及IOC依赖注入,接下来就是初始化这个bean了

initializeBean

protected Object initializeBean(String beanName, Object bean, @Nullable RootBeanDefinition mbd) {
   if (System.getSecurityManager() != null) {
      AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
         invokeAwareMethods(beanName, bean);
         return null;
      }, getAccessControlContext());
   }
   else {
      invokeAwareMethods(beanName, bean);
   }

   Object wrappedBean = bean;
   if (mbd == null || !mbd.isSynthetic()) {
      wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
   }

   try {
      invokeInitMethods(beanName, wrappedBean, mbd);
   }
   catch (Throwable ex) {
      throw new BeanCreationException(
            (mbd != null ? mbd.getResourceDescription() : null),
            beanName, "Invocation of init method failed", ex);
   }
   if (mbd == null || !mbd.isSynthetic()) {
      wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
   }

   return wrappedBean;
}

对于这个方法,不过多的讲细节了,注意下流程

  1. 首先是invokeAwareMethods方法调用,这个方法就是我们一系列的Aware接口,比如我们BeanNameAware,ApplicationContextAware就是在这个环节做的
  2. 然后是applyBeanPostProcessorsBeforeInitialization,这个是把所有的BeanPostProcessor里面的postProcessBeforeInitialization执行一遍,我们的@PostConstruct注解就是属于CommonAnnotationBeanPostProcessor这个processor然后被处理的
  3. 然后是invokeInitMethods,这个方法里面包含两部分,首先根据当前的bean有没有实现InitializingBean这个接口,如果实现了就会去执行这个接口的afterPropertiesSet方法进行初始化;然后再获取自定义的初始化方法,比如我们在xml中指定的init-Method方法,就会在这里被找出来。

所以我们这个的初始化流程就是

  1. 构造函数
  2. IOC依赖注入
  3. 初始化属性设置
  4. Aware钩子函数
  5. @PostConstruct注解初始化函数
  6. afterPropertiesSet初始化方法执行
  7. init-Method初始化方法执行。

到此,我们的spring的初始化流程讲完。