Spring源码8. prepareContext()准备应用上下文

上篇回顾

上一篇SpringBootExceptionReporter异常上报中分析了springboot如何处理启动过程中的异常


目录

1. 准备容器prepareContext()
2. 统一ApplicationContext和Application使用的environment
3. ApplicationContext的后置处理
4. 执行Initializers
    4.1 DelegatingApplicationContextInitializer
    4.2 SharedMetadataReaderFactoryContextInitializer
    4.3 ContextIdApplicationContextInitializer
    4.4 ConfigurationWarningsApplicationContextInitializer
    4.5 ServerPortInfoApplicationContextInitializer
    4.6 ConditionEvaluationReportLoggingListener
5. 发布ApplicationContextInitializedEvent事件
6. 打印启动和profile日志
7. 手工注册单例Bean
8. 初始化BeanDefinitionLoader, 加载Application
9. 发布contextLoaded事件
    9.1 ConfigFileApplicationListener
    9.2 LoggingApplicationListener
    9.3 BackgroundPreinitializer
    9.4 DelegatingApplicationListener

1. 准备环境prepareContext()

准备应用上下文环境AnnotationConfigServletWebServerApplicationContext, 执行了以下8个步骤

  1. 统一ApplicationContext和Application使用的environment
  2. 后置处理ApplicationContext
  3. 执行Initializers
  4. 发布contextPrepared事件
  5. 打印启动和profile日志
  6. 注册单例bean
  7. 加载启动类
  8. 发布contextLoaded事件
public class SpringApplication {

    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);
            //...
    }
    

    /**
     * 准备应用上下文
     * @param context AnnotationConfigServletWebServerApplicationContext实例
     * @param environment SpringApplication中的StandardServletEnvironment实例
     * @param applicationArguments SpringApplication中的DefaultApplicationArguments实例
     * @param printedBanner 默认使用SpringApplicationBanner实例
     */
    private void prepareContext(ConfigurableApplicationContext context,
            ConfigurableEnvironment environment, SpringApplicationRunListeners listeners,
            ApplicationArguments applicationArguments, Banner printedBanner) {
        //设置context(上下文)环境
        //统一ApplicationContext和Application,使用Application的environment
        context.setEnvironment(environment);
        //ApplicationContext的后置处理
        postProcessApplicationContext(context);
        //执行Initializers
        applyInitializers(context);
        //发布contextPrepared事件
        listeners.contextPrepared(context);
        if (this.logStartupInfo) {
            //配置了info日志
            //打印启动和profile日志
            logStartupInfo(context.getParent() == null);
            logStartupProfileInfo(context);
        }
        //获取到DefaultListableBeanFactory实例
        ConfigurableListableBeanFactory beanFactory = context.getBeanFactory();
        //注册名为springApplicationArguments,值为applicationArguments的单例bean
        beanFactory.registerSingleton("springApplicationArguments", applicationArguments);
        //banner不为空,那么注册名为springBootBanner,值为printedBanner的单例bean
        if (printedBanner != null) {
            beanFactory.registerSingleton("springBootBanner", printedBanner);
        }
        if (beanFactory instanceof DefaultListableBeanFactory) {
            //allowBeanDefinitionOverriding默认为false
            ((DefaultListableBeanFactory) beanFactory)
                    .setAllowBeanDefinitionOverriding(this.allowBeanDefinitionOverriding);
        }
        // 获取sources列表,获取到我们的YanggxApplication.class
        Set<Object> sources = getAllSources();
        Assert.notEmpty(sources, "Sources must not be empty");
        //初始化bean加载器,并加载bean到应用上下文
        load(context, sources.toArray(new Object[0]));
        //发布contextLoaded事件
        listeners.contextLoaded(context);
    }
}

2. 统一ApplicationContext和Application使用的environment

配置ApplicationContext和Application的environment成员变量, 使用Application的environment, AnnotationConfigServletWebServerApplicationContext的bean定读取器reader和bean扫描器scanner都使用Application的environment

public class AnnotationConfigServletWebServerApplicationContext
        extends ServletWebServerApplicationContext implements AnnotationConfigRegistry {
    @Override
    public void setEnvironment(ConfigurableEnvironment environment) {
        //显式调用父类AbstractApplicationContext的setEnvironment方法
        super.setEnvironment(environment);
        //调用AnnotatedBeanDefinitionReader#setEnvironment()方法
        this.reader.setEnvironment(environment);
        
        //ClassPathBeanDefinitionScanner继承了ClassPathScanningCandidateComponentProvider,所以调用了父类setEnvironment方法
        this.scanner.setEnvironment(environment);
    }
}
显式调用父类AbstractApplicationContext的setEnvironment方法
public abstract class AbstractApplicationContext extends DefaultResourceLoader
        implements ConfigurableApplicationContext {
    
    //environment成员变量
    @Nullable
    private ConfigurableEnvironment environment;
    
    @Override
    public void setEnvironment(ConfigurableEnvironment environment) {
        this.environment = environment;
    }
}
调用AnnotatedBeanDefinitionReader#setEnvironment()方法
public class AnnotatedBeanDefinitionReader {
    public void setEnvironment(Environment environment) {
        //初始化conditionEvaluator
        this.conditionEvaluator = new ConditionEvaluator(this.registry, environment, null);
    }
}
调用ClassPathBeanDefinitionScanner的setEnvironment方法

