美文网首页springboot
springboot-自动装配-源码解读解析ImportSele

springboot-自动装配-源码解读解析ImportSele

作者: 愤怒的奶牛 | 来源:发表于2020-08-05 21:05 被阅读0次

    前面我们阅读到了springboot 通过读取META-INF/spring.factories 配置文件中的类,并通过ImportSelector 接口返回给spring 容器,达到 加载Bean 的目的,现在我们来阅读spring 部分源码,看看 ImportSelector 接口返回的数据在spring 中是如何处理的。

    • springboot 启动源码
      为了解决上面这个问题,我们必须阅读部分springboot 源码,我们可以从启动类开始:
    SpringApplication.run(FastCodingApplication.class, args);
    
    • SpringApplication
    /**
         * Static helper that can be used to run a {@link SpringApplication} from the
         * specified source using default settings.
         * @param primarySource the primary source to load
         * @param args the application arguments (usually passed from a Java main method)
         * @return the running {@link ApplicationContext}
         */
        public static ConfigurableApplicationContext run(Class<?> primarySource,
                String... args) {
            return run(new Class<?>[] { primarySource }, args);
        }
    
    /**
         * Static helper that can be used to run a {@link SpringApplication} from the
         * specified sources using default settings and user supplied arguments.
         * @param primarySources the primary sources to load
         * @param args the application arguments (usually passed from a Java main method)
         * @return the running {@link ApplicationContext}
         */
        public static ConfigurableApplicationContext run(Class<?>[] primarySources,
                String[] args) {
            return new SpringApplication(primarySources).run(args);
        }
    
    /**    启动,最后会到这个方法
         * Run the Spring application, creating and refreshing a new
         * {@link ApplicationContext}.
         * @param args the application arguments (usually passed from a Java main method)
         * @return a running {@link ApplicationContext}
         */
        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;
        }
    
    • refreshContext(context);
    private void refreshContext(ConfigurableApplicationContext context) {
            refresh(context); // 继续进去
            if (this.registerShutdownHook) {
                try {
                    context.registerShutdownHook();
                }
                catch (AccessControlException ex) {
                    // Not allowed in some environments.
                }
            }
        }
    
    • refresh(context);
    /**
         * Refresh the underlying {@link ApplicationContext}.
         * @param applicationContext the application context to refresh
         */
        protected void refresh(ApplicationContext applicationContext) {
            Assert.isInstanceOf(AbstractApplicationContext.class, applicationContext);
            ((AbstractApplicationContext) applicationContext).refresh(); // 进去这里
        }
    

    // ((AbstractApplicationContext) applicationContext).refresh();

    • AbstractApplicationContext
        // 如果你以前阅读过spring的源码的话,一点很熟悉这个方法,当然,如果没有阅读过,也没有关系,我们不需要每个方法的知道是干啥,我们只关心这里有没有方法是和我们问题有关的:加载ImportSelector 接口返回的 Bean 。
          @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();
                }
            }
        }
    

    相关文章

      网友评论

        本文标题:springboot-自动装配-源码解读解析ImportSele

        本文链接:https://www.haomeiwen.com/subject/pcwdrktx.html