• Spring及tomcat初始化日志


    Tomcat

    StandardContext初始化过程

    //org.apache.catalina.core.StandardContext#startInternal
    
      // 子容器启动
      for (Container child : findChildren()) {
          if (!child.getState().isAvailable()) {
              child.start();
          }
      }
    
    //初始化WebappLoader 
       if (getLoader() == null) {
            WebappLoader webappLoader = new WebappLoader(getParentClassLoader());
            webappLoader.setDelegate(getDelegate());
            setLoader(webappLoader);
        }
    
    //实例化contextManager ,用于管理session
         Manager contextManager = null;
         try {
                 contextManager = getCluster().createManager(getName());
             } catch (Exception ex) {
                 log.error("standardContext.clusterFail", ex);
                 ok = false;
             }             
        setManager(contextManager);            
    
        //1. 
        //初始化所有Listener实例,    
         if (ok) {
             if (!listenerStart()) {
                 log.error( "Error listenerStart");
             }
         }
         //2.
         try {
             // 启动StandardManager,该类管理Session信息
             if ((manager != null) && (manager instanceof Lifecycle)) {
                 ((Lifecycle) getManager()).start();
             }
    
             //启动后台线程, 检查seesion超时
             super.threadStart();
         } 
    
    
    //3. 初始化 application filters
      if (ok) {
          if (!filterStart()) {
              log.error("Error filterStart");
              ok = false;
          }
      }
    
    
    //4. 
    //加载和初始化标记"load on startup"大于1的Servelet
    if (ok) {
        loadOnStartup(findChildren());
    }

    Tomcat初始化监听对象:

    监听器分两种LifeCycleListener, EventListener ,如图所示,

    参考资料: 

    https://blog.csdn.net/yangsnow_rain_wind/article/details/80118321


    serveltContext

    serveltContext标示Tomcat存储当前Web程序的上下文信息,

    1. 每个Engine有多个war包, 每个war包就是一个web应用程序, 每个web应用程序只有一个Context上下文,这就是servletContext.
    2. 每个servletcontext下可以有多个servlet, 每个servlet需要有配置url映射. 每个servlet需要被包装为StandardWrapper类, 存储到servletcontext容器中.
    3. ServletContext 对象是一个为整个 web 应用提供共享的内存,多个servlet实例见可以通过context进行通信.
    4. ServletContext 在tomcat中对应的类是ApplicationContext

    参照笔记: https://blog.csdn.net/yangsnow_rain_wind/article/details/80118321


    1、spi简单说明
    spi,即service privider interface,是jdk为厂商和插件提供的一种解耦机制。
    spi的具体规范为:当服务的提供者,提供了服务接口的一种实现之后,在jar包的META-INF/services/目录里同时创建一个以服务接口命名的文件。该文件里就是实现该服务接口的具体实现类。而当外部程序装配这个模块的时候,就能通过该jar包META-INF/services/里的配置文件找到具体的实现类名,并通过反射机制实例化,完成模块的注入。 基于这样一个约定就能很好的找到服务接口的实现类,而不需要再代码里制定。jdk提供服务实现查找的一个工具类:java.util.ServiceLoader

    2、spring-web中的具体应用
    从servlet3.0开始,web容器启动时为提供给第三方组件机会做一些初始化的工作,例如注册servlet或者filtes等,servlet规范中通过ServletContainerInitializer.onStartup实现此功能。

    每个框架要使用ServletContainerInitializer就必须在对应的jar包的META-INF/services 目录创建一个名为javax.servlet.ServletContainerInitializer的文件,文件内容指定具体的ServletContainerInitializer实现类,那么,当web容器启动时就会运行这个初始化器做一些组件内的初始化工作。

    一般伴随着ServletContainerInitializer一起使用的还有HandlesTypes注解,通过HandlesTypes可以将感兴趣的一些类注入到ServletContainerInitializerde的onStartup方法作为参数传入。

    spring-web的jar定义了一个具体的实现类,SpringServletContainerInitializer,并且在META-INF/services/目录下定义了如下文件org.springframework.web.SpringServletContainerInitializer。

    3、SpringServletContainerInitializer

    SpringServletContainerInitializer是接口ServletContainerInitializer的实现类,tomcat启动时调用processServletContainerInitializers,通过SPI机制,找到classpath下所有实现ServletContainerInitializers接口的类,然后初始化这个类,并调用此类的接口onStartup.

    SpringServletContainerInitializer类上注解为@HandlesTypes(WebApplicationInitializer.class)~,它的作用是将感兴趣的一些类注入到ServletContainerInitializer,并作为参数传给onStartup方法,并后续完成类初始化。

    源码如下:

     

     最终ServletContainerInitializers.onStartup方法变成了实现WebApplicationInitializer.onStartup(ServletContext)

     4. WebApplicationInitializer

    通过实现接口WebApplicationInitializer,在其中可以添加servlet,listener等,在加载Web项目的时候会加载这个接口实现类,从而起到web.xml相同的作用。

    其重要的一个实现类是SpringBootServletInitializer

    5. SpringBootServletInitializer

    
    

     


    事件监听 

    ServletContextListener:在servlet启动时,获得监听(contextInitialized,contextDestroyed)

    ContextLoaderListener: 用来在部署相关Web应用时初始化其上下文环境(initWebApplicationContext, 并放置在servletContext.attr(".root")属性中),在停止退出Web应用时清理其资源

    ServletContextListener:

    包括两个接口方法:contextInitialized,contextDestroyed,Web 应用的生命周期中,ServletContext 对象最早被创建,最晚被销毁,常被用于在web容器启动war之前对servlet进行提前配置,

    如设置attribute参数到servletContext中。SpringMVC框架中被用来初始化IOC容器等,(ContextLoaderListener类中在contextInitialized方法中初始化initWebApplicationContext(被放在servletContext.attr(".root")属性中)) 

     

    Filter

     Filter(过滤器)可以改变HTTP请求的内容、响应、及header信息,过滤器通常不产生响应或像 servlet 那样对请求作出响应,而是修改或调整到资源的请求,修改或调整来自资源的响应。

    当容器接收到传入的请求时,它将获取列表中所有符合该请求的过虑器组成过虑器链(FilterChain),然后通过FilterChain嵌套调用各过虑器的Filter.doFilter()方法(一个过滤器可以使得滤器链调用下一个过滤器),传入ServletRequest 和ServletResponse进行处理。

          当滤器链调用完各Filter.doFilter()方法后,会调用相关Servlet.service()方法,从而进行Servlet的处理。注意,Filter.doFilter()可以阻止过滤器链接下来的调用,返回时过滤器负责填充Reponse对象。

          过滤器实例移除之前,容器必须先调用过滤器的Filter.destroy()方法。

    web.xml中组件加载顺序为:

           context-param -> listener -> filter -> servlet(同类则按编写顺序执行)


     

    ApplicationContextInitializer:

    ApplicationContextInitializer是Spring框架原有的东西,这个类的主要作用就是在ConfigurableApplicationContext类型(或者子类型)的ApplicationContextrefresh之前,允许我们对ConfiurableApplicationContext的实例做进一步的设置和处理。

    ApplicationContextInitializer接口是在spring容器刷新Refresh之前执行的一个回调函数

    实际应用:

    在一个Springboot应用中,classpath上会包含很多jar包,有些jar包需要在ConfigurableApplicationContext#refresh()调用之前对应用上下文做一些初始化动作,因此它们会提供自己的ApplicationContextInitializer实现类,然后放在自己的META-INF/spring.factories属性文件中,这样相应的ApplicationContextInitializer实现类就会被SpringApplication#initialize发现。

    添加方法有三种

    1. 启动类里手动增加initializer

    @SpringBootApplication
    @EnableConfigServer
    @EnableDiscoveryClient
    public class ConfigServer {
        public static void main(String[] args) {
            SpringApplication springApplication = new SpringApplication(ConfigServer.class);
    
            // 方法一:添加自定义的 ApplicationContextInitializer 实现类的实例(注册ApplicationContextInitializer)
            springApplication.addInitializers(new ApplicationContextInitializer1());
    
            ConfigurableApplicationContext context = springApplication.run(args);
    
            context.close();
        }
    }

    2.application.properties添加配置方式

    context.initializer.classes = com.springboot.xx.xx.ApplicationPropertiesApplicationContextInitializer

    3. 使用spring.factories方式

    1. 先定义先定义ApplicationContextInitializer

    2、然后在项目下的resources下新建META-INF文件夹,文件夹下新建spring.factories文件

    org.springframework.context.ApplicationContextInitializer=com.x.ApplicationContextInitializer1

    总结:

    ApplicationContextInitializer是Spring留出来允许我们在上下文刷新之前做自定义操作的钩子,若我们有需求想要深度整合Spring上下文,借助它不乏是一个非常好的实现。

     

     


    网关作用:

    在微服务实施之后,各个服务的拆分粒度很小,对于客户端来说,做一个操作可能会涉及到 后端的多个服务组件的调用,那意味着它需要频繁的发起多次访问才能进行数据聚合实现用 户的功能。 如果我们在所有的微服务之前增加一个网关,对于客户端来说它需要做什么功能操作直接调 用网关并且告诉网关所要做的事情即可,网关根据请求的功能对后端的多个服务的数据进行 聚合聚合哦从而减少客户端的调用频次。 并且,由于有了网关的聚合,我们还可以在网关层对请求进行统一鉴权和认证; 包括还可 以实现限流、请求日志统一记录、 灰度发布等等。

    Enable 注解不仅仅可以像前面演示的案例一样很简单的实 现多个 Configuration 的整合,还可以实现一些复杂的场 景,比如可以根据上下文来激活不同类型的 bean, @Import 注解可以配置三种不同的 class

    1. 第一种就是前面演示过的,基于普通 bean 或者带有 @Configuration 的 bean 进行诸如

    2. 实现 ImportSelector 接口进行动态注入
    3. 实现 ImportBeanDefinitionRegistrar 接口进行动态注入

    @EnableAutoConfiguration 注解的实现原理

    在@EnableAutoConfiguration注解内使用到了@import注解来完成导入配置的功能,而EnableAutoConfigurationImportSelector内部则是使用了SpringFactoriesLoader.loadFactoryNames方法进行扫描具有META-INF/spring.factories文件的jar包


    自动填充属性
    EnableConfigurationProperties
     
     
  • 相关阅读:
    角学习教程
    用AngularJS指令扩展HTML
    MVC 6动态导航菜单从数据库
    从Angular5和ASP开始。网络核心
    .NET中的音乐符号
    在Blazor的音乐符号-第二部分
    ASP。NET Core 2.1:集成VMD.RESTApiResponseWrapper。REST API应用程序的核心
    AsyncHttpClient
    Mina
    Volley
  • 原文地址:https://www.cnblogs.com/snow-man/p/12341803.html
Copyright © 2020-2023  润新知