ClassPathBeanDefinitionScanner继承了ClassPathScanningCandidateComponentProvider, 所以调用了父类setEnvironment方法

ublic class ClassPathScanningCandidateComponentProvider implements EnvironmentCapable, ResourceLoaderAware {
    @Nullable
    private Environment environment;

    public void setEnvironment(Environment environment) {
        Assert.notNull(environment, "Environment must not be null");
        this.environment = environment;
        //conditionEvaluator置为null
        this.conditionEvaluator = null;
    }
}

3. ApplicationContext的后置处理

执行了以下三步

  1. 设置ApplicationContext的beanNameGenerator
  2. 设置ApplicationContext的resourceLoader和classLoader
  3. 设置ApplicationContext的类型转换Service
protected void postProcessApplicationContext(ConfigurableApplicationContext context) {
        //没有设置beanNameGenerator,默认为null
        if (this.beanNameGenerator != null) {
            //如果beanNameGenerator不为空
            //那么注册一个名为internalConfigurationBeanNameGenerator
            //值为beanNameGenerator的单例bean
            context.getBeanFactory().registerSingleton(
                    AnnotationConfigUtils.CONFIGURATION_BEAN_NAME_GENERATOR,
                    this.beanNameGenerator);
        }
        //没有设置resourceLoader,默认为null
        if (this.resourceLoader != null) {
            //如果resourceLoader不为空
            if (context instanceof GenericApplicationContext) {
                //context是GenericApplicationContext子类
                //那么设置上下文context的resourceLoader
                ((GenericApplicationContext) context)
                        .setResourceLoader(this.resourceLoader);
            }
            if (context instanceof DefaultResourceLoader) {
                //如果当前上下文是DefaultResourceLoader的子类
                //那么设置上下文context的classLoader
                ((DefaultResourceLoader) context)
                        .setClassLoader(this.resourceLoader.getClassLoader());
            }
        }
        //this.addConversionService默认为true
        if (this.addConversionService) {
            //设置类型转换Service
            context.getBeanFactory().setConversionService(
                    ApplicationConversionService.getSharedInstance());
        }
    }

4. 执行Initializers

initializers在SpringApplication初始化期间获取到, 一共获取到6个初始化器:

  • DelegatingApplicationContextInitializer
  • SharedMetadataReaderFactoryContextInitializer
  • ContextIdApplicationContextInitializer
  • ConfigurationWarningsApplicationContextInitializer
  • ServerPortInfoApplicationContextInitializer
  • ConditionEvaluationReportLoggingListener
protected void applyInitializers(ConfigurableApplicationContext context) {
    for (ApplicationContextInitializer initializer : getInitializers()) {
        //断言判断initializer的类型是否符合条件
        Class<?> requiredType = GenericTypeResolver.resolveTypeArgument(
                initializer.getClass(), ApplicationContextInitializer.class);
        Assert.isInstanceOf(requiredType, context, "Unable to call initializer.");
        //执行各个initializer的初始化initialize方法
        initializer.initialize(context);
    }
}
4.1 DelegatingApplicationContextInitializer

获取环境中属性context.initializer.classesInitializer配置的ApplicationContextInitializer列表, 执行其initialize()方法, 由于我们没有配置属性context.initializer.classesInitializer, 所以不会执行任何操作

//代理初始化器
public class DelegatingApplicationContextInitializer implements
        ApplicationContextInitializer<ConfigurableApplicationContext>, Ordered {
        
    private static final String PROPERTY_NAME = "context.initializer.classes";
    
    @Override
    public void initialize(ConfigurableApplicationContext context) {
        ConfigurableEnvironment environment = context.getEnvironment();
        //获取environment中配置的context.initializer.classes属性
        //其值为各个initializer,用逗号分隔开
        List<Class<?>> initializerClasses = getInitializerClasses(environment);
        if (!initializerClasses.isEmpty()) {
            //获取到各个initializer,并执行其initialize()方法
            applyInitializerClasses(context, initializerClasses);
        }
    }
            
}
4.2 SharedMetadataReaderFactoryContextInitializer

