zxpnet网站 zxpnet网站
首页
前端
后端服务器
  • 分类
  • 标签
  • 归档
GitHub (opens new window)

zxpnet

一个爱学习的java开发攻城狮
首页
前端
后端服务器
  • 分类
  • 标签
  • 归档
GitHub (opens new window)
  • 大后端课程视频归档
  • 南航面试题
  • 并发编程

  • 性能调优

  • java8语法

  • lombok

  • 日志

  • 工具类

  • spring

  • mybatis

  • springboot

    • springboot基础篇
    • springboot配置文件yaml
    • springboot web开发
    • springboot数据访问
    • springboot单元测试
    • springboot性能监控actuator
    • SpringBoot 原理解析
      • 需求分析
      • 1、Profile功能
        • 1、application-profile功能
        • 2、@Profile条件装配功能
        • 3、profile分组
      • SpringBoot 原理解析
      • SpringBoot启动过程
      • 2、Application Events and Listeners
      • 3、ApplicationRunner 与 CommandLineRunner
      • springboot实现方式
        • 1.实现ServletContextAware接口
        • 2.实现ServletContextListener接口
        • 3.@PostConstruct和static代码块
        • 4.实现CommandLineRunner接口
        • 5、springboot的启动类main方法体
        • 6、在servletcontext设置系统属性
    • spring.factories文件
    • springboot常用注解
    • springboot序列化
    • springboot整合swagger
    • Spring Boot 定制URL匹配规则的方法
    • springboot整合redisson分布式锁
    • springboot+线程池使用
    • springboot2应用中碰到的一些坑
    • SpringBoot面试题
  • redis

  • zookeeper

  • springcloud

  • dubbo

  • netty

  • springsecurity

  • mq消息中间件

  • shiro

  • beetle

  • 模板引擎

  • jpa

  • 数据结构与算法

  • 数据库知识与设计

  • gradle

  • maven

  • bus

  • 定时任务

  • docker

  • centos

  • 加解密

  • biz业务

  • pigx项目

  • 开源项目

  • 品达通用权限项目-黑马

  • 货币交易项目coin-尚学堂

  • php

  • backend
  • springboot
shollin
2021-06-08
目录

SpringBoot 原理解析

# 需求分析

我们有时候需要让项目在启动时提前加载相应的数据或者执行某个方法,比如初始化数据、加载数据字典到缓存当中、显示banner等等

# 1、Profile功能

为了方便多环境适配,springboot简化了profile功能。

# 1、application-profile功能

  • 默认配置文件 application.yaml;任何时候都会加载

  • 指定环境配置文件 application-{env}.yaml

  • 激活指定环境

  • 配置文件激活

  • 命令行激活:java -jar xxx.jar --spring.profiles.active=prod --person.name=haha

  • 修改配置文件的任意值,命令行优先

  • 默认配置与环境配置同时生效

  • 同名配置项,profile配置优先

# 2、@Profile条件装配功能

@Configuration(proxyBeanMethods = false)
@Profile("production")
public class ProductionConfiguration {

    // ...

}
1
2
3
4
5
6
7

# 3、profile分组

spring.profiles.group.production[0]=proddb
spring.profiles.group.production[1]=prodmq

使用:--spring.profiles.active=production  激活
1
2
3
4

# SpringBoot 原理解析

  • 1.在命令行中传入的参数

  • 2.SPRING_APPLICATION_JSON中的属性。SPRING_APPLICATION_JSON是以JSON格式配置在系统环境变量中。

  • 3.java:comp/env 中的JNDI属性。

  • 4.java的系统属性,可以通过System.getProperties()获得的内容。

  • 5.操作系统的环境变量

  • 6.通过random.*配置的随机属性

  • 7.位于当前应用jar包之外,针对不同{profile}环境的配置文件内容,例如application-{profile}.properties或者是YAML定义的配置文件。

  • 8.位于当前应用jar包之内,针对不同{profile}环境的配置文件内容,例如application-{profile}.properties或者是YAML定义的配置文件。

  • 9.位于当前应用jar包之外的application.properties和YAML配置内容。

  • 10.位于当前应用jar包之内的application.properties和YAML配置内容。

  • 11.在@Configuration注解修改的类中,通过@PropertySource注解定义的属性内容。

  • 12.应用默认属性,使用SpringApplication.setDefaultProperties定义的内容。

