• Spring Boot启动流程


    基础准备

    1,BeanPostProcessor:这个接口的作用在于对于新构造的实例可以做一些自定义的修改。比如如何构造、属性值的修改、构造器的选择等等

    2,BeanFactoryPostProcessor:在容器实例化任何其它bean之前读取配置元数据,并可以根据需要进行修改,例如可以把bean的scope从singleton改为prototype,也可以把property的值给修改掉

    3,BeanDefinitionRegistryPostProcessor:允许在普通的BeanFactoryPostProcessor接口实现类执行之前注册更多的BeanDefinition。特别地是,BeanDefinitionRegistryPostProcessor可以注册BeanFactoryPostProcessor的BeanDefinition

    4,Import:通过注解导入BeanDefinition,例如EnableAutoConfiguration导入spring.factories配置的各种配置类。在ImportSelector中选择要导入的Configuration类或者通过ImportBeanDefinitionRegistrar添加BeanDefinition,基于注解的导入可以通过配置属性值决定导入那些类

    应用初始化

    @Configuration
    @EnableAutoConfiguration//三个注解的使用后面ConfigurationClassPostProcessor部分会讲到
    @ComponentScan
    public class Application {
        public static void main(String[] args) {
            SpringApplication.run(Application.class, args);
        }
    }
    

      

    构造SpringApplication对象

    public SpringApplication(Object... sources) {
        initialize(sources);
    }
    private void initialize(Object[] sources) {
        // 为成员变量sources赋值
        if (sources != null && sources.length > 0) {
            this.sources.addAll(Arrays.asList(sources));
        }
        this.webEnvironment = deduceWebEnvironment();
        //从spring.factories加载ApplicationContextInitializer,用来初始化ApplicationContext,在prepareContext中调用,例如DuibaEnvironmentDecryptApplicationInitializer对配置进行解密
        setInitializers((Collection) getSpringFactoriesInstances(ApplicationContextInitializer.class));
        //从spring.factories加载ApplicationListener,订阅ApplicationContext的创建和刷新的不同阶段的事件,被SpringApplicationRunListener调用,例如ConfigFileApplicationListener订阅ApplicationEnvironmentPreparedEvent加载配置文件
        setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));
        this.mainApplicationClass = deduceMainApplicationClass();
    }
    

      

    图一:默认加载的ApplicationListener以及对应的作用

    核心方法

    //获取spring.factories下定义的SpringApplicationRunListener,发布SpringApplication启动过程中的各种事件,主要是EventPublishingRunListener来将事件广播到ApplicationListener
    SpringApplicationRunListeners listeners = getRunListeners(args);
    listeners.starting();
    ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);
    //创建Environment,发布ApplicationEnvironmentPreparedEvent,springcloud就是使用BootstrapApplicationListener通过订阅这个事件完成了configserver上配置的加载
    ConfigurableEnvironment environment = prepareEnvironment(listeners,applicationArguments);
    Banner printedBanner = printBanner(environment);//打印banner
    //创建ApplicationContext
    context = createApplicationContext();
    analyzers = new FailureAnalyzers(context);
    //调用ApplicationContextInitializer初始化,注入当前启动类的BeanDefinition,完成后beanmap中还只有启动类和AnnotationConfigUtils注入的几个BeanPostProcessor(不考虑springcloud的场景),这个类上声明的Configuration,EnableAutoConfiguration,ComponentScan等被ConfigurationClassPostProcessor处理加载其余的BeanDefinition
    prepareContext(context, environment, listeners, applicationArguments,printedBanner);
    refreshContext(context);//核心方法,调用Context的refresh方法
    afterRefresh(context, applicationArguments);
    listeners.finished(context, null);
    

      

    createApplicationContext:创建ApplicationContext 对于web应用创建AnnotationConfigEmbeddedWebApplicationContext,初始化时调用AnnotationConfigUtils.registerAnnotationConfigProcessors注册常用的BeanPostProcessor:

    ConfigurationClassPostProcessor:处理@Configuration CommonAnnotationBeanPostProcessor:处理@Resource、@PostConstruct和@PreDestroy AutowiredAnnotationBeanPostProcessor:处理@Autowired、@Value、@Lookup和@Inject注解的实现 RequiredAnnotationBeanPostProcessor:处理@Required注解 BeanValidationPostProcessor:处理@Min,@NotNull等注解

    refreshContext:调用AbstractApplicationContext的refresh方法

    // 初始化 refresh 的上下文环境
            prepareRefresh();
            // 初始化 BeanFactory,加载并解析BeanDefinition,子类实现
            ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
            // 对 BeanFactory 进行功能增强,例如添加ApplicationContextAwareProcessor设置各种Aware实现类的属性。注入一些其它信息的bean,比如environment、systemProperties等
            //添加ApplicationListenerDetector,用于探测 ApplicationListener 类型接口
            prepareBeanFactory(beanFactory);
            try {
                // 子类扩展注册BeanDefinition
                postProcessBeanFactory(beanFactory);
                // BeanFactoryPostProcessor 用于对 BeanFactory 实例进行后置处理,重点包含ConfigurationClassPostProcessor会解析@Configuration注解的类进行注册
                invokeBeanFactoryPostProcessors(beanFactory);
                // 注册BeanPostProcessor,主要是AnnotationConfigUtils.registerAnnotationConfigProcessors注册的BeanPostProcessor,如果是通过配置类创建的在上一步已经注册了
                registerBeanPostProcessors(beanFactory);
                // 初始化国际化资源
                initMessageSource();
                // 初始化事件广播器
                initApplicationEventMulticaster();
                // 子类实现,springboot中是EmbeddedWebApplicationContext创建web容器(Tomcat,jetty等)
                onRefresh();
                //将容器中解析出的ApplicationListener注册到广播器
                registerListeners();
                // 实例化所有非延迟加载的单例
                finishBeanFactoryInitialization(beanFactory);
                //发布上下文刷新完毕事件,调用所有实现了 Lifecycle 的 start 方法,调用web服务器的start方法
                finishRefresh();
            }
    

      

    图二:invokeBeanFactoryPostProcessors内部的调用流程

    图三:ConfigurationClassPostProcessor解析注解加载BeanDefinition的流程

    总结:
    1,扩展性强:通过ApplicationContextInitializer,SpringApplicationRunListener,SmartApplicationListener(或者EventListener注解)等在应用的启动过程调用自定义行为,例如Spring Cloud就是通过BootstrapApplicationListener订阅ApplicationEnvironmentPreparedEvent在启动过程中实现了外部配置文件的加载

    2,灵活:通过Configuration,Import等灵活的实现类注入简化了配置,配合ConfigurationProperties极大的简化了系统的初始化配置

    参考:
    http://zhaox.github.io/java/2016/03/22/spring-boot-start-flow

    http://fangjian0423.github.io/2017/05/10/springboot-context-refresh/

    http://www.zhenchao.org/2017/06/03/spring-src-application-context/

  • 相关阅读:
    java开发:分享一下百度ueditor和七牛的图片集成上传
    java开发:分享一下使用urlrewrite实现网址的个性访问
    javascript应用:页面解析list和map封装后的json数据
    JAVA开发:分享一些SpringMvc+Ibatis+spring的框架使用心得
    使用OLEDB读取excel和csv文件
    静态代码块、构造代码块
    序列化和反序列化
    windows下Mysql5.7.10免安装版配置
    form表单中的encType属性
    关于字符编码,你所需要知道的(ASCII,Unicode,Utf-8,GB2312…)
  • 原文地址:https://www.cnblogs.com/sdhjl2000/p/8520431.html
Copyright © 2020-2023  润新知