添加了一个类型为CachingMetadataReaderFactoryPostProcessor的BeanFactoryPostProcessor, CachingMetadataReaderFactoryPostProcessor会做两件事情

  • 注册一个名称为internalCachingMetadataReaderFactory, 类型为SharedMetadataReaderFactoryBean的bean, 用于读取bean的元数据Metadata
  • 获取名称为internalConfigurationAnnotationProcessor, 类型为ConfigurationClassPostProcessor的bean定义, 为其添加name为metadataReaderFactory, value为internalCachingMetadataReaderFactory的internalCachingMetadataReaderFactory
class SharedMetadataReaderFactoryContextInitializer implements
        ApplicationContextInitializer<ConfigurableApplicationContext>, Ordered {

    public static final String BEAN_NAME = "org.springframework.boot.autoconfigure."
            + "internalCachingMetadataReaderFactory";

    @Override
    public void initialize(ConfigurableApplicationContext applicationContext) {
        //spring上下文容器添加一个CachingMetadataReaderFactoryPostProcessor
        applicationContext.addBeanFactoryPostProcessor(
                new CachingMetadataReaderFactoryPostProcessor());
    }
}
4.3 ContextIdApplicationContextInitializer

初始化容器ID, 获取属性spring.application.name配置的应用名称, 如果不存在的话, 默认使用application

//容器ID初始化器
public class ContextIdApplicationContextInitializer implements
        ApplicationContextInitializer<ConfigurableApplicationContext>, Ordered {
    @Override
    public void initialize(ConfigurableApplicationContext applicationContext) {
        //获取并设置容器ID
        ContextId contextId = getContextId(applicationContext);
        applicationContext.setId(contextId.getId());
        //容器beanFactory中注册一个名称为ContextId类名
        //值为contextId的bean
        applicationContext.getBeanFactory().registerSingleton(ContextId.class.getName(),
                contextId);
    }
    
    //获取ContextID
    private ContextId getContextId(ConfigurableApplicationContext applicationContext) {
        //父容器获取spring.application.name对应的bean
        ApplicationContext parent = applicationContext.getParent();
        if (parent != null && parent.containsBean(ContextId.class.getName())) {
            return parent.getBean(ContextId.class).createChildId();
        }
        //父容器获取不到,则生成一个contextId
        return new ContextId(getApplicationId(applicationContext.getEnvironment()));
    }
    
    //获取应用ID
    private String getApplicationId(ConfigurableEnvironment environment) {
        //获取属性:spring.application.name
        String name = environment.getProperty("spring.application.name");
        //如果为空,默认名application
        return StringUtils.hasText(name) ? name : "application";
    }

    //ContextId类
    class ContextId {
        //原子Long类
        private final AtomicLong children = new AtomicLong(0);

        private final String id;

        ContextId(String id) {
            this.id = id;
        }

        ContextId createChildId() {
            //线程安全递增
            return new ContextId(this.id + "-" + this.children.incrementAndGet());
        }

        String getId() {
            return this.id;
        }

    }
            
}
4.4 ConfigurationWarningsApplicationContextInitializer

配置告警初始化器, 用于检测注解了包org, org.springframework包内的类, 如果注解了,那么打印warn日志