优先级按上面的顺序由高到低,数字越小优先级越高。

参考文档:

09、原理解析 · 语雀 (yuque.com)

# SpringBoot启动过程

  • 创建 SpringApplication

  • 保存一些信息。

  • 判定当前应用的类型。ClassUtils。Servlet

  • bootstrappers**:初始启动引导器(List):去spring.factories文件中找** org.springframework.boot.Bootstrapper

  • 找 ApplicationContextInitializer;去spring.factories****找 ApplicationContextInitializer

  • List<ApplicationContextInitializer<?>> initializers

  • 找 ApplicationListener ;应用监听器。去spring.factories****找 ApplicationListener

  • List<ApplicationListener<?>> listeners

  • 运行 SpringApplication

  • StopWatch

  • 记录应用的启动时间

  • **创建引导上下文(Context环境)**createBootstrapContext()

  • 获取到所有之前的 bootstrappers 挨个执行 intitialize() 来完成对引导启动器上下文环境设置

  • 让当前应用进入headless模式。java.awt.headless

  • 获取所有 RunListener**(运行监听器)【为了方便所有Listener进行事件感知】**

  • getSpringFactoriesInstances 去spring.factories****找 SpringApplicationRunListener.

  • 遍历 SpringApplicationRunListener 调用 starting 方法;

  • 相当于通知所有感兴趣系统正在启动过程的人,项目正在 starting。

  • 保存命令行参数;ApplicationArguments

  • 准备环境 prepareEnvironment();

  • 返回或者创建基础环境信息对象。StandardServletEnvironment

  • 配置环境信息对象。

  • 读取所有的配置源的配置属性值。

  • 绑定环境信息

  • 监听器调用 listener.environmentPrepared();通知所有的监听器当前环境准备完成

  • 创建IOC容器(createApplicationContext())

  • 根据项目类型(Servlet)创建容器,

  • 当前会创建 AnnotationConfigServletWebServerApplicationContext

  • 准备ApplicationContext IOC容器的基本信息 prepareContext()

  • 保存环境信息

  • IOC容器的后置处理流程。

  • 应用初始化器;applyInitializers;

  • 遍历所有的 ApplicationContextInitializer 。调用 initialize.。来对ioc容器进行初始化扩展功能

  • 遍历所有的 listener 调用 contextPrepared。EventPublishRunListenr;通知所有的监听器****contextPrepared

  • 所有的监听器 调用 contextLoaded。通知所有的监听器 contextLoaded;

  • **刷新IOC容器。**refreshContext

  • 创建容器中的所有组件(Spring注解)

  • 容器刷新完成后工作?afterRefresh

  • 所有监听 器 调用 listeners.started(context); 通知所有的监听器 started

  • **调用所有runners;**callRunners()

  • 获取容器中的 ApplicationRunner

  • 获取容器中的 CommandLineRunner

  • 合并所有runner并且按照@Order进行排序

  • 遍历所有的runner。调用 run 方法

  • 如果以上有异常,

  • 调用Listener 的 failed

  • 调用所有监听器的 running 方法 listeners.running(context); 通知所有的监听器 running

  • **running如果有问题。继续通知 failed 。**调用所有 Listener 的 **failed;**通知所有的监听器 failed

# 2、Application Events and Listeners

https://docs.spring.io/spring-boot/docs/current/reference/html/spring-boot-features.html#boot-features-application-events-and-listeners

ApplicationContextInitializer

ApplicationListener

SpringApplicationRunListener

# 3、ApplicationRunner 与 CommandLineRunner

# springboot实现方式

