美文网首页spring全家桶
Spring-IOC & Spring-Boot2启动

Spring-IOC & Spring-Boot2启动

作者: suxin1932 | 来源:发表于2019-11-13 16:55 被阅读0次
    #概述
    1.springboot启动过程
    2.spring容器refresh过程
    3.BeanDefinitio注册过程
    4.Bean实例化, 初始化过程
    5.Bean的循环依赖问题
    6.BeanFactory VS ApplicationContext VS FactoryBean
    

    2.SpringBoot2.0核心原理(spring-boot-2.1.4, 即spring5.1.6)

    IOC & DI基本流程图

    Spring 启动时读取应用程序提供的Bean配置信息,
    并在Spring容器中生成一份相应的Bean配置注册表,
    然后根据这张注册表实例化Bean,装配好Bean之间的依赖关系,为上层应用提供准备就绪的运行环境。
    
    IOC过程.png

    2.1 Bean创建大致流程

    XML方式创建bean

    Bean创建过程--XML方式.png
    // 1.ResourceLoader
    从存储介质中加载Spring配置信息,并使用Resource表示这个配置文件的资源.
    
    // 2.BeanDefinitionReader
    读取Resource所指向的配置文件资源,然后解析配置文件。
    配置文件中每一个<bean>解析成一个BeanDefinition对象,并保存到BeanDefinitionRegistry中;
    
    // 3.ClassPathBeanDefinitionScanner -- BeanFactoryPostProcessor
    容器扫描BeanDefinitionRegistry中的BeanDefinition,
    使用Java的反射机制自动识别出BeanFactoryPostProcessor实现类的Bean,
    然后调用BeanFactoryPostProcessor实现类对BeanDefinitionRegistry中的BeanDefinition进行加工处理。
    主要完成以下两项工作:
    1) 对使用到占位符的<bean>元素标签进行解析,得到最终的配置值,
    这意味对一些半成品式的BeanDefinition对象进行加工处理并得到成品的BeanDefinition对象;
    2) 对BeanDefinitionRegistry中的BeanDefinition进行扫描,
    通过Java反射机制找出所有实现java.beans.PropertyEditor接口的Bean, 
    并自动将它们注册到Spring容器的PropertyEditorRegistry注册表中.
    
    // 4.InstantiationStrategy
    Spring容器从BeanDefinitionRegistry中取出加工后的BeanDefinition,
    并调用InstantiationStrategy着手进行Bean实例化的工作.
    
    // 5.BeanWrapper
    在实例化Bean时,Spring容器使用BeanWrapper对Bean进行封装,
    BeanWrapper提供了很多以Java反射机制操作Bean的方法,
    它将结合该Bean的BeanDefinition以及容器中PropertyEditor,完成Bean属性的设置工作.
    
    // 6.BeanPostProcessor
    利用容器中注册的Bean后处理器(实现BeanPostProcessor接口的Bean)
    对已经完成属性设置工作的Bean进行后续加工,直接装配出一个准备就绪的Bean。
    
    //////////////////////// 总结 //////////////////////// 
    整个过程中涉及到的组件按其所承担的角色可以划分为:
    1)物料组件:
    Resource、BeanDefinition、PropertyEditor以及最终的Bean等,
    它们是加工流程中被加工、被消费的组件,就像流水线上被加工的物料;
    2)加工设备组件:
    ResourceLoader、BeanDefinitionReader、BeanFactoryPostProcessor、InstantiationStrategy以及BeanWrapper等组件
    像是流水线上不同环节的加工设备,对物料组件进行加工处理。
    

    2.1.1 BeanDefinition & BeanDefinitionBuilder

    在Java中,一切皆对象。在JDK中使用java.lang.Class来描述类这个对象。
    
    在Spring中,存在bean这样一个概念,那Spring又是怎么抽象bean这个概念,用什么类来描述bean这个对象呢?
    
    Spring使用BeanDefinition来描述bean。
    

    BeanDefinition类图

    BeanDefinition类图.png

    BeanDefinition类图补充

    BeanDefinition类图补充.png

    BeanDefinition方法&属性

    BeanDefinition方法&属性.png

    BeanDefinitionBuilder构建BeanDeifinition

    BeanDefinitionBuilder构建BeanDeifinition.png

    2.1.2 父接口AttributeAccessor & BeanMetadataElement

    #AttributeAccessor 
    提供了一些访问bean属性的方法
    #BeanMetadataElement
    只有一个方法, 用来获取元数据元素的配置源对象
    

    AttributeAccessor

    AttributeAccessor.png

    BeanMetadataElement

    BeanMetadataElement.png

    2.1.3 BeanDefinitionReader

    各种BeanDefinitionReader类图

    各种BeanDefinitionReader类图.png

    AnnotatedBeanDefinitionReader

    AnnotatedBeanDefinitionReader.png

    ConfigurationClassBeanDefinitionReader

    ConfigurationClassBeanDefinitionReader.png

    XmlBeanDefinitionReader

    XmlBeanDefinitionReader.png

    2.1.4 BeanDefinitionReaderUtils & BeanDefinitionHolder & BeanDefinitionLoader & ClassPathBeanDefinitionScanner

    BeanDefinitionLoader
    SpringBoot提供的一个新类, 用来加载BeanDefinition

    BeanDefinitionLoader.png

    BeanDefinitionReaderUtils

    BeanDefinitionReaderUtils.png

    BeanDefinitionHolder

    BeanDefinitionHolder.png

    ClassPathBeanDefinitionScanner

    ClassPathBeanDefinitionScanner.png

    2.1.5 BeanDefinitionRegistry

    BeanDefinitionRegistry

    这里的注册, 实则是将BeanDefinition放置到DefaultListableBeanFactory的beanDefinitionMap中, 缓存起来.
    注意: 
    不是缓存Bean, Bean缓存在其父类DefaultSingletonBeanRegistry的一些成员变量.
    
    BeanDefinitionRegistry.png

    2.1.6 ApplicationContext

    2.1.7 BeanFactory VS ApplicationContext VS FactoryBean

    2.1.7.1 FactoryBean

    FactoryBean-1.png FactoryBean-2.png

    2.1.7.2 BeanFactory

    BeanFactory是Spring容器的基础接口,提供了基础的容器访问能力。
    BeanFactory提供懒加载方式,只有通过getBean方法调用获取Bean才会进行实例化。
    常用的是加载XMLBeanFactory (已废弃).
    
    BeanFactory类图.png

    2.1.7.3 ApplicationContext

    ApplicationContext继承自BeanFactory接口,ApplicationContext包含了BeanFactory中所有的功能:
    1.国际化
    实现了MessageResource接口,因而具有消息处理的能力(i18N)
    
    2.强大的事件机制(Event)  
    基本上牵涉到事件(Event)方面的设计,就离不开观察者模式,
    ApplicationContext的事件机制主要通过ApplicationEvent和ApplicationListener这两个接口来提供的,
    和java swing中的事件机制一样。即当ApplicationContext中发布一个事件的时,
    所有扩展了ApplicationListener的Bean都将会接受到这个事件,并进行相应的处理。
    
    3.底层资源的访问  
    ApplicationContext扩展了ResourceLoader(资源加载器)接口,
    从而可以用来加载多个Resource,而BeanFactory没有扩展ResourceLoader.
    
    4.对Web应用的支持  
    与BeanFactory通常以编程的方式被创建不同的是,ApplicationContext能以声明的方式创建,如使用ContextLoader。
    当然你也可以使用ApplicationContext的实现之一来以编程的方式创建ApplicationContext实例 。
    
    5.延迟加载
    1) BeanFactroy采用的是延迟加载形式来注入Bean的,即只有在使用到某个Bean时(调用getBean()),
    才对该Bean进行加载实例化,这样,我们就不能发现一些存在的spring的配置问题。
    而ApplicationContext则相反,它是在容器启动时,一次性创建了所有的Bean。
    这样,在容器启动时,我们就可以发现Spring中存在的配置错误。
    2) BeanFactory和ApplicationContext都支持BeanPostProcessor、BeanFactoryPostProcessor的使用,
    但两者之间的区别是:BeanFactory需要手动注册,而ApplicationContext则是自动注册.
    

    summary

    ApplicationContext继承了BeanFactory,
    BeanFactory是Spring中比较原始的Factory,它不支持AOP、Web等Spring插件,
    ApplicationContext不仅包含了BeanFactory的所有功能,还支持Spring的各种插件,
    还以一种面向框架的方式工作以及对上下文进行分层和实现继承。
    
    BeanFactory是Spring框架的基础设施,面向Spring本身;
    ApplicationContext面向使用Spring的开发者,相比BeanFactory提供了更多面向实际应用的功能,
    几乎所有场合都可以直接使用ApplicationContext而不是底层的BeanFactory.
    
    ApplicationContext类图.png BeanFactory & ApplicationContext.png

    https://www.jianshu.com/p/2808f7c4a24f (beanfactory与applicationcontext)

    2.1.8 BeanFactoryPostProcessor & BeanDefinitionRegistryPostProcessor & PostProcessorRegistrationDelegate

    #BeanFactoryPostProcessor
    我们可以通过实现BeanFactoryPostProcessor接口,获取BeanFactory,
    操作BeanFactory对象,修改BeanDefinition,但不要去实例化bean。
    
    #BeanDefinitionRegistryPostProcessor
    是BeanFactoryPostProcessor的子类,在父类的基础上,增加了新的方法,
    允许我们获取到BeanDefinitionRegistry,从而编码动态修改BeanDefinition。
    例如往BeanDefinition中添加一个新的BeanDefinition。
    
    这两个接口是在AbstractApplicationContext#refresh方法中执行到
    invokeBeanFactoryPostProcessors(beanFactory)
    
    #典型应用:ConfigurationClassPostProcessor
    ConfigurationClassPostProcessor#postProcessBeanFactory:
    主要负责对Full Configuration 配置进行增强,拦截@Bean方法来确保增强执行@Bean方法的语义。
    ConfigurationClassPostProcessor#postProcessBeanDefinitionRegistry:
    负责扫描我们的程序,根据程序的中Bean创建BeanDefinition,并注册到容器中。
    

    BeanDefinitionRegistryPostProcessor手动注册BeanDefinition

    BeanDefinitionRegistryPostProcessor手动注册BeanDefinition.png

    PostProcessorRegistrationDelegate

    PostProcessorRegistrationDelegate.png

    https://blog.csdn.net/ztchun/article/details/90814135

    2.1.9 DefaultSingletonBeanRegistry

    /**
     * 共享bean实例的通用注册表,实现了SingletonBeanRegistry. 
     * 允许注册表中注册的单例应该被所有调用者共享,通过bean名称获得。
     * 
     * 还支持登记的DisposableBean实例,(这可能会或不能正确的注册单例),关闭注册表时destroyed.
     * 可以注册bean之间的依赖关系,执行适当的关闭顺序。
     * 
     * 这个类主要用作基类的BeanFactory实现, 提供基本的管理
     * singleton bean 实例功能, 提供一次性bean的注册功能。
     * 
     * 三个主要的存储器(map) :
     * singletonObject
     * singletonFactory
     * earlySingletonObject
     * 当注册一个 singleton object 的时候,会在 singletonObject 的存储器中加入此 object,而在其他的两个存储器中移除。
     * 当然,这样的行为是可以在子类中去复写override的。
     * 
     * 在 getSingleton的时候,spring的默认实现是: 
     * 先从 singleton object 的存储器中去寻找,
     * 如果找不到,再从 early singleton object 存储器中寻找,
     * 再找不到,那就在寻找对应的 singleton factory,造出所需的 singleton object,然后返回。
     */
    public class DefaultSingletonBeanRegistry extends SimpleAliasRegistry implements SingletonBeanRegistry {
     
        //内部标记为一个空的单例对象: 并发 Maps( 不支持空值 )作为标志值。
        protected static final Object NULL_OBJECT = new Object();
     
        // 日记用来记录子类
        protected final Log logger = LogFactory.getLog(getClass());
     
        //是存放singleton对象的缓存
        private final Map<String, Object> singletonObjects = new ConcurrentHashMap<String, Object>();
     
        // 是存放制造singleton的工厂对象的缓存
        private final Map<String, ObjectFactory> singletonFactories = new HashMap<String, ObjectFactory>();
     
        //是存放singletonFactory 制造出来的 singleton 的缓存
        private final Map<String, Object> earlySingletonObjects = new HashMap<String, Object>();
    
        //就是单例注册表
        private final Set<String> registeredSingletons = new LinkedHashSet<String>(16);
     
        //目前正在创建中的单例bean的名称的集合
        private final Set<String> singletonsCurrentlyInCreation = Collections.synchronizedSet(new HashSet<String>());
     
        //存放异常出现的相关的原因的集合
        private Set<Exception> suppressedExceptions;
     
        //标志,指示我们目前是否在销毁单例中
        private boolean singletonsCurrentlyInDestruction = false;
     
        //存放一次性bean的缓存
        private final Map<String, Object> disposableBeans = new LinkedHashMap<String, Object>();
     
        //外部bean与被包含在外部bean的所有内部bean集合包含关系的缓存
        private final Map<String, Set<String>> containedBeanMap = new ConcurrentHashMap<String, Set<String>>();
     
        //指定bean与依赖指定bean的所有bean的依赖关系的缓存
        private final Map<String, Set<String>> dependentBeanMap = new ConcurrentHashMap<String, Set<String>>();
     
        //指定bean与创建这个bean所需要依赖的所有bean的依赖关系的缓存
        private final Map<String, Set<String>> dependenciesForBeanMap = new ConcurrentHashMap<String, Set<String>>();
          
        ////// 此处省略部分方法, 详见下图 ////// 
    }
    
    DefaultSingletonBeanRegistry.png

    2.1.10 bean的初始化

    https://blog.csdn.net/qwe6112071/article/details/85224582

    3.SpringBoot2.0启动过程

    3.1SpringBoot2.0核心启动流程

    SpringBoot2.0大致启动流程.png

    3.1.1创建SpringApplication

    step1-创建SpringApplication.png step1-创建SpringApplication时SPI读取jar包下文件.png

    3.1.2运行SpringApplication

    step2-运行SpringApplication.png

    3.1.3Spring容器的refresh过程 (tomcat容器在这里启动)

    #对应于3.1.2流程的step11, refresh流程为:
    
    public void refresh() throws BeansException, IllegalStateException {
        synchronized (this.startupShutdownMonitor) {
            // 1. 初始化 refresh 的上下文环境
            prepareRefresh();
            // 2. 初始化 BeanFactory,加载并解析配置
            ConfigurableListableBeanFactory beanFactory = this.obtainFreshBeanFactory();
            /* ---至此,完成了简单容器 DefaultListableBeanFactory 的所有功能,下面开始对简单容器进行增强--- */
            // 3. 对 BeanFactory 进行功能增强, 
            // 如 context's ClassLoader and post-processors
            prepareBeanFactory(beanFactory);
            try {
                // 4. 后置处理 beanFactory,交由子类实现
                postProcessBeanFactory(beanFactory);
                // 5. 调用已注册的 BeanFactoryPostProcessor
                invokeBeanFactoryPostProcessors(beanFactory);
                // 6. 注册 BeanPostProcessor,仅仅是注册,调用在getBean的时候
                registerBeanPostProcessors(beanFactory);
                // 7. 初始化国际化资源
                initMessageSource();
                // 8. 初始化事件广播器
                initApplicationEventMulticaster();
                // 9. 留给子类实现的模板方法
                onRefresh();
                // 10. 注册事件监听器
                registerListeners();
                // 11. 实例化所有非延迟加载的单例
                finishBeanFactoryInitialization(beanFactory);
                // 12. 完成刷新过程,发布应用事件
                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();
            }
        }
    }
    

    step1: prepareRefresh

    // org.springframework.context.support.AbstractApplicationContext#prepareRefresh
    protected void prepareRefresh() {
        // Switch to active.
        this.startupDate = System.currentTimeMillis();
        this.closed.set(false);
        this.active.set(true);
    
        // 这里省略打印日志的代码
        if (logger.isDebugEnabled()) { ... }        
    
        // Initialize any placeholder property sources in the context environment.
        // 初始化上下文环境,容器的一些信息这个时候加载了进来比如:文件路径信息, 由子类实现
        initPropertySources();
        
        // 校验标示为必填的属性信息是否都有了:
        // see ConfigurablePropertyResolver#setRequiredProperties
        getEnvironment().validateRequiredProperties();
        
        // 存储 pre-refresh ApplicationListeners...
        if (this.earlyApplicationListeners == null) {
            this.earlyApplicationListeners = new LinkedHashSet<>(this.applicationListeners);
        }
        else {
            // Reset local application listeners to pre-refresh state.
            this.applicationListeners.clear();
            this.applicationListeners.addAll(this.earlyApplicationListeners);
        }
        // Allow for the collection of early ApplicationEvents, to be published once the multicaster is available...
        this.earlyApplicationEvents = new LinkedHashSet<>();
    }
    

    step2: obtainFreshBeanFactory

    // 方法走进:
    org.springframework.context.support.AbstractApplicationContext#obtainFreshBeanFactory
    
    protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
        // 刷新 BeanFactory: 子类实现, 该方法在所有bean实例化之前被refresh方法调用
        refreshBeanFactory();
        // 获取 BeanFactory: 子类实现, 需检查context是否仍active, 否则 throw e;
        return getBeanFactory();
    }
    
    // AbstractApplicationContext有2个子类, 分别实现了上述俩方法, 
    1.GenericApplicationContext (本例spring-boot启动时, 走进了该类)
    2.AbstractRefreshableApplicationContext (xml配置时, 可能走进该类)
    https://blog.csdn.net/qq924862077/article/details/60879926
    

    step3: prepareBeanFactory

    // org.springframework.context.support.AbstractApplicationContext#prepareBeanFactory
    
    protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory) {
        // 设置classloader(用于加载bean),设置表达式解析器(解析bean定义中的一些表达式),添加属性编辑注册器(注册属性编辑器)
        beanFactory.setBeanClassLoader(getClassLoader());
        beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver(beanFactory.getBeanClassLoader()));
        beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this, getEnvironment()));
    
        // 添加ApplicationContextAwareProcessor: 主要是对Aware接口的支持,如果实现了相应的 Aware接口,则注入对应的资源
        beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));
        // 取消下述6个接口的自动注入, 因为ApplicationContextAwareProcessor把这5个接口的实现工作做了
        beanFactory.ignoreDependencyInterface(EnvironmentAware.class);
        beanFactory.ignoreDependencyInterface(EmbeddedValueResolverAware.class);
        beanFactory.ignoreDependencyInterface(ResourceLoaderAware.class);
        beanFactory.ignoreDependencyInterface(ApplicationEventPublisherAware.class);
        beanFactory.ignoreDependencyInterface(MessageSourceAware.class);
        beanFactory.ignoreDependencyInterface(ApplicationContextAware.class);
    
        // 注册自动装配规则,如果发现依赖特殊类型,就使用该指定值注入
        // MessageSource registered (and found for autowiring) as a bean.
        beanFactory.registerResolvableDependency(BeanFactory.class, beanFactory);
        beanFactory.registerResolvableDependency(ResourceLoader.class, this);
        beanFactory.registerResolvableDependency(ApplicationEventPublisher.class, this);
        beanFactory.registerResolvableDependency(ApplicationContext.class, this);
    
        // Register early post-processor for detecting inner beans as ApplicationListeners.
        beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(this));
    
        // Detect a LoadTimeWeaver and prepare for weaving, if found.
        if (beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {
            beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));
            // Set a temporary ClassLoader for type matching.
            beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));
        }
    
        // Register default environment beans.
        if (!beanFactory.containsLocalBean(ENVIRONMENT_BEAN_NAME)) {
            beanFactory.registerSingleton(ENVIRONMENT_BEAN_NAME, getEnvironment());
        }
        if (!beanFactory.containsLocalBean(SYSTEM_PROPERTIES_BEAN_NAME)) {
            beanFactory.registerSingleton(SYSTEM_PROPERTIES_BEAN_NAME, getEnvironment().getSystemProperties());
        }
        if (!beanFactory.containsLocalBean(SYSTEM_ENVIRONMENT_BEAN_NAME)) {
            beanFactory.registerSingleton(SYSTEM_ENVIRONMENT_BEAN_NAME, getEnvironment().getSystemEnvironment());
        }
    }
    

    step4: postProcessBeanFactory

    // org.springframework.context.support.AbstractApplicationContext#postProcessBeanFactory
    这是一个留给子类去拓展的空方法,
    AnnotationConfigApplicationContext类中的该方法没有做任何事情。
    
    postProcessBeanFactory方法子类实现.png

    step5: invokeBeanFactoryPostProcessors

    ->AbstractApplicationContext#invokeBeanFactoryPostProcessors
    --> --> PostProcessorRegistrationDelegate#invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory, List<BeanFactoryPostProcessor>)  
    --> PostProcessorRegistrationDelegate#invokeBeanDefinitionRegistryPostProcessors
        --> ConfigurationClassPostProcessor#postProcessBeanDefinitionRegistry
        --> ConfigurationClassPostProcessor#processConfigBeanDefinitions
            --> ConfigurationClassParser#parse(Set<BeanDefinitionHolder>)
            --> ConfigurationClassParser#parse(AnnotationMetadata metadata, String beanName)
            --> ConfigurationClassParser#processConfigurationClass
            // 启动类 SpringCloudDubboEurekaApplication 加了 ComponentScan 注解, 这里被解析, 将扫描主类所在包所有 class
            --> ConfigurationClassParser#doProcessConfigurationClass
                // 处理所有加了 @PropertySource 的类
                // 处理所有加了 @ComponentScan 的类
                --> ComponentScanAnnotationParser#parse
                    --> ClassPathBeanDefinitionScanner#doScan
                        --> ClassPathScanningCandidateComponentProvider#findCandidateComponents
                        // 扫包路径: packageSearchPath --> classpath*:com/zy/eureka/**/*.class
                        --> ClassPathScanningCandidateComponentProvider#scanCandidateComponents
                            --> GenericApplicationContext#getResources
                                --> PathMatchingResourcePatternResolver#getResources
                                --> PathMatchingResourcePatternResolver#findPathMatchingResources
                                --> PathMatchingResourcePatternResolver#doFindPathMatchingFileResources
                                --> PathMatchingResourcePatternResolver#doFindMatchingFileSystemResources
                                --> PathMatchingResourcePatternResolver#retrieveMatchingFiles
                                // 这一步递归扫描获取所有 classpath*:com/zy/eureka/**/*.class 中需要被 spring 管理的 class 
                                --> PathMatchingResourcePatternResolver#doRetrieveMatchingFiles
                        // 扫包后, 处理注解: @Lazy,@Primary,@DependsOn,@Role,@Description
                        --> AnnotationConfigUtils#processCommonDefinitionAnnotations(AnnotatedBeanDefinition)
                        --> AnnotationConfigUtils#processCommonDefinitionAnnotations(AnnotatedBeanDefinition, AnnotatedTypeMetadata)
                        // 注册 BeanDefinition
                        --> ClassPathBeanDefinitionScanner#registerBeanDefinition
                            --> BeanDefinitionReaderUtils#registerBeanDefinition
                                // 将扫描到的需要被 spring 管理的 class 放进: DefaultListableBeanFactory 的 beanDefinitionMap<String, BeanDefinition>
                                --> DefaultListableBeanFactory#registerBeanDefinition
                                // 别名注册: 将别名放置到 SimpleAliasRegistry 的 aliasMap<String, String>
                                --> SimpleAliasRegistry#registerAlias
                // 处理所有加了 @Import 的类
                --> ConfigurationClassParser#processImports
                // 处理所有加了 @ImportResource 的类
                // 处理所有加了 @Bean 的类
                // 处理所有接口中被 default 修饰的方法(jdk8提供了此功能)
                // 处理父类
            --> ConfigurationClassParser#parse(Set<BeanDefinitionHolder>)
                // 这一步将会获取所有jar包classpath下META-INF/spring.factories文件中的value(此时已从缓存中取, 因为springboot启动时, 已加载过一次)
                // 将加载到的内容放置到 ConfigurationClassParser 的 this.configurationClasses中, 
                // 以便于后续 ConfigurationClassPostProcessor#processConfigBeanDefinitions 的方法 this.reader.loadBeanDefinitions(configClasses);
                // 来将加载的类, 注册进DefaultListableBeanFactory#beanDefinitionMap
                --> ConfigurationClassParser.DeferredImportSelectorHandler#process
        --> ConfigurationClassPostProcessor#processConfigBeanDefinitions    
            // this.reader.loadBeanDefinitions(configClasses);
            --> ConfigurationClassBeanDefinitionReader#loadBeanDefinitions
            --> ConfigurationClassBeanDefinitionReader#loadBeanDefinitionsForConfigurationClass
            // 这一步, 将项目中加了 @Configuration 注解, 并且加了 @Import 注解的类自身注册进 DefaultListableBeanFactory#beanDefinitionMap
            --> ConfigurationClassBeanDefinitionReader#registerBeanDefinitionForImportedConfigurationClass
            // 这一步, 将项目中加了 @Configuration 注解的类下, 加了 @Bean 注解的类注册进 DefaultListableBeanFactory#beanDefinitionMap
            --> ConfigurationClassBeanDefinitionReader#loadBeanDefinitionsForBeanMethod
            --> ConfigurationClassBeanDefinitionReader#loadBeanDefinitionsFromRegistrars
                // 下面这个类, 是自动配置中, 关于 AOP 的 BeanDefinition 的 register 
                --> AspectJAutoProxyRegistrar#registerBeanDefinitions
                    --> AopConfigUtils#registerAspectJAnnotationAutoProxyCreatorIfNecessary(BeanDefinitionRegistry)
                    --> AopConfigUtils#registerAspectJAnnotationAutoProxyCreatorIfNecessary(BeanDefinitionRegistry, Object)
                    // 这一步, 将 @EnableAspectJAutoProxy 所对应的 aop 的BeanDefinition 注册进DefaultListableBeanFactory#beanDefinitionMap
                    --> AopConfigUtils#registerOrEscalateApcAsRequired
                    // 这些流程之后, 将根据是否存在 proxyTargetClass 属性或 exposeProxy 属性, 对如何进行aop赋值
    
    // AbstractApplicationContext#invokeBeanFactoryPostProcessors
    
    public static void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory, List<BeanFactoryPostProcessor> beanFactoryPostProcessors) {
    
        // Invoke BeanDefinitionRegistryPostProcessors first, if any.
        Set<String> processedBeans = new HashSet<>();
    
        if (beanFactory instanceof BeanDefinitionRegistry) {
            BeanDefinitionRegistry registry = (BeanDefinitionRegistry) beanFactory;
            List<BeanFactoryPostProcessor> regularPostProcessors = new ArrayList<>();
            List<BeanDefinitionRegistryPostProcessor> registryProcessors = new ArrayList<>();
    
            // beanFactoryPostProcessors是传进来里的对象,把传入的对象分类放入 BeanFactoryPostProcessor 和  BeanDefinitionRegistryPostProcessor
            // BeanDefinitionRegistryPostProcessor extends BeanFactoryPostProcessor ,是一个特殊的 BeanFactoryPostProcessor
            for (BeanFactoryPostProcessor postProcessor : beanFactoryPostProcessors) {
                if (postProcessor instanceof BeanDefinitionRegistryPostProcessor) {
                    BeanDefinitionRegistryPostProcessor registryProcessor =
                            (BeanDefinitionRegistryPostProcessor) postProcessor;
                    // 如果传入的beanFactoryPostProcessors是它的子类,即:BeanDefinitionRegistryPostProcessor
                    // 则执行传入的BeanDefinitionRegistryPostProcessor的postProcessBeanDefinitionRegistry方法
                    registryProcessor.postProcessBeanDefinitionRegistry(registry);
                    registryProcessors.add(registryProcessor);
                } else {
                    regularPostProcessors.add(postProcessor);
                }
            }
    
            // 不要在这里初始化 FactoryBeans, 这里要先分离实现了:
            // PriorityOrdered, Ordered, and the rest接口的 BeanDefinitionRegistryPostProcessors
            List<BeanDefinitionRegistryPostProcessor> currentRegistryProcessors = new ArrayList<>();
    
            // First, invoke the BeanDefinitionRegistryPostProcessors that implement PriorityOrdered.
            // 这里只能拿到spring内部的BeanDefinitionRegistryPostProcessor,
            // 因为到这里spring还没有去扫描Bean,获取不到我们通过@Component标识的自定义BeanDefinitionRegistryPostProcessor
            // 一般默认情况下,这里只有一个: ConfigurationClassPostProcessor
            String[] postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
            for (String ppName : postProcessorNames) {
                if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
                    // 这里开始创建 BeanDefinitionRegistryPostProcessor子类bean 了
                    currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
                    processedBeans.add(ppName);
                }
            }
            //排序
            sortPostProcessors(currentRegistryProcessors, beanFactory);
            // registryProcessors 中放的是 implement PriorityOrdered 的 BeanDefinitionRegistryPostProcessor
            registryProcessors.addAll(currentRegistryProcessors);
            // 执行BeanDefinitionRegistryPostProcessor,currentRegistryProcessors中放的是spring内部的BeanDefinitionRegistryPostProcessor
            // 默认情况下,只有 org.springframework.context.annotation.ConfigurationClassPostProcessor
            // ConfigurationClassPostProcessor 里面就是在执行扫描 Bean,并且注册 BeanDefinition
            invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
            // 清空这个临时变量,方便后面再使用
            currentRegistryProcessors.clear();
    
            // Next, invoke the BeanDefinitionRegistryPostProcessors that implement Ordered.
            // 这里已经可以获取到我们通过注册到Spring容器的 BeanDefinitionRegistryPostProcessor 了
            postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
            for (String ppName : postProcessorNames) {
                // 之前优先处理的是实现PriorityOrdered接口的,而PriorityOrdered接口也实现了Ordered接口
                // 所有这里需要把之前已经处理过的给过滤掉
                if (!processedBeans.contains(ppName) && beanFactory.isTypeMatch(ppName, Ordered.class)) {
                    //之前这个临时变量已经被清空了,现在又开始放东西了
                    currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
                    processedBeans.add(ppName);
                }
            }
            sortPostProcessors(currentRegistryProcessors, beanFactory);
            // registryProcessors 中放的是 implement Ordered 的 BeanDefinitionRegistryPostProcessor
            registryProcessors.addAll(currentRegistryProcessors);
            invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
            currentRegistryProcessors.clear();
    
            // Finally, invoke all other BeanDefinitionRegistryPostProcessors until no further ones appear.
            boolean reiterate = true;
            while (reiterate) {
                reiterate = false;
                postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
                for (String ppName : postProcessorNames) {
                    //执行没有实现Ordered接口的BeanDefinitionRegistryPostProcessor
                    if (!processedBeans.contains(ppName)) {
                        currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
                        processedBeans.add(ppName);
                        reiterate = true;
                    }
                }
                sortPostProcessors(currentRegistryProcessors, beanFactory);
                // registryProcessors 中放的是 未implement Ordered 的 BeanDefinitionRegistryPostProcessor
                registryProcessors.addAll(currentRegistryProcessors);
                invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
                currentRegistryProcessors.clear();
            }
    
            // Now, invoke the postProcessBeanFactory callback of all processors handled so far.
            // List<BeanDefinitionRegistryPostProcessor> registryProcessors
            // 之前已经执行过 BeanDefinitionRegistryPostProcessor 独有方法, 现在执行其父类方法
            invokeBeanFactoryPostProcessors(registryProcessors, beanFactory);
    
            // List<BeanFactoryPostProcessor> regularPostProcessors
            // 执行 BeanFactoryPostProcessor 方法
            invokeBeanFactoryPostProcessors(regularPostProcessors, beanFactory);
        } else {
            // Invoke factory processors registered with the context instance.
            invokeBeanFactoryPostProcessors(beanFactoryPostProcessors, beanFactory);
        }
    
        // Do not initialize FactoryBeans here: We need to leave all regular beans
        // uninitialized to let the bean factory post-processors apply to them!
        // 获取 BeanFactoryPostProcessor 的 beanName
        String[] postProcessorNames = beanFactory.getBeanNamesForType(BeanFactoryPostProcessor.class, true, false);
    
        // Separate between BeanFactoryPostProcessors that implement PriorityOrdered, Ordered, and the rest.
        List<BeanFactoryPostProcessor> priorityOrderedPostProcessors = new ArrayList<>();
        List<String> orderedPostProcessorNames = new ArrayList<>();
        List<String> nonOrderedPostProcessorNames = new ArrayList<>();
        for (String ppName : postProcessorNames) {
            // 如果已经被执行过了, 就不在执行
            // 因为一开始先获取的 BeanDefinitionRegistryPostProcessor, 而BeanDefinitionRegistryPostProcessor继承了BeanFactoryPostProcessor
            if (processedBeans.contains(ppName)) {
                // skip - already processed in first phase above
            } else if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
                priorityOrderedPostProcessors.add(beanFactory.getBean(ppName, BeanFactoryPostProcessor.class));
            } else if (beanFactory.isTypeMatch(ppName, Ordered.class)) {
                orderedPostProcessorNames.add(ppName);
            } else {
                nonOrderedPostProcessorNames.add(ppName);
            }
        }
    
        // First, invoke the BeanFactoryPostProcessors that implement PriorityOrdered.
        // 根据不同的优先级,按序执行 BeanFactoryPostProcessor
        sortPostProcessors(priorityOrderedPostProcessors, beanFactory);
        invokeBeanFactoryPostProcessors(priorityOrderedPostProcessors, beanFactory);
    
        // Next, invoke the BeanFactoryPostProcessors that implement Ordered.
        List<BeanFactoryPostProcessor> orderedPostProcessors = new ArrayList<>();
        for (String postProcessorName : orderedPostProcessorNames) {
            orderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class));
        }
        sortPostProcessors(orderedPostProcessors, beanFactory);
        invokeBeanFactoryPostProcessors(orderedPostProcessors, beanFactory);
    
        // Finally, invoke all other BeanFactoryPostProcessors.
        List<BeanFactoryPostProcessor> nonOrderedPostProcessors = new ArrayList<>();
        for (String postProcessorName : nonOrderedPostProcessorNames) {
            nonOrderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class));
        }
        invokeBeanFactoryPostProcessors(nonOrderedPostProcessors, beanFactory);
    
        // Clear cached merged bean definitions since the post-processors might have
        // modified the original metadata, e.g. replacing placeholders in values...
        beanFactory.clearMetadataCache();
    }
    

    step6: AbstractApplicationContext#registerBeanPostProcessors

    // 注意: 与step5调用的是同一个类, 但静态方法不同, 走进:
    PostProcessorRegistrationDelegate#registerBeanPostProcessors(ConfigurableListableBeanFactory, AbstractApplicationContext)
    -->
    最终调用 AbstractBeanFactory#addBeanPostProcessor
    将BeanPostProcessor注册进一个List:
    private final List<BeanPostProcessor> beanPostProcessors = new CopyOnWriteArrayList<>();
    -->
    在后续bean创建步骤前后, 会判断某个bean是否实现了BeanPostProcessor接口, 
    从而是否需要调用其2个方法postProcessBeforeInitialization & postProcessAfterInitialization.
    见bean的生命周期一文
    <https://www.jianshu.com/p/a766267be3c6>
    

    step7: initMessageSource

    // AbstractApplicationContext#initMessageSource
    
    protected void initMessageSource() {
        ConfigurableListableBeanFactory beanFactory = getBeanFactory();
        // 看容器中是否包含id为messageSource的bean
        if (beanFactory.containsLocalBean(MESSAGE_SOURCE_BEAN_NAME)) {
            // 如果有名为messageSource的bean, 则取该bean作为messageSource
            this.messageSource = beanFactory.getBean(MESSAGE_SOURCE_BEAN_NAME, MessageSource.class);
            // 如果对应的messageSource是一个HierarchicalMessageSource, 且其ParentMessageSource为null
            // 则会在context父容器存在的情况下取父容器对应的messageSource作为当前messageSource的parentMessageSource
            if (this.parent != null && this.messageSource instanceof HierarchicalMessageSource) {
                HierarchicalMessageSource hms = (HierarchicalMessageSource) this.messageSource;
                if (hms.getParentMessageSource() == null) {
                    hms.setParentMessageSource(getInternalParentMessageSource());
                }
            }
            if (logger.isTraceEnabled()) { ... }
        }
        // 如果没有, 则新建 DelegatingMessageSource
        else {
            DelegatingMessageSource dms = new DelegatingMessageSource();
            dms.setParentMessageSource(getInternalParentMessageSource());
            this.messageSource = dms;
            beanFactory.registerSingleton(MESSAGE_SOURCE_BEAN_NAME, this.messageSource);
            if (logger.isTraceEnabled()) { ... }
        }
    }
    
    MessageSource接口,以用于支持信息的国际化和包含参数的信息的替换。
    ApplicationContext接口继承了MessageSource接口,
    所有ApplicationContext实现类对MessageSource接口的实现都是在AbstractApplicationContext中实现的,
    可以通过ApplicationContext来调用MessageSource接口方法以实现信息的国际化和替换信息中包含的参数。
    MessageSource提供了三个实现类,分别是
    >> ReloadableResourceBundleMessageSource
    >> StaticMessageSource
    >> ResourceBundleMessageSource
    

    https://www.jianshu.com/p/46eda1f96abe (国际化配置)

    step8: initApplicationEventMulticaster

    // AbstractApplicationContext#initApplicationEventMulticaster
    
    protected void initApplicationEventMulticaster() {
        ConfigurableListableBeanFactory beanFactory = getBeanFactory();
        // 如果 beanFactory 中存在名为 applicationEventMulticaster 的 ApplicationEventMulticaster 广播器, 则设置为本 context 中的
        if (beanFactory.containsLocalBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME)) {
            this.applicationEventMulticaster = beanFactory.getBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, ApplicationEventMulticaster.class);
            if (logger.isTraceEnabled()) { ... }
        }
        // 否则, 新建一个 SimpleApplicationEventMulticaster 的广播器
        else {
            this.applicationEventMulticaster = new SimpleApplicationEventMulticaster(beanFactory);
            beanFactory.registerSingleton(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, this.applicationEventMulticaster);
            if (logger.isTraceEnabled()) { ... }
        }
    }
    
    观察者模式的典型应用。观察者模式由主题Subject和Observer组成。
    广播器相当于主题Subject,其包含多个监听器。当主题发生变化时会通知所有得监听器。
    
    在后续的 "step12 finishRefresh" 步骤中, 
    会广播给实现了 ApplicationListener#onApplicationEvent方法的class, 调用其实现方法.
    
    注意:
    此处, 不调用项目中自定义的实现了ApplicationListener接口的class的onApplicationEvent方法, 因为bean还未初始化.
    

    step9: onRefresh

    AbstractApplicationContext并未实现onRefresh方法, 而是交由子类实现, 
    这里体现了模板模式, 可以是tomcat容器实现, 也可以是jetty等.
    这里启动了Tomcat, 主要是初始化2个核心组件,连接器(Connector)和容器(Container), 
    一个Tomcat实例就是一个Server,一个Server包含多个Service,
    也就是多个应用程序,每个Service包含多个连接器(Connetor)和一个容器(Container), 
    而容器下又有多个子容器,父子关系为:Engine,Host,Context,Wrapper,
    其中除了Engine外,其余的容器都是可以有多个。
    
    
    --> AbstractApplicationContext#onRefresh    
        --> ServletWebServerApplicationContext#onRefresh
        --> ServletWebServerApplicationContext#createWebServer
            --> TomcatServletWebServerFactory#getWebServer
            --> TomcatServletWebServerFactory#getTomcatWebServer
                --> TomcatWebServer#TomcatWebServer(Tomcat, boolean)
                --> TomcatWebServer#initialize
                    // Start the server to trigger initialization listeners
                    this.tomcat.start();
                    // Unlike Jetty, all Tomcat threads are daemon threads. 
                    // We create a blocking non-daemon to stop immediate shutdown               
                    startDaemonAwaitThread();
                        --> TomcatWebServer#startDaemonAwaitThread
                            // 这里起了一个线程, 使得 mainThread 一直存活, 并有后台线程池一直监听 http 连接
                            --> StandardServer#await
    
    
    tomcat启动后, main 线程不停止原理.png

    step10: registerListeners

    // AbstractApplicationContext#registerListeners
    
    protected void registerListeners() {
        // 注册静态指定的事件监听器ApplicationListener到事件广播中心ApplicationEventMulticaster
        for (ApplicationListener<?> listener : getApplicationListeners()) {
            getApplicationEventMulticaster().addApplicationListener(listener);
        }
    
        // 在beanFactory中查找ApplicationListener名称集合
        String[] listenerBeanNames = getBeanNamesForType(ApplicationListener.class, true, false);
        for (String listenerBeanName : listenerBeanNames) {
            //遍历名称并将当前名称的事件监听器注册到事件广播中心
            getApplicationEventMulticaster().addApplicationListenerBean(listenerBeanName);
        }
    
        // 所有事件监听器添加完成后,遍历发布者(ApplicationEventPublisher-ApplicaitonContext)已经发布的事件集合,并将事件通知到给定的监听器
        Set<ApplicationEvent> earlyEventsToProcess = this.earlyApplicationEvents;
        this.earlyApplicationEvents = null;
        if (earlyEventsToProcess != null) {
            for (ApplicationEvent earlyEvent : earlyEventsToProcess) {
                //通过事件广播中心ApplicationEventMulticaster,下发事件到具体的监听器ApplicationListener
                getApplicationEventMulticaster().multicastEvent(earlyEvent);
            }
        }
    }
    
    registerListeners 方法主要完成将监听器注册到事件广播中心实例中,
    在initApplicationEventMulticaster创建了事件广播中心实例,但广播中心还没有持有任何监听器,
    这步主要完成监听器的注册,以便事件下发时,能找到对应的监听器。
    

    step11: finishBeanFactoryInitialization (实例化所有非懒加载的单例)

    // AbstractApplicationContext#finishBeanFactoryInitialization
    
    -------------------------------------------------------------------------------
    在项目启动的时候会依次加载并实例化的是单例的非懒加载的类, 默认调用的是无参数的构造器。
    
    而对于prototype类型的,即@Scope("prototype"),在首次被用到的时候加载.
    -------------------------------------------------------------------------------
    
    
    --> DefaultListableBeanFactory#preInstantiateSingletons
        --> AbstractBeanFactory#getBean(String)
            --> AbstractBeanFactory#doGetBean
                --> AbstractAutowireCapableBeanFactory#createBean(String, RootBeanDefinition, Object[])
                    --> AbstractAutowireCapableBeanFactory#resolveBeforeInstantiation
                        --> AbstractAutowireCapableBeanFactory#resolveBeforeInstantiation
                            // 这里,如果实现了 InstantiationAwareBeanPostProcessor 接口, 则会调用其 postProcessBeforeInstantiation 方法
                            // 这里是在 bean 实例化之前执行的方法
                            --> AbstractAutowireCapableBeanFactory#applyBeanPostProcessorsBeforeInstantiation
                    --> AbstractAutowireCapableBeanFactory#doCreateBean
                        --> AbstractAutowireCapableBeanFactory#createBeanInstance
                            // bean实例化: 
                            --> AbstractAutowireCapableBeanFactory#instantiateBean
                                --> SimpleInstantiationStrategy#instantiate(RootBeanDefinition, String, BeanFactory)
                                    --> BeanUtils#instantiateClass(java.lang.reflect.Constructor<T>, java.lang.Object...)
                                        // 这一步通过反射调用构造器的方式将bean进行了实例化
                                        --> java.lang.reflect.Constructor#newInstance
                        // 这里,如果实现了 InstantiationAwareBeanPostProcessor 接口, 则会调用其 postProcessAfterInstantiation 方法
                        // 这是在 bean 实例化之后, 初始化之前执行的方法
                        --> AbstractAutowireCapableBeanFactory#populateBean
                        // bean实例化后, 开始初始化
                        --> AbstractAutowireCapableBeanFactory#initializeBean(String, Object, RootBeanDefinition)
                            // 如果实现了 BeanNameAware 接口, 则调用其 setBeanName 方法
                            // 如果实现了 BeanClassLoaderAware 接口, 则调用其 setBeanClassLoader 方法
                            // 如果实现了 BeanFactoryAware 接口, 则调用其 setBeanFactory 方法
                            --> AbstractAutowireCapableBeanFactory#invokeAwareMethods
                            // 如果实现了 BeanPostProcessor 接口, 则调用其 postProcessBeforeInitialization 方法
                            --> AbstractAutowireCapableBeanFactory#applyBeanPostProcessorsBeforeInitialization
                            // 如果实现了 InitializingBean 接口, 则调用其 afterPropertiesSet 方法
                            --> AbstractAutowireCapableBeanFactory#invokeInitMethods
                                // 如果自定义了初始化方法, 则调用其初始化方法(如 xml 中定义 init-method="xxx")
                                --> AbstractAutowireCapableBeanFactory#invokeCustomInitMethod
                            // 如果实现了 BeanPostProcessor 接口, 则调用其 postProcessAfterInitialization 方法
                            --> AbstractAutowireCapableBeanFactory#applyBeanPostProcessorsAfterInitialization
        // 如果实现了 SmartInitializingSingleton 接口, 则调用其 afterSingletonsInstantiated 方法
        smartSingleton.afterSingletonsInstantiated();
    
    ------这个 bean 实例化 & 初始化过程可以参考下述链接------
    

    https://www.jianshu.com/p/a766267be3c6 (bean生命周期)
    https://blog.csdn.net/u014082714/article/details/82388931 (bean加载)

    step12: finishRefresh

    // AbstractApplicationContext#finishRefresh
    
    protected void finishRefresh() {
        //  清除上下文资源缓存(如扫描中的ASM元数据)
        clearResourceCaches();
    
        // 当ApplicationContext启动或停止时,它会通过LifecycleProcessor来与所有声明的bean的周期做状态更新,
        // 而在LifecycleProcessor的使用前首先需要初始化, 若未定义, 则用 DefaultLifecycleProcessor
        initLifecycleProcessor();
    
        // 启动所有实现了Lifecycle接口的bean。
        getLifecycleProcessor().onRefresh();
    
        // 通过Spring中的事件发布机制来发出ContextRefreshedEvent事件
        // 若自定义了实现 ApplicationListener 接口的实现类, 监听 ContextRefreshedEvent 事件, 并加入了 IOC 容器, 则会调用其重写的 onApplicationEvent 方法
        // 如 org.apache.dubbo.config.spring.ServiceBean 在 IOC 容器加载完毕后, 进行服务的导出 --> apache dubbo 也这样搞了
        // 与 ContextRefreshedEvent 事件相似的还有 ContextStartedEvent、ContextClosedEvent、ContextStoppedEvent
        // 当然也可以继承 ApplicationContextEvent 抽象类来实现自定义的事件
        publishEvent(new ContextRefreshedEvent(this));
    
        // 调用LiveBeansView的registerApplicationContext方法:如果设置了JMX相关的属性,则就调用该方法
        LiveBeansView.registerApplicationContext(this);
    }
    
    #涉及到的相关class
    1.ApplicationEventMulticaster:
    应用事件广播器,用于发布事件到相应的监听器。
    2.LifecycleProcessor:
    生命周期处理器,用于处理生命周期事件。
    3.Lifecycle:
    定义生命周期控制方法的接口,特别是 SmartLifecycle,可以在 Spring IoC 容器刷新完毕时进行触发。
    通常用来配置后台程序,在启动后一直运行(如对 MQ 进行轮询等)。
    3.1 SmartLifecycle
    Shutting down the Spring IoC container gracefully in non-web applications.
    4.ApplicationContextEvent:
    应用事件的基类。
    5.ApplicationListener:
    应用事件监听器,用于监听应用事件。
    
    SmartLifecycle.png

    https://www.jianshu.com/p/7b8f2a97c8f5 (SmartLifecycle)

    4.Spring中的一些问题

    4.1 循环依赖的问题

    1.什么是循环依赖?
    循环依赖-->循环引用。即2个或以上bean 互相持有对方,最终形成闭环。
    eg:A依赖B,B依赖C,C又依赖A。
    
    2.Spring中循环依赖的场景?
    1) 构造器的循环依赖。【这个Spring解决不了】
    A有参构造是B。B的有参构造是C, C的有参构造是A, 这样就产生了一个循环依赖的情况。
    2)【setter循环依赖】field属性的循环依赖
    Spring是先将Bean对象实例化【依赖无参构造函数】--->再设置对象属性的.
    setter方式 单例,默认方式: 
    通过递归方法找出当前Bean所依赖的Bean,然后提前缓存【会放入Cache中】起来。
    当Spring实例化了A、B、C后,紧接着会去设置对象的属性,
    此时A依赖B,就会去Map中取出存在里面的单例B对象,以此类推,不会出来循环的问题了。
    
    #Java的引用传递
    Spring的循环依赖的理论依据其实是基于Java的引用传递,当我们获取到对象的引用时,
    对象的field或属性是可以延后设置的(但是构造器必须是在获取引用之前)。
    
    #Spring的单例对象的初始化主要分为三步: 
    ①createBeanInstance:实例化,其实也就是 调用对象的构造方法实例化对象
    ②populateBean:填充属性,这一步主要是多bean的依赖属性进行填充
    ③initializeBean:调用spring xml中的init() 方法。
    循环依赖主要发生在第一、第二步。也就是构造器循环依赖和field循环依赖。
    
    那么我们要解决循环引用也应该从初始化过程着手,
    对于单例来说,在Spring容器整个生命周期内,有且只有一个对象,
    所以很容易想到这个对象应该存在Cache中,Spring为了解决单例的循环依赖问题,使用了三级缓存。
    
    #解决构造函数注入导致的循环依赖问题:
    "调整配置文件,将构造函数注入方式改为属性注入方式即可"
    
    解决循环依赖关键在于构造函数注入在属性注入之前.png
    #源码中的实现 DefaultSingletonBeanRegistry --> 三级缓存
    /** 单例对象的cache. Cache of singleton objects: bean name to bean instance. */
    private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256);
    
    /** 单例对象工厂的cache. Cache of singleton factories: bean name to ObjectFactory. */
    private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap<>(16);
    
    /** 提前暴光的单例对象的Cache 。【用于检测循环引用,与singletonFactories互斥】.Cache of early singleton objects: bean name to bean instance. */
    private final Map<String, Object> earlySingletonObjects = new HashMap<>(16);
    
    /** 这里 getSingleton 时通过三级缓存解决循环依赖. */
    protected Object getSingleton(String beanName, boolean allowEarlyReference) {
        Object singletonObject = this.singletonObjects.get(beanName);
        if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
            synchronized (this.singletonObjects) {
                singletonObject = this.earlySingletonObjects.get(beanName);
                if (singletonObject == null && allowEarlyReference) {
                    ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
                    if (singletonFactory != null) {
                        singletonObject = singletonFactory.getObject();
                        this.earlySingletonObjects.put(beanName, singletonObject);
                        this.singletonFactories.remove(beanName);
                    }
                }
            }
        }
        return singletonObject;
    }
    
    
    #getSingleton()的整个过程分析:
    Spring首先从一级缓存singletonObjects中获取。
    如果获取不到,并且对象正在创建中,就再从二级缓存earlySingletonObjects中获取。
    如果还是获取不到且允许singletonFactories通过getObject()获取,
    就从三级缓存singletonFactory.getObject()(三级缓存)获取,
    如果获取到了则从singletonFactories中移除,并放入earlySingletonObjects中。
    其实也就是从三级缓存移动到了二级缓存。
    
    从上面三级缓存的分析,我们可以知道,Spring解决循环依赖的诀窍就在于singletonFactories这个三级cache。
    这个cache的类型是ObjectFactory。
    

    4.2 Spring中父子容器

    4.2.1 Spring-SpringMVC中的父子容器

    Spring-SpringMVC中的父子容器.png

    web.xml

    <!DOCTYPE web-app PUBLIC
     "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
     "http://java.sun.com/dtd/web-app_2_3.dtd" >
    <web-app>
      <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>classpath:spring/applicationContext.xml</param-value> <!-- 如果是监听多个文件,可用‘,’隔开 -->
      </context-param>
      <!-- 定义SPRING监听器,加载spring, 这里扫包后, 生成父容器 -->
      <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
      </listener>
    
      <servlet>
        <servlet-name>springMVC</servlet-name>
        <!-- 这里扫包后, 生成子容器 -->
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <init-param>
          <param-name>contextConfigLocation</param-name>
          <!-- 如果是监听多个文件,可用‘,’隔开 -->
          <param-value>classpath:spring/spring-mvc.xml</param-value>
        </init-param>
      </servlet>
      <servlet-mapping>
        <servlet-name>springMVC</servlet-name>
        <url-pattern>/</url-pattern>
      </servlet-mapping>
    </web-app>
    

    applicationContext.xml扫包配置

    <!--开启自动扫包:注意这里只扫描 service, mapper 层的包,防止重复扫描-->
    <context:component-scan base-package="com.zy.service,com.zy.mapper"/>
    <!--只有这里配置了, 本文件中才能读取到, 子容器读不到-->
    <context:property-placeholder location="classpath:db.properties"/>
    

    spring-mvc.xml扫包配置

    <!--开启自动扫包:注意这里只扫描 controller 层的包,防止重复扫描-->
    <!--如果springmvc容器扫多了,那么父子容器都有一套service,controller用自己的service,那么在父容器中配置的事务就不生效了-->
    <context:component-scan base-package="com.zy.controller"/>
    <!--只有这里配置了, 本文件中才能读取到, 父容器读不到-->
    <context:property-placeholder location="classpath:db.properties"/>
    

    spring & spring-mvc的启动过程

    1.对于一个web应用,其部署在web容器中,web容器提供其一个全局的上下文环境,
    这个上下文就是ServletContext,其为后面的spring IoC容器提供宿主环境;
    
    2.在web.xml中会提供有ContextLoaderListener。
    在web容器启动时,会触发容器初始化事件,
    此时ContextLoaderListener会监听到这个事件,其contextInitialized方法会被调用,
    在这个方法中,spring会初始化一个启动上下文,这个上下文被称为根上下文,
    即WebApplicationContext,其实际的实现类XmlWebApplicationContext。
    这个就是spring的IoC容器,其对应的Bean定义的配置由web.xml中的context-param标签指定。
    在这个IoC容器初始化完毕后,spring以
    WebApplicationContext.ROOTWEBAPPLICATIONCONTEXTATTRIBUTE为属性Key,
    将其存储到ServletContext中,便于获取;
    
    3.ContextLoaderListener监听器初始化完毕后,开始初始化web.xml中配置的Servlet,
    这个servlet可以配置多个,以最常见的DispatcherServlet为例,
    这个servlet实际上是一个标准的前端控制器,用以转发、匹配、处理每个servlet请求。
    DispatcherServlet上下文在初始化的时候会建立自己的IoC上下文,用以持有spring mvc相关的bean。
    在建立DispatcherServlet自己的IoC上下文时,会利用
    WebApplicationContext.ROOTWEBAPPLICATIONCONTEXTATTRIBUTE
    先从ServletContext中获取之前的根上下文(即WebApplicationContext)作为自己上下文的parent上下文。
    有了这个parent上下文之后,再初始化自己持有的上下文。
    这个DispatcherServlet初始化自己上下文的工作在其initStrategies方法中可以看到,
    大概的工作就是初始化处理器映射、视图解析等。
    这个servlet自己持有的上下文默认实现类也是mlWebApplicationContext。
    初始化完毕后,spring以与servlet的名字相关(此处不是简单的以servlet名为Key,而是通过一些转换)
    的属性为属性Key,也将其存到ServletContext中,以便后续使用。
    这样每个servlet就持有自己的上下文,即拥有自己独立的bean空间,
    同时各个servlet共享相同的bean,即根上下文(第2步中初始化的上下文)定义的那些bean。
    

    父子容器特点

    #父子容器中的对象<子可访问父对象, 父不可访问子对象>
    子容器可以访问父容器的对象,父容器不能访问子容器中的对象。
    
    #父子容器中的属性<属性互相都访问不到>
    如果在父容器中有properties文件,其中的属性子容器是访问不到的!子容器也是无法访问到父容器中的属性的.
    即: 这个读取配置文件的操作, 配置在哪个文件中, 哪里才能读取到
    <context:property-placeholder location="classpath:db.properties"/>
    

    可能产生的问题

    1.重复扫包导致bean可能注册到两个容器中
    2.重复扫包导致事务不生效(若controller扫到的bean没有事务)
    即@Transactional无效(也可能该注解搞到了private方法上)
    3.父容器中Bean找不到
    4.SpringMVC不能正常跳转
    

    解决父子容器冲突问题

    Spring容器优先加载由ServletContextListener(对应applicationContext.xml)产生的父容器,
    而SpringMVC(对应spring-mvc.xml)产生的是子容器。
    
    如果说子容器扫描了service及dao所在的包, 则会将@Service注解的实例也装配到子容器中.
    一方面导致bean的重复加载, 另一方面子容器中的bean是没有经过事务加强处理,即没有事务处理能力的Service,
    而父容器进行初始化的Service是保证事务的增强处理能力的。
    
    所以若想使得service层仍然有事务处理能力, 在子容器扫包时:
    方法1:仅仅扫描controller层即可, 不要扫描其它层.
    方法2:在子容器中将Service exclude掉.
    
    #总结:
    >> 如果只处理service的bean,那么只在父容器的配置文件中操作
    >> 如果只处理controller的bean,那么在mvc的配置文件中修改
    >> 如果同时要处理service,还要处理controller,那么在两个配置文件中都进行修改
    

    https://www.jianshu.com/p/e48eeca7c0b7 (Spring父子容器)
    https://blog.csdn.net/weixin_39559282/article/details/83352672

    4.2.2 SpringCloud项目中的父子容器

    https://blog.csdn.net/forezp/article/details/87910226 (cloud父子容器)

    参考资源
    https://www.jianshu.com/p/524d62ee91fb (加载xml文件的方式)
    https://segmentfault.com/a/1190000020742805?utm_source=tag-newest
    https://www.cnblogs.com/bigshark/p/11355655.html (springboot2.0启动大概流程)
    https://www.jianshu.com/p/09c0581fbacf (SpringCloud启动中SpringApplication构造方法执行多次)
    https://www.jianshu.com/p/7164bf18a57b (refresh方法)
    https://www.jianshu.com/p/c7a416ba7950 (refresh方法)
    https://blog.csdn.net/xingxing513234072/article/details/78247480 (Spring容器初始化过程 & Bean注册 & Bean实例化 ----- IOC & DI)
    https://blog.csdn.net/u014082714/article/details/82388931 (Bean的创建和初始化 ---->核心)
    https://blog.csdn.net/elim168/article/details/77891450 (国际化MessageSource)
    https://blog.csdn.net/v123411739/article/details/99288413 (IOC机制)
    https://blog.csdn.net/wugaokai0831/article/details/84008654 (DefaultSingletonBeanRegistry)
    https://www.jianshu.com/p/f13f554ee8ce (BeanFactory & ApplicationContext)
    https://blog.csdn.net/woshilijiuyi/article/details/82219585 (这一篇挺好)
    https://blog.csdn.net/qq_36381855/article/details/79752689 (循环依赖)

    相关文章

      网友评论

        本文标题:Spring-IOC & Spring-Boot2启动

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