public class ConfigurationWarningsApplicationContextInitializer
        implements ApplicationContextInitializer<ConfigurableApplicationContext> {

    @Override
    public void initialize(ConfigurableApplicationContext context) {
        //添加一个beanFactory后置处理器
        //ConfigurationWarningsPostProcessor的子类
        context.addBeanFactoryPostProcessor(
                new ConfigurationWarningsPostProcessor(getChecks()));
    }

    //返回ComponentScanPackageCheck实例
    protected Check[] getChecks() {
        return new Check[] { new ComponentScanPackageCheck() };
    }

    /**
     * 配置错误后置处理器
     */
    protected static final class ConfigurationWarningsPostProcessor
            implements PriorityOrdered, BeanDefinitionRegistryPostProcessor {

        private Check[] checks;

        @Override
        public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry)
                throws BeansException {
            //处理各个检查之后的警告
            for (Check check : this.checks) {
                //没有问题的话message为null
                String message = check.getWarning(registry);
                if (StringUtils.hasLength(message)) {
                    //有错误信息,打印告警信息
                    warn(message);
                }
            }

        }

        private void warn(String message) {
            if (logger.isWarnEnabled()) {
                //打印告警日志
                logger.warn(String.format("%n%n** WARNING ** : %s%n%n", message));
            }
        }
    }
    
    //Component注解扫描Check类
    protected static class ComponentScanPackageCheck implements Check {

        //有问题的包
        private static final Set<String> PROBLEM_PACKAGES;

        static {
            //将org和org.springframework包添加到PROBLEM_PACKAGES
            //也就是不允许配置这两个包内的类方法和属性
            Set<String> packages = new HashSet<>();
            packages.add("org.springframework");
            packages.add("org");
            PROBLEM_PACKAGES = Collections.unmodifiableSet(packages);
        }

        @Override
        public String getWarning(BeanDefinitionRegistry registry) {
            //获取被扫描的包
            Set<String> scannedPackages = getComponentScanningPackages(registry);
            //获取有问题的包
            List<String> problematicPackages = getProblematicPackages(scannedPackages);
            if (problematicPackages.isEmpty()) {
                //没有问题返回null
                return null;
            }
            //有问题返回的错误信息
            return "Your ApplicationContext is unlikely to "
                    + "start due to a @ComponentScan of "
                    + StringUtils.collectionToDelimitedString(problematicPackages, ", ")
                    + ".";
        }

        private boolean isProblematicPackage(String scannedPackage) {
            if (scannedPackage == null || scannedPackage.isEmpty()) {
                return true;
            }
            //如果包名为org或者org.springframework
            //那么返回true,否则返回false
            return PROBLEM_PACKAGES.contains(scannedPackage);
        }

        private String getDisplayName(String scannedPackage) {
            if (scannedPackage == null || scannedPackage.isEmpty()) {
                return "the default package";
            }
            return "'" + scannedPackage + "'";
        }
    }
}
4.5 ServerPortInfoApplicationContextInitializer

服务端口初始化器, 分别实现了ApplicationContextInitializer和ApplicationListener接口, 在applicationContext中添加了事件监听器this, 监听了WebServerInitializedEvent事件, 配置服务的端口号

public class ServerPortInfoApplicationContextInitializer
        implements ApplicationContextInitializer<ConfigurableApplicationContext>,
        ApplicationListener<WebServerInitializedEvent> {

    @Override
    public void initialize(ConfigurableApplicationContext applicationContext) {
        //把this添加到Application的listener中
        applicationContext.addApplicationListener(this);
    }
    
    //监听处理WebServerInitializedEvent事件
    @Override
    public void onApplicationEvent(WebServerInitializedEvent event) {
        //获取environment中配置的server.ports
        String propertyName = "local." + getName(event.getApplicationContext()) + ".port";
        setPortProperty(event.getApplicationContext(), propertyName,
                event.getWebServer().getPort());
    }
}
4.6 ConditionEvaluationReportLoggingListener

条件评估日志监听器, 主要作用是给applicationContext添加了一个ConditionEvaluationReportListener监听器, ConditionEvaluationReportListener监听了ContextRefreshedEvent和ApplicationFailedEvent事件, 打印相应日志

public class ConditionEvaluationReportLoggingListener
        implements ApplicationContextInitializer<ConfigurableApplicationContext> {
    @Override
    public void initialize(ConfigurableApplicationContext applicationContext) {
        this.applicationContext = applicationContext;
        //applicationContext中添加一个ConditionEvaluationReportListener
        applicationContext
                .addApplicationListener(new ConditionEvaluationReportListener());
        if (applicationContext instanceof GenericApplicationContext) {
            //注册一个ConditionEvaluationReport bean
            this.report = ConditionEvaluationReport
                    .get(this.applicationContext.getBeanFactory());
        }
    }
    
    //监听到ApplicationEvent
    protected void onApplicationEvent(ApplicationEvent event) {
        ConfigurableApplicationContext initializerApplicationContext = this.applicationContext;
        if (event instanceof ContextRefreshedEvent) {
            //ContextRefreshed事件
            if (((ApplicationContextEvent) event)
                    .getApplicationContext() == initializerApplicationContext) {
                logAutoConfigurationReport();
            }
        }
        else if (event instanceof ApplicationFailedEvent
                && ((ApplicationFailedEvent) event)
                        .getApplicationContext() == initializerApplicationContext) {
            //ApplicationFailedEvent事件
            logAutoConfigurationReport(true);
        }
    }
}

//用于记录Condition注解的评估情况
public final class ConditionEvaluationReport {

    //bean名称为autoConfigurationReport
    //类型为ConditionEvaluationReport
    private static final String BEAN_NAME = "autoConfigurationReport";
    
    //从beanFactory中获取ConditionEvaluationReport实例
    public static ConditionEvaluationReport get(
            ConfigurableListableBeanFactory beanFactory) {
        synchronized (beanFactory) {
            ConditionEvaluationReport report;
            if (beanFactory.containsSingleton(BEAN_NAME)) {
                //如果bean已经被注册,立即返回
                report = beanFactory.getBean(BEAN_NAME, ConditionEvaluationReport.class);
            }
            else {
                //否则注册bean
                report = new ConditionEvaluationReport();
                beanFactory.registerSingleton(BEAN_NAME, report);
            }
            locateParent(beanFactory.getParentBeanFactory(), report);
            return report;
        }
    }
}