# 1.实现ServletContextAware接口

注意:该方法会在填充完普通Bean的属性,但是还没有进行Bean的初始化之前执行

Aware的意思是感知 ApplicationContextAware可以获得 ApplicationContext上下文资源 ServletContextAware可以获得ServletContext上下文资源 … 实现xxAware接口的子类,会覆盖对应的setXX()方法,从而可以获得Spring容器中的xx资源

/**
 * spring工具类 方便在非spring管理环境中获取bean
 * @author ruoyi
 */
@Component
public class SpringUtils implements ServletContextAware,ApplicationContextAware,BeanFactoryPostProcessor {
	
	/** Spring应用上下文环境 */
    private static ConfigurableListableBeanFactory beanFactory;

    private static ApplicationContext applicationContext;

    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException
    {
        SpringUtils.beanFactory = beanFactory;
    }

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException
    {
        SpringUtils.applicationContext = applicationContext;
    }

    /**
     * 获取对象
     *
     * @param name
     * @return Object 一个以所给名字注册的bean的实例
     * @throws org.springframework.beans.BeansException
     *
     */
    @SuppressWarnings("unchecked")
    public static <T> T getBean(String name) throws BeansException
    {
        return (T) beanFactory.getBean(name);
    }

    /**
     * 获取类型为requiredType的对象
     *
     * @param clz
     * @return
     * @throws org.springframework.beans.BeansException
     *
     */
    public static <T> T getBean(Class<T> clz) throws BeansException
    {
        T result = (T) beanFactory.getBean(clz);
        return result;
    }

    /**
     * 如果BeanFactory包含一个与所给名称匹配的bean定义,则返回true
     * @param name
     * @return boolean
     */
    public static boolean containsBean(String name)
    {
        return beanFactory.containsBean(name);
    }

    /**
     * 判断以给定名字注册的bean定义是一个singleton还是一个prototype。 如果与给定名字相应的bean定义没有被找到,将会抛出一个异常(NoSuchBeanDefinitionException)
     *
     * @param name
     * @return boolean
     * @throws org.springframework.beans.factory.NoSuchBeanDefinitionException
     *
     */
    public static boolean isSingleton(String name) throws NoSuchBeanDefinitionException
    {
        return beanFactory.isSingleton(name);
    }

    /**
     * @param name
     * @return Class 注册对象的类型
     * @throws org.springframework.beans.factory.NoSuchBeanDefinitionException
     */
    public static Class<?> getType(String name) throws NoSuchBeanDefinitionException
    {
        return beanFactory.getType(name);
    }

    /**
     * 如果给定的bean名字在bean定义中有别名,则返回这些别名
     *
     * @param name
     * @return
     * @throws org.springframework.beans.factory.NoSuchBeanDefinitionException
     *
     */
    public static String[] getAliases(String name) throws NoSuchBeanDefinitionException
    {
        return beanFactory.getAliases(name);
    }

    /**
     * 获取aop代理对象
     * 
     * @param invoker
     * @return
     */
    @SuppressWarnings("unchecked")
    public static <T> T getAopProxy(T invoker)
    {
        return (T) AopContext.currentProxy();
    }

    /**
     * 获取当前的环境配置,无配置返回null
     *
     * @return 当前的环境配置
     */
    public static String[] getActiveProfiles()
    {
        return applicationContext.getEnvironment().getActiveProfiles();
    }

    /**
     * 获取当前的环境配置,当有多个环境配置时,只获取第一个
     *
     * @return 当前的环境配置
     */
    public static String getActiveProfile()
    {
        final String[] activeProfiles = getActiveProfiles();
        return StringUtils.isNotEmpty(activeProfiles) ? activeProfiles[0] : null;
    }

