zoukankan      html  css  js  c++  java
  • SpringBoot 初始化流程以及各种常见第三方配置的源码实现

    带着这几个问题去分析SpringBoot 初始化以及扩展机制实现

      1.容器何时被创建,并默认配置了什么?

      2.Spring 容器依赖于哪个后置处理器进行bean 容器的装配?

      3.Spring 如何进行第三方的扩展包括@import注解  DeferredImportSelector 接口 以及  ImportSelector 接口处理过程

    spring 容器何时被创建:

    了解 web.xml 初始化spring 容器的童鞋不用看这个了 

    <1>  我们回顾一下我们在使用 ssm 框架时候,需要配置web.xml,在web.xml 中我们一定会配置(listener  以及 contextConfigLocation 属性)如下:

      <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>classpath:spring/*.xml</param-value>
      </context-param>
    
    <!--监听器配置,容器启动时候会被调用一次-->
     <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
      </listener>

      监听器初始化方法在容器启动的时候会被调用执行(这个是tomcat 调用的)

    /**
         * Initialize the root web application context.
         */
        @Override
        public void contextInitialized(ServletContextEvent event) {
            initWebApplicationContext(event.getServletContext());
        }

      之后就会创建XmlWebApplicationContext 容器

    try {
                    return ClassUtils.forName(contextClassName, ContextLoader.class.getClassLoader());
                }
    //反射创建XmlWebApplicationContext
        return (ConfigurableWebApplicationContext) BeanUtils.instantiateClass(contextClass);

      之后就是刷新的操作了:

    wac.refresh();

     监听器创建的Springcotext 容器是父容器,在监听器初始化成功后,将此容器放入servletContext 上下文中,由于servletContext 在各个 servlet之间参数是透明的,所以 DispatcherServlet

    初始化子容器的时候会根据上下文找到监听器初始化的父容器进行关联

                    servletContext.setAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE, this.context);

    --------回顾到这里,我们看一下SpringBoot 启动流程容器的创建方式:

    <2>  首先是主启动类

    @SpringBootApplication
    @MapperScan("com.tuibei.mapper")
    public class TuibeiApplication {
        public static void main(String[] args) {
          SpringApplication.run(TuibeiApplication.class, args);
        }
    }

        a. 我们一路点下去看它run 方法 ,也就是如下方法:

    public ConfigurableApplicationContext run(String... args) {
            StopWatch stopWatch = new StopWatch();
            stopWatch.start();
            ConfigurableApplicationContext context = null;
            Collection<SpringBootExceptionReporter> exceptionReporters = new ArrayList<>();
            configureHeadlessProperty();
            SpringApplicationRunListeners listeners = getRunListeners(args);
            listeners.starting();
            try {
                ApplicationArguments applicationArguments = new DefaultApplicationArguments(
                        args);
                ConfigurableEnvironment environment = prepareEnvironment(listeners,
                        applicationArguments);
                configureIgnoreBeanInfo(environment);
                Banner printedBanner = printBanner(environment);
                context = createApplicationContext();
                exceptionReporters = getSpringFactoriesInstances(
                        SpringBootExceptionReporter.class,
                        new Class[] { ConfigurableApplicationContext.class }, context);
                prepareContext(context, environment, listeners, applicationArguments,
                        printedBanner);
                refreshContext(context);
                afterRefresh(context, applicationArguments);
                stopWatch.stop();
                if (this.logStartupInfo) {
                    new StartupInfoLogger(this.mainApplicationClass)
                            .logStarted(getApplicationLog(), stopWatch);
                }
                listeners.started(context);
                callRunners(context, applicationArguments);
            }
            catch (Throwable ex) {
                handleRunFailure(context, ex, exceptionReporters, listeners);
                throw new IllegalStateException(ex);
            }
    
            try {
                listeners.running(context);
            }
            catch (Throwable ex) {
                handleRunFailure(context, ex, exceptionReporters, null);
                throw new IllegalStateException(ex);
            }
            return context;
        }

      b. 我们先主要看 这个方法进行创建容器:

     context = createApplicationContext();

      c .如下:判断类型反射创建的是  AnnotationConfigServletWebServerApplicationContext 容器

    protected ConfigurableApplicationContext createApplicationContext() {
            Class<?> contextClass = this.applicationContextClass;
            if (contextClass == null) {
                try {
                    switch (this.webApplicationType) {
                    case SERVLET:
                        contextClass = Class.forName(DEFAULT_SERVLET_WEB_CONTEXT_CLASS);
                        break;
                    case REACTIVE:
                        contextClass = Class.forName(DEFAULT_REACTIVE_WEB_CONTEXT_CLASS);
                        break;
                    default:
                        contextClass = Class.forName(DEFAULT_CONTEXT_CLASS);
                    }
                }
                catch (ClassNotFoundException ex) {
                    throw new IllegalStateException(
                            "Unable create a default ApplicationContext, "
                                    + "please specify an ApplicationContextClass",
                            ex);
                }
            }
            return (ConfigurableApplicationContext) BeanUtils.instantiateClass(contextClass);
        }

       d .如上通过反射创建了容器对象,我们具体看一下创建AnnotationConfigServletWebServerApplicationContext 容器对象的过程

        可以看到装配reader(f 步骤)    以及scanner (g 步骤)

    public AnnotationConfigServletWebServerApplicationContext() {
            this.reader = new AnnotatedBeanDefinitionReader(this);
            this.scanner = new ClassPathBeanDefinitionScanner(this);
        }

      e. 通过源码层层递进,我们可以我们熟悉的 Bean 工厂的实例化

    private final DefaultListableBeanFactory beanFactory;
        public GenericApplicationContext() {
            this.beanFactory = new DefaultListableBeanFactory();
        }

      f .reader 会给我们默认注册一些处理器(很重要,很重要,很重要

    public static void registerAnnotationConfigProcessors(BeanDefinitionRegistry registry) {
            registerAnnotationConfigProcessors(registry, null);
        }

      说一些我现在知道的一些注册的处理器:

       ConfigurationClassPostProcessor ------>这个处理器在springboot 中有主导的地位,基本上SpringBoot 上所有的be an  都是通过此处理器进行装配的,用来解析我们的@Configuration 各种注解,装配到容器中

      AutowiredAnnotationBeanPostProcessor ------> 这个用来进行处理自动注入的 像@AutoWrized 这样的注解

    public static Set<BeanDefinitionHolder> registerAnnotationConfigProcessors(
                BeanDefinitionRegistry registry, @Nullable Object source) {
    
            DefaultListableBeanFactory beanFactory = unwrapDefaultListableBeanFactory(registry);
            if (beanFactory != null) {
                if (!(beanFactory.getDependencyComparator() instanceof AnnotationAwareOrderComparator)) {
                    beanFactory.setDependencyComparator(AnnotationAwareOrderComparator.INSTANCE);
                }
                if (!(beanFactory.getAutowireCandidateResolver() instanceof ContextAnnotationAutowireCandidateResolver)) {
                    beanFactory.setAutowireCandidateResolver(new ContextAnnotationAutowireCandidateResolver());
                }
            }
    
            Set<BeanDefinitionHolder> beanDefs = new LinkedHashSet<>(8);
    
            if (!registry.containsBeanDefinition(CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME)) {
                RootBeanDefinition def = new RootBeanDefinition(ConfigurationClassPostProcessor.class);
                def.setSource(source);
                beanDefs.add(registerPostProcessor(registry, def, CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME));
            }
    
            if (!registry.containsBeanDefinition(AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME)) {
                RootBeanDefinition def = new RootBeanDefinition(AutowiredAnnotationBeanPostProcessor.class);
                def.setSource(source);
                beanDefs.add(registerPostProcessor(registry, def, AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME));
            }
    
            // Check for JSR-250 support, and if present add the CommonAnnotationBeanPostProcessor.
            if (jsr250Present && !registry.containsBeanDefinition(COMMON_ANNOTATION_PROCESSOR_BEAN_NAME)) {
                RootBeanDefinition def = new RootBeanDefinition(CommonAnnotationBeanPostProcessor.class);
                def.setSource(source);
                beanDefs.add(registerPostProcessor(registry, def, COMMON_ANNOTATION_PROCESSOR_BEAN_NAME));
            }
    
            // Check for JPA support, and if present add the PersistenceAnnotationBeanPostProcessor.
            if (jpaPresent && !registry.containsBeanDefinition(PERSISTENCE_ANNOTATION_PROCESSOR_BEAN_NAME)) {
                RootBeanDefinition def = new RootBeanDefinition();
                try {
                    def.setBeanClass(ClassUtils.forName(PERSISTENCE_ANNOTATION_PROCESSOR_CLASS_NAME,
                            AnnotationConfigUtils.class.getClassLoader()));
                }
                catch (ClassNotFoundException ex) {
                    throw new IllegalStateException(
                            "Cannot load optional framework class: " + PERSISTENCE_ANNOTATION_PROCESSOR_CLASS_NAME, ex);
                }
                def.setSource(source);
                beanDefs.add(registerPostProcessor(registry, def, PERSISTENCE_ANNOTATION_PROCESSOR_BEAN_NAME));
            }
    
            if (!registry.containsBeanDefinition(EVENT_LISTENER_PROCESSOR_BEAN_NAME)) {
                RootBeanDefinition def = new RootBeanDefinition(EventListenerMethodProcessor.class);
                def.setSource(source);
                beanDefs.add(registerPostProcessor(registry, def, EVENT_LISTENER_PROCESSOR_BEAN_NAME));
            }
    
            if (!registry.containsBeanDefinition(EVENT_LISTENER_FACTORY_BEAN_NAME)) {
                RootBeanDefinition def = new RootBeanDefinition(DefaultEventListenerFactory.class);
                def.setSource(source);
                beanDefs.add(registerPostProcessor(registry, def, EVENT_LISTENER_FACTORY_BEAN_NAME));
            }
    
            return beanDefs;
        }

       g.

      sacnner 这个我们点进去会很熟悉,就说用来进行处理包扫描到,与我们xml 配置的 <context:component-scan base-package="com.project" /> 这个一致,用来进行包扫描,使用默认的拦截器 

    /**
         * Create a new {@code ClassPathBeanDefinitionScanner} for the given bean factory.
         * @param registry the {@code BeanFactory} to load bean definitions into, in the form
         * of a {@code BeanDefinitionRegistry}
         */
        public ClassPathBeanDefinitionScanner(BeanDefinitionRegistry registry) {
            this(registry, true);
        }

      注册默认的拦截器,可以看到会默认扫描带有@Component 注解的类:

    /**
         * Register the default filter for {@link Component @Component}.
         * <p>This will implicitly register all annotations that have the
         * {@link Component @Component} meta-annotation including the
         * {@link Repository @Repository}, {@link Service @Service}, and
         * {@link Controller @Controller} stereotype annotations.
         * <p>Also supports Java EE 6's {@link javax.annotation.ManagedBean} and
         * JSR-330's {@link javax.inject.Named} annotations, if available.
         *
         */
        @SuppressWarnings("unchecked")
        protected 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.trace("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.trace("JSR-330 'javax.inject.Named' annotation found and supported for component scanning");
            }
            catch (ClassNotFoundException ex) {
                // JSR-330 API not available - simply skip.
            }
        }

      ----到这里容器就创建完成了 ,下来就是be an 工厂的装配了,就是我们的第二个问题

    Spring 容器依赖于哪个后置处理器进行bean 容器的装配

    SpringBoot 中 bean 工厂的Bean 工厂的装配是依赖于spring 容器创建时候默认注册的后置工厂处理器 ConfigurationClassPostProcessor 实现的,我们具体看一下它的触发流程:

    (1)Spring 容器的刷新方法(refresh):这个refresh()方法会触发容器刷新以及bean 工厂注册装配,以及扩展机制的实现逻辑,如下:

    org.springframework.context.support.AbstractApplicationContext.refresh()
    @Override
        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();
                }
            }
        }

     (2) ConfigurationClassPostProcessor 实现了 BeanDefinitionRegistryPostProcessor ,BeanDefinitionRegistryPostProcessor 是Spring 工厂注册的后置处理器,会在refresh()方法的  invokeBeanFactoryPostProcessors(beanFactory) 方法中调用;

    public class ConfigurationClassPostProcessor implements BeanDefinitionRegistryPostProcessor,
            PriorityOrdered, ResourceLoaderAware, BeanClassLoaderAware, EnvironmentAware {

    (3)在 invokeBeanFactoryPostProcessors(beanFactory)中,会执行如下的方法;

    // First, invoke the BeanDefinitionRegistryPostProcessors that implement PriorityOrdered.
    //1. 在Spring bean工厂中找到实现 BeabDefinitionRegistryPostProcessor 的类,
    //2.getBean () 进行实例化;
    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);
          // 3.调用 invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry); currentRegistryProcessors.clear();

    调用逻辑,就是调用 BeabDefinitionRegistryPostProcessor的  postProcessBeanDefinitionRegistry() 方法

    /**
         * Invoke the given BeanDefinitionRegistryPostProcessor beans.
         */
        private static void invokeBeanDefinitionRegistryPostProcessors(
                Collection<? extends BeanDefinitionRegistryPostProcessor> postProcessors, BeanDefinitionRegistry registry) {
    
            for (BeanDefinitionRegistryPostProcessor postProcessor : postProcessors) {
                postProcessor.postProcessBeanDefinitionRegistry(registry);
            }
        }

    (4)ConfigurationClassPostProcessor 就是实现了BeabDefinitionRegistryPostProcessor 后置工厂处理接口, 所以也会被调用,如下标红代码就会处理我们springBoot 的各种包扫描,Configuration Bean Condition import 一些我们扩展,并注册成为be an

        /**
         * Derive further bean definitions from the configuration classes in the registry.
         */
        @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);
        }

     我们就开始分析  ConfigurationClassPostProcessor 后置工厂处理器的逻辑也就是我们的第三个问题

    spring 如何进行扩展的实现以及注解的解析

      (1)我们先进入ConfigurationClassPostProcessor 的processConfigBeanDefinitions(registry) 方法:

    public void processConfigBeanDefinitions(BeanDefinitionRegistry registry) {
            List<BeanDefinitionHolder> configCandidates = new ArrayList<>();
        //获取到目前所有的Bean 工厂的名字 String[] candidateNames
    = registry.getBeanDefinitionNames();     //选取合适的的configCandudates ,这里最后选取出来的是我们的主启动类的bean for (String beanName : candidateNames) { BeanDefinition beanDef = registry.getBeanDefinition(beanName); if (ConfigurationClassUtils.isFullConfigurationClass(beanDef) || ConfigurationClassUtils.isLiteConfigurationClass(beanDef)) { 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(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 取解析每一个@Configuration 注解
    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 {
            //解析入口方方法,去进行实际的操作 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); 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(); } }

    (2)如上代码,可以得知解析@Configuration 的入口就是 parser.parse(candidates) 方法;

    public void parse(Set<BeanDefinitionHolder> configCandidates) {
            for (BeanDefinitionHolder holder : configCandidates) {
                BeanDefinition bd = holder.getBeanDefinition();
                try {
                    if (bd instanceof AnnotatedBeanDefinition) {
                        parse(((AnnotatedBeanDefinition) bd).getMetadata(), holder.getBeanName());
                    }
                    else if (bd instanceof AbstractBeanDefinition && ((AbstractBeanDefinition) bd).hasBeanClass()) {
                        parse(((AbstractBeanDefinition) bd).getBeanClass(), holder.getBeanName());
                    }
                    else {
                        parse(bd.getBeanClassName(), holder.getBeanName());
                    }
                }
                catch (BeanDefinitionStoreException ex) {
                    throw ex;
                }
                catch (Throwable ex) {
                    throw new BeanDefinitionStoreException(
                            "Failed to parse configuration class [" + bd.getBeanClassName() + "]", ex);
                }
            }
        //处理@import 导入的实现了DeferredImportSelector 接口的be an,这个是最后执行的;
            this.deferredImportSelectorHandler.process();
        }
      深入点下去会看到:这个方法是递归的方法,这个方法基本上说处理了几乎所有的be an 配置
    
    protected final SourceClass doProcessConfigurationClass(ConfigurationClass configClass, SourceClass sourceClass)
                throws IOException {
    
            if (configClass.getMetadata().isAnnotated(Component.class.getName())) {
                // Recursively process any member (nested) classes first
                processMemberClasses(configClass, sourceClass);
            }
    
            // 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
        //处理@import注解 比如实现接口ImportSelector  ImportBeanDefinitionRegistrar 的类 以及导入普通的类
    
            processImports(configClass, sourceClass, getImports(sourceClass), 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;
        }

    @import 注解扩展实现:

      @import 可以说说springboot 扩展的一个重要实现了,很多的注解的实现都会依赖import 注解,只有了解了import 注解的解析流程,才能玩转boot

      code 地址:org.springframework.context.annotation.ConfigurationClassParser#processImports

    private void processImports(ConfigurationClass configClass, ConfigurationClassParser.SourceClass currentSourceClass,
                                    Collection<ConfigurationClassParser.SourceClass> importCandidates, boolean checkForCircularImports) {
    
            //1.没有得到解析的类信息,直接返回
            if (importCandidates.isEmpty()) {
                return;
            }
    
            if (checkForCircularImports && isChainedImportOnStack(configClass)) {
                this.problemReporter.error(new ConfigurationClassParser.CircularImportProblem(configClass, this.importStack));
            }
            else {
                this.importStack.push(configClass);
                try {
                    //2.分析@import
                    for (ConfigurationClassParser.SourceClass candidate : importCandidates) {
                            //3.如果 是实现了ImportSelector 接口的类
                        if (candidate.isAssignable(ImportSelector.class)) {
                            // Candidate class is an ImportSelector -> delegate to it to determine imports
                            Class<?> candidateClass = candidate.loadClass();
                            ImportSelector selector = BeanUtils.instantiateClass(candidateClass, ImportSelector.class);
                            ParserStrategyUtils.invokeAwareMethods(
                                    selector, this.environment, this.resourceLoader, this.registry);
                            //4.如果是实现了DeferredImportSelector 的类, DeferredImportSelector extends ImportSelector
                            if (selector instanceof DeferredImportSelector) {
                                //将实现了DeferredImportSelector 的类放入延迟的一个list 结构中,在parse 解析完之后最后执行
                                this.deferredImportSelectorHandler.handle(
                                        configClass, (DeferredImportSelector) selector);
                            }
                            else {
                                //5.ImportSelector 接口的类,调用其selectImports 方法
                                String[] importClassNames = selector.selectImports(currentSourceClass.getMetadata());
                                //6.转换为SourceClass
                                Collection<ConfigurationClassParser.SourceClass> importSourceClasses = asSourceClasses(importClassNames);
                                //7.再递归一遍 processImports操作
                                processImports(configClass, currentSourceClass, importSourceClasses, false);
                            }
                        }
                        //7.对于实现了 ImportBeanDefinitionRegistrar 的类,属于注册bean
                        else if (candidate.isAssignable(ImportBeanDefinitionRegistrar.class)) {
                            // Candidate class is an ImportBeanDefinitionRegistrar ->
                            // delegate to it to register additional bean definitions
                            Class<?> candidateClass = candidate.loadClass();
                            ImportBeanDefinitionRegistrar registrar =
                                    BeanUtils.instantiateClass(candidateClass, ImportBeanDefinitionRegistrar.class);
                            ParserStrategyUtils.invokeAwareMethods(
                                    registrar, this.environment, this.resourceLoader, this.registry);
                            //8.放入Map中,后面统一执行注册
                            configClass.addImportBeanDefinitionRegistrar(registrar, currentSourceClass.getMetadata());
                        }
                        else {
                            // Candidate class not an ImportSelector or ImportBeanDefinitionRegistrar ->
                            // process it as an @Configuration class
                            this.importStack.registerImport(
                                    currentSourceClass.getMetadata(), candidate.getMetadata().getClassName());
                            //9.其他类类型都会当作@Configuration 类进行解析
                            processConfigurationClass(candidate.asConfigClass(configClass));
                        }
                    }
                }
                catch (BeanDefinitionStoreException ex) {
                    throw ex;
                }
                catch (Throwable ex) {
                    throw new BeanDefinitionStoreException(
                            "Failed to process import candidates for configuration class [" +
                                    configClass.getMetadata().getClassName() + "]", ex);
                }
                finally {
                    this.importStack.pop();
                }
            }
        }

      从上面代码可以看到,这个方法会处理4中类型的数据:

      1.类 实现了 ImportSelector :会立马进行初始化并 运行其 selectImports 方法

      2.类实现了  DeferredImportSelector :见名之意,延迟的导入,会将信息保存放入一个handle list 中 ,会在parse 完之后的 org.springframework.context.annotation.ConfigurationClassParser.DeferredImportSelectorHandler#process  这个方法中进行调用。

      3.类实现了 ImportBeanDefinitionRegistrar :进行类的装配,bean 注册,会将信息放留在map 结构中,最终会在当前类解析完后的      org.springframework.context.annotation.ConfigurationClassBeanDefinitionReader#loadBeanDefinitions  这个方法中调用。

      4.其他类:会当作@Configuration 类进行解析。

      关于 2.3 调用顺序 先进行2 的解析然后在进行3的解析。

  • 相关阅读:
    jquery 源码学习(二)
    附加作业2
    附加题1
    实验八:一维数组的应用
    第七次作业总结
    第七次作业
    实验六:函数
    Thanks for your encourage!
    实验五:循环结构
    作业四 分支结构
  • 原文地址:https://www.cnblogs.com/iscys/p/9961158.html
Copyright © 2011-2022 走看看