5. 发布ApplicationContextInitializedEvent事件

Application容器初始化完成事件, 对该事件感兴趣的监听器有

  1. BackgroundPreinitializer
  2. DelegatingApplicationListener
BackgroundPreinitializer

扩展点, 后台进程初始化器, 用于多线程执行后台耗时任务, 在这里不处理ApplicationContextInitializedEvent事件

DelegatingApplicationListener

扩展点, 代理监听器, 继续分发事件, 不处理ApplicationContextInitializedEvent事件

6. 打印启动和profile日志

//logStartupInfo默认为true
if (this.logStartupInfo) {
        //打印项目启动信息
        // Starting YanggxApplication on pcname with PID 12372 (E:\java\spring\target\classes started by username in E:\java\spring)
        logStartupInfo(context.getParent() == null);
    
        //打印profile
        //No active profile set, falling back to default profiles: default
        logStartupProfileInfo(context);
    }

7. 注册单例Bean

注册了两个单例Bean

  • 命令行参数bean, 名称为springApplicationArguments, 值为applicationArgument
  • banner bean, 名称为springBootBanner, 值为printedBanner
//注册命令行参数bean
beanFactory.registerSingleton("springApplicationArguments", applicationArguments);
if (printedBanner != null) {
    //banner bean
    beanFactory.registerSingleton("springBootBanner", printedBanner);
}
7.1 手工注册单例Bean流程

调用DefaultListableBeanFactory#registerSingleton方法, 显示调用父类DefaultSingletonBeanRegistry#registerSingleton方法

DefaultListableBeanFactory 手工注册单例Bean

手工注册单例Bean, 不同于扫描bean定义, 然后注册单例bean, 手工注册的单例Bean, 没有维护到beanDefinitionMap中, 而是将beanName维护到manualSingletonNames中

public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFactory
        implements ConfigurableListableBeanFactory, BeanDefinitionRegistry, Serializable {

    //注册单例bean
    public void registerSingleton(String beanName, Object singletonObject) throws IllegalStateException {
        super.registerSingleton(beanName, singletonObject);

        //判断bean的创建过程是否已经开始了
        //调用抽象父类AbstractBeanFactory#hasBeanCreationStarted()方法
        //判断AbstractBeanFactory成员变量alreadyCreated Set不为空
        if (hasBeanCreationStarted()) {
            //bean创建过程已经开始了
            //锁住成员变量beanDefinitionMap
            synchronized (this.beanDefinitionMap) {
                if (!this.beanDefinitionMap.containsKey(beanName)) {
                    //如果bean定义Map,  beanDefinitionMap已经包含了bean
                    //维护到手工单例bean名称manualSingletonNames中
                    Set<String> updatedSingletons = new LinkedHashSet<>(this.manualSingletonNames.size() + 1);
                    updatedSingletons.addAll(this.manualSingletonNames);
                    updatedSingletons.add(beanName);
                    this.manualSingletonNames = updatedSingletons;
                }
            }
        }
        else {
            // bean还没有注册过, 仍处于启动注册阶段
            if (!this.beanDefinitionMap.containsKey(beanName)) {
                //如果beanDefinitionMap不包含beanName
                //那么添加到manualSingletonNames
                this.manualSingletonNames.add(beanName);
            }
        }

        //清空allBeanNamesByType和singletonBeanNamesByType
        clearByTypeCache();
    }
}
DefaultSingletonBeanRegistry手工注册单例Bean

将beanName添加到registeredSingletons中, beanName和对应的对象保存singletonObjects中, 并删除beanName对应的beanFactory, earlySingleton

//默认单例bean注册器
public class DefaultSingletonBeanRegistry extends SimpleAliasRegistry implements SingletonBeanRegistry {
    