    /**
     * 在填充普通bean属性之后但在初始化之前调用
     * 类似于initializingbean的afterpropertiesset或自定义init方法的回调
     *
     */
    @Override
    public void setServletContext(ServletContext servletContext) {
        System.out.println("setServletContext方法");
    }    
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141

# 2.实现ServletContextListener接口

/**
     * 在初始化Web应用程序中的任何过滤器或servlet之前,将通知所有servletContextListener上下文初始化。
     */
    @Override
    public void contextInitialized(ServletContextEvent sce) {
        //ServletContext servletContext = sce.getServletContext();
        System.out.println("执行contextInitialized方法");
    }
1
2
3
4
5
6
7
8

# 3.@PostConstruct和static代码块

  • 将要执行的方法所在的类交个spring容器扫描(@Component),并且在要执行的方法上添加@PostConstruct注解或者静态static代码块执行

  • 被@PostConstruct修饰的方法会在服务器加载Servlet的时候运行,并且只会被服务器调用一次,类似于Serclet的inti()方法。被@PostConstruct修饰的方法会在构造函数之后,init()方法之前运行。

  • @PreDestroy说明

    被@PreDestroy修饰的方法会在服务器卸载Servlet的时候运行,并且只会被服务器调用一次,类似于Servlet的destroy()方法。被@PreDestroy修饰的方法会在destroy()方法之后运行,在Servlet被彻底卸载之前。

    ———————————————— 版权声明:本文为CSDN博主「这辈子_安静的努力着」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。 原文链接:https://blog.csdn.net/qq_35868412/article/details/89085500

  • 这是最简单的方式。但是会影响服务提供,比如这个方法要执行五分钟 这五分钟之内是无法提供服务的,这个方法是在服务初始化后之前运行, 所以 此方法运行不结束,服务就无法初始化, 在这过程路也无法提供服务。

@Component
public class Test2 {
    //静态代码块会在依赖注入后自动执行,并优先执行
    static{
        System.out.println("---static--");
    }
    /**
     *  @Postcontruct’在依赖注入完成后自动调用
     */
    @PostConstruct
    public static void haha(){
        System.out.println("@Postcontruct’在依赖注入完成后自动调用");
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14

# 4.实现CommandLineRunner接口

  • 实现CommandLineRunner接口,@Order注解里面的参数是类执行的顺序,由小到大顺序。

  • 监听接口方式,启动服务,执行方式时仍然提供服务,服务初始化之后即表示所有的bean以及applicationCOntenxt已完成,执行方法。

@Component
//@Order(value=1)//有多个CommandLineRunner接口时可以指定执行顺序(小的先执行)
public class SettingConfig implements CommandLineRunner {

 	@Autowired
    ConfigRepository configRepository;
    @Autowired
    CacheService cacheService;
    
	/**
     * 用于指示bean包含在SpringApplication中时应运行的接口。可以定义多个applicationrunner bean
     * 在同一应用程序上下文中,可以使用有序接口或@order注释对其进行排序。
     */
    @Override
    public void run(String... strings) throws Exception {	
       System.err.println("执行数据初始化操作......");
        //将config数据。。放置redis
        List<Config> configs = configRepository.findAll();
        if(configs != null && !configs.isEmpty()){
            for(Config config : configs){
                String key = Constant.CONFIG_PREFIX+config.getKey();
                String val = config.getValue();

                cacheService.set(key, val);
            }
        }
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28

# 5、springboot的启动类main方法体

# 6、在servletcontext设置系统属性

/**
* 在ServletContext里存放部分数据
* @return
*/
@Bean
public ServletContextInitializer initializer() {
	return new ServletContextInitializer() {
		@Override
		public void onStartup(ServletContext servletContext) throws ServletException {
			servletContext.setAttribute("jsVer", "1.0");
		}
	};
}
1
2
3
4
5
6
7
8
9
10
11
12
13
#springboot
springboot性能监控actuator
spring.factories文件

← springboot性能监控actuator spring.factories文件→

最近更新
01
国际象棋
09-15
02
成语
09-15
03
自然拼读
09-15
更多文章>
Theme by Vdoing | Copyright © 2019-2023 zxpnet | 粤ICP备14079330号-1
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式