spring启动简析

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或者而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 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 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 handlerMappings = new ConcurrentHashMap(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,举例一个配置


代码如下

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 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 doScan(String... basePackages) {
   Assert.notEmpty(basePackages, "At least one base package must be specified");
   Set beanDefinitions = new LinkedHashSet();
   for (String basePackage : basePackages) {
      Set 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 findCandidateComponents(String basePackage) {
   Set candidates = new LinkedHashSet();
   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数据判断是否满足过滤器,也就是我们配置在的子元素中,这个子元素的配置是可以让我们自定义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) 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) 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 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 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 beanFactoryPostProcessors) {
   // Invoke BeanDefinitionRegistryPostProcessors first, if any.
   Set processedBeans = new HashSet();

   if (beanFactory instanceof BeanDefinitionRegistry) {
      BeanDefinitionRegistry registry = (BeanDefinitionRegistry) beanFactory;
      List regularPostProcessors = new LinkedList();
      List registryProcessors = new LinkedList();

      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 currentRegistryProcessors = new ArrayList();

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

            Set 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 oldCandidateNames = new HashSet<>(Arrays.asList(candidateNames));
                Set 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 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 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 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 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 readerClass = importResource.getClass("reader");
      for (String resource : resources) {
         String resolvedResource = this.environment.resolveRequiredPlaceholders(resource);
         configClass.addImportedResource(resolvedResource, readerClass);
      }
   }

   // Process individual @Bean methods
   Set 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 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) ((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) () -> {
               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 doGetBean(
      String name, @Nullable Class 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) 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 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) () -> {
         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的初始化流程讲完。

你可能感兴趣的:(spring启动简析)