    //缓存单例bean, key为bean名称,value为bean实例
    private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256);

    //缓存beanFactory, key为bean名称, value为beanFactory
    private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap<>(16);

    //早期单例缓存, key为bean名称, value为bean实例
    //为了解决循环依赖而引入的
    private final Map<String, Object> earlySingletonObjects = new HashMap<>(16);

    //单例bean名称set
    private final Set<String> registeredSingletons = new LinkedHashSet<>(256);

    //正在创建的单例bean名称set
    private final Set<String> singletonsCurrentlyInCreation =
            Collections.newSetFromMap(new ConcurrentHashMap<>(16));


    //手工注册单例bean
    @Override
    public void registerSingleton(String beanName, Object singletonObject) throws IllegalStateException {
        //判断名称和值不可以为空
        Assert.notNull(beanName, "Bean name must not be null");
        Assert.notNull(singletonObject, "Singleton object must not be null");
        synchronized (this.singletonObjects) {
            //判断bean是否为空
            Object oldObject = this.singletonObjects.get(beanName);
            if (oldObject != null) {
                //不为空抛异常
                throw new IllegalStateException("Could not register object [" + singletonObject +
                        "] under bean name '" + beanName + "': there is already object [" + oldObject + "] bound");
            }
            //添加一个单例bean
            addSingleton(beanName, singletonObject);
        }
    }
    
    //添加一个单例bean
    protected void addSingleton(String beanName, Object singletonObject) {
        synchronized (this.singletonObjects) {
            //保存到singletonObjects的map中
            this.singletonObjects.put(beanName, singletonObject);
            this.singletonFactories.remove(beanName);
            this.earlySingletonObjects.remove(beanName);
            //添加beanName
            this.registeredSingletons.add(beanName);
        }
    }
}

8. 初始化BeanDefinitionLoader, 加载Application

首先生成一个BeanDefinitionLoader, 用于加载SpringApplication的成员变量sources, 当前sources列表中只有YanggxApplication.class一个对象

protected void load(ApplicationContext context, Object[] sources) {
    if (logger.isDebugEnabled()) {
        logger.debug(
                "Loading source " + StringUtils.arrayToCommaDelimitedString(sources));
    }
    //实例化BeanDefinitionLoader
    BeanDefinitionLoader loader = createBeanDefinitionLoader(
            getBeanDefinitionRegistry(context), sources);
    //this.beanNameGenerator为null
    if (this.beanNameGenerator != null) {
        loader.setBeanNameGenerator(this.beanNameGenerator);
    }
    //this.resourceLoader为null
    if (this.resourceLoader != null) {
        loader.setResourceLoader(this.resourceLoader);
    }
    //this.environment为null
    if (this.environment != null) {
        loader.setEnvironment(this.environment);
    }
    //调用load()方法,加载各个sources
    loader.load();
}
8.1 BeanDefinitionLoader

加载SpringApplication维护的sources列表资源, 可以加载类, XML, groovy等资源, 由于我们传入的sources中只有一个YanggxApplication.class, 所以调用的是load(Class<?> source)方法, 最后调用的是AnnotatedBeanDefinitionReader#register()方法, 注册了一个Bean定义

class BeanDefinitionLoader {

    //启动类列表
    private final Object[] sources;

    //注解Bean定义读取器
    private final AnnotatedBeanDefinitionReader annotatedReader;

    //XML Bean定义读取器
    private final XmlBeanDefinitionReader xmlReader;

    //groovy Bean定义读取器
    private BeanDefinitionReader groovyReader;

    //Bean定义扫描器
    private final ClassPathBeanDefinitionScanner scanner;

    //资源加载器
    private ResourceLoader resourceLoader;

    /**
     * 构造函数
     */
    BeanDefinitionLoader(BeanDefinitionRegistry registry, Object... sources) {
        Assert.notNull(registry, "Registry must not be null");
        Assert.notEmpty(sources, "Sources must not be empty");
        //传入的sources, 目前只有YanggxApplication.class
        this.sources = sources;
        this.annotatedReader = new AnnotatedBeanDefinitionReader(registry);
        this.xmlReader = new XmlBeanDefinitionReader(registry);
        if (isGroovyPresent()) {
            //使用了groovy
            this.groovyReader = new GroovyBeanDefinitionReader(registry);
        }
        this.scanner = new ClassPathBeanDefinitionScanner(registry);
        //排除sources扫描
        this.scanner.addExcludeFilter(new ClassExcludeFilter(sources));
    }

    /**
     * 加载sources
     */
    public int load() {
        int count = 0;
        for (Object source : this.sources) {
            count += load(source);
        }
        return count;
    }
    
    //加载Object资源
    private int load(Object source) {
        Assert.notNull(source, "Source must not be null");
        if (source instanceof Class<?>) {
            //加载类资源
            return load((Class<?>) source);
        }
        if (source instanceof Resource) {
            //加载Resource资源
            return load((Resource) source);
        }
        if (source instanceof Package) {
            //加载Package资源
            return load((Package) source);
        }
        if (source instanceof CharSequence) {
            //加载字符串资源
            return load((CharSequence) source);
        }
        throw new IllegalArgumentException("Invalid source type " + source.getClass());
    }

    //加载类资源
    private int load(Class<?> source) {
        if (isGroovyPresent()
                && GroovyBeanDefinitionSource.class.isAssignableFrom(source)) {
            // 使用了groovy,加载groovy资源
            GroovyBeanDefinitionSource loader = BeanUtils.instantiateClass(source,
                    GroovyBeanDefinitionSource.class);
            load(loader);
        }
        //如果是@Component注解
        if (isComponent(source)) {
            this.annotatedReader.register(source);
            return 1;
        }
        return 0;
    }

    //加载groovy资源
    private int load(GroovyBeanDefinitionSource source) {
        int before = this.xmlReader.getRegistry().getBeanDefinitionCount();
        ((GroovyBeanDefinitionReader) this.groovyReader).beans(source.getBeans());
        int after = this.xmlReader.getRegistry().getBeanDefinitionCount();
        return after - before;
    }
    //加载resource资源
    private int load(Resource source) {
        if (source.getFilename().endsWith(".groovy")) {
            //使用了groovy
            if (this.groovyReader == null) {
                throw new BeanDefinitionStoreException(
                        "Cannot load Groovy beans without Groovy on classpath");
            }
            return this.groovyReader.loadBeanDefinitions(source);
        }
        //加载xml资源
        return this.xmlReader.loadBeanDefinitions(source);
    }
    
    //加载package资源
    private int load(Package source) {
        //scanner扫描
        return this.scanner.scan(source.getName());
    }

    //load xml资源
    private int load(CharSequence source) {
        String resolvedSource = this.xmlReader.getEnvironment()
                .resolvePlaceholders(source.toString());
        try {
            //先尝试加载类资源
            return load(ClassUtils.forName(resolvedSource, null));
        }
        catch (IllegalArgumentException | ClassNotFoundException ex) {
        }
        // 不成功的话,加载resource资源
        Resource[] resources = findResources(resolvedSource);
        int loadCount = 0;
        boolean atLeastOneResourceExists = false;
        for (Resource resource : resources) {
            if (isLoadCandidate(resource)) {
                atLeastOneResourceExists = true;
                loadCount += load(resource);
            }
        }
        if (atLeastOneResourceExists) {
            return loadCount;
        }
        // 不成功的话,加载package资源
        Package packageResource = findPackage(resolvedSource);
        if (packageResource != null) {
            return load(packageResource);
        }
        //还不成功的话,就抛异常
        throw new IllegalArgumentException("Invalid source '" + resolvedSource + "'");
    }
}
AnnotatedBeanDefinitionReader注册Bean定义
public class AnnotatedBeanDefinitionReader {

    //Class列表注册Bean定义
    public void register(Class<?>... annotatedClasses) {
        for (Class<?> annotatedClass : annotatedClasses) {
            //单个Bean注册
            registerBean(annotatedClass);
        }
    }
    
    //单个Class注册bean
    public void registerBean(Class<?> annotatedClass) {
        doRegisterBean(annotatedClass, null, null, null);
    }

    //注册Bean定义
    <T> void doRegisterBean(Class<T> annotatedClass, @Nullable Supplier<T> instanceSupplier, @Nullable String name,
            @Nullable Class<? extends Annotation>[] qualifiers, BeanDefinitionCustomizer... definitionCustomizers) {
        //生成注解BeanDefinition
        AnnotatedGenericBeanDefinition abd = new AnnotatedGenericBeanDefinition(annotatedClass);
        
        //判断是否符合@Conditional注解的条件
        //不满足的话, 就不注册Bean
        if (this.conditionEvaluator.shouldSkip(abd.getMetadata())) {
            return;
        }
        //设置instanceSupplier, //AbstractAutowireCapableBeanFactory#createBeanInstance中调用了instanceSupplier.get()生成bean实例
        abd.setInstanceSupplier(instanceSupplier);
        //Scope元空间
        ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(abd);
        abd.setScope(scopeMetadata.getScopeName());
        //生成Bean名称
        String beanName = (name != null ? name : this.beanNameGenerator.generateBeanName(abd, this.registry));

        //处理Lazy, Primary, DependsOn, Role, Description注解
        AnnotationConfigUtils.processCommonDefinitionAnnotations(abd);
        if (qualifiers != null) {
            for (Class<? extends Annotation> qualifier : qualifiers) {
                if (Primary.class == qualifier) {
                    abd.setPrimary(true);
                }
                else if (Lazy.class == qualifier) {
                    abd.setLazyInit(true);
                }
                else {
                    abd.addQualifier(new AutowireCandidateQualifier(qualifier));
                }
            }
        }
        for (BeanDefinitionCustomizer customizer : definitionCustomizers) {
            //beanDefinition定制器
            customizer.customize(abd);
        }

        //bean定义容器
        BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(abd, beanName);
        
        //Scope代理模式处理
        //ScopedProxyMode.DEFAULT和NO不需要代理处理
        //INTERFACES使用JDK动态代理
        //TARGET_CLASS使用CGLIB动态代理
        definitionHolder = AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);
        
        //注册Bean定义
        BeanDefinitionReaderUtils.registerBeanDefinition(definitionHolder, this.registry);
    }
}

9. 发布contextLoaded事件

调用listeners.contextLoaded(context), 发布了一个ApplicationPreparedEvent事件, 对ApplicationPreparedEvent事件感兴趣的监听器有:

  1. ConfigFileApplicationListener
  2. LoggingApplicationListener
  3. BackgroundPreinitializer
  4. DelegatingApplicationListener
9.1 ConfigFileApplicationListener

配置文件监听器

public class ConfigFileApplicationListener
        implements EnvironmentPostProcessor, SmartApplicationListener, Ordered {
    //事件处理
    @Override
    public void onApplicationEvent(ApplicationEvent event) {
        if (event instanceof ApplicationEnvironmentPreparedEvent) {
            onApplicationEnvironmentPreparedEvent(
                    (ApplicationEnvironmentPreparedEvent) event);
        }
        if (event instanceof ApplicationPreparedEvent) {
            //处理ApplicationPreparedEvent
            onApplicationPreparedEvent(event);
        }
    }
    
    //处理ApplicationPreparedEvent
    private void onApplicationPreparedEvent(ApplicationEvent event) {
        this.logger.switchTo(ConfigFileApplicationListener.class);
        addPostProcessors(((ApplicationPreparedEvent) event).getApplicationContext());
    }
    
    //applicationContext中添加一个PropertySourceOrderingPostProcessor
    protected void addPostProcessors(ConfigurableApplicationContext context) {
        //用于重排序PropertySourceOrderingPostProcessor
        context.addBeanFactoryPostProcessor(
                new PropertySourceOrderingPostProcessor(context));
    }
}
9.2 LoggingApplicationListener

日志监听器

public class LoggingApplicationListener implements GenericApplicationListener {

    private void onApplicationPreparedEvent(ApplicationPreparedEvent event) {
        ConfigurableListableBeanFactory beanFactory = event.getApplicationContext()
                .getBeanFactory();
        //注册日志单例bean
        if (!beanFactory.containsBean(LOGGING_SYSTEM_BEAN_NAME)) {
            beanFactory.registerSingleton(LOGGING_SYSTEM_BEAN_NAME, this.loggingSystem);
        }
    }
    
}
9.3 BackgroundPreinitializer

后台预初始化器, 当前不做任务处理, 方便以后扩展

9.4 DelegatingApplicationListener

代理监听器, 不做任何处理, 方便以后扩展

总结

这一步的主要作用是为下面刷新applicationContext做准备

  • 统一了ApplicationContext和Application的environment
  • 设置ApplicationContext的beanNameGenerator,resouceLoader和classLoader, 并设置beanFactory的类型转换Service
  • 执行Initializer
  • 发布ApplicationContextInitializedEvent
  • 打印启动日志和profile日志
  • 手工注册命令行和banner两个单例Bean
  • 初始化BeanDefinitionLoader, 加载启动类sources
  • 发布contextLoaded事件

下一篇

我们将会在下一篇refreshContext()刷新应用上下文, 研究springboot如何扫描加载bean, 如何建立webserver容器

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 199,393评论 5 467
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 83,790评论 2 376
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 146,391评论 0 330
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 53,703评论 1 270
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 62,613评论 5 359
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,003评论 1 275
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,507评论 3 390
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,158评论 0 254
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,300评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,256评论 2 317
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,274评论 1 328
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,984评论 3 316
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,569评论 3 303
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,662评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,899评论 1 255
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,268评论 2 345
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 41,840评论 2 339

推荐阅读更多精彩内容

  • Spring容器高层视图 Spring 启动时读取应用程序提供的Bean配置信息,并在Spring容器中生成一份相...
    Theriseof阅读 2,791评论 1 24
  • 1.Spring整体架构 1)核心容器(Core Container) Core模块,主要包含了Spring框架基...
    Sponge1128阅读 1,042评论 0 1
  • 参考W3C Spring教程 Spring致力于J2EE应用的各种解决方案,而不仅仅专注于某一层解决方案。可以说S...
    王侦阅读 1,151评论 0 6
  • 什么是Spring框架?  Spring框架是个轻量级的Java EE框架。所谓轻量级,是指不依赖于容器就能运行的...
    小任务大梦想阅读 354评论 1 0
  • 认识顾音的时候,她是夜猫子,对于她来说凌晨一点才是睡觉时间。 后来慢慢熟悉以后,知道顾音有一个男朋友,她给我看过男...
    小益读书阅读 220评论 0 0