Spring Boot 入门

Spring Boot 入门

官方地址
你是否已经厌烦了创建一个web项目
1)配置web.xml,加载spring和spring mvc

2)配置数据库连接、配置spring事务

3)配置加载配置文件的读取,开启注解

4)配置日志文件

...

配置完成之后部署tomcat 调试,每次新建都要重复现有步骤

但是如果使用Spring Boot 你可以start
image.png

点击你选择的依赖,这里我们选择web
image.png

导入我们的环境,我们看它的目录结构
image.png

直接main 函数启动:
我们直接看关键信息
image.png

上面分别告诉你,启动文件使用哪一个,如果没有设置则使用默认的,也就是application.properties
下面是web容器的端口,默认使用的是tomcat,当然也可以方便的更换成其他容器undertow等等,而这些操作只需要简单的更换pom文件和更新properties文件

image.png
这样激活的就是application-local.properties文件
image.png
方便调试不同的环境
image.png
这样就更换的了web容器
image.png
参数配置

剩下的使用就跟spring 差别不大了
image.png
image.png

因为没有了配置文件,我们看看针对spring mvc的一些MethodResolver小技巧 如何配置
本身boot 为我们提供了生命周期的口子:WebMvcConfigurationSupport
image.png
image.png
image.png
这样同样就完成了我们的参数解析,常用的扩展在此声明周期函数中都可以找到
image.png

具体的使用大家可以参考开头官方文档,使用非常详细了,接下来我们看看加载流程:
从开始:
image.png

首先经过代理之后最终看到其目的是为了实例化SpringApplication这个类
image.png

我们看构造函数中核心的几个步骤:
image.png

首先是deduceWebApplicationType,它的目的是为了明确应用的类型是标准类型还是web类型环境,
通过对应环境的核心类进行判断:
image.png

接着是:setInitializers
它会去调用getSpringFactoriesInstances,getSpringFactoriesInstances委托给getSpringFactoriesInstances 去调用SpringFactoriesLoader.loadFactoryNames(type, classLoader)
image.png
loadFactoryNames的作用是:读取META-INF/spring.factories里面的配置文件 明确要实例化的组件
image.png
读取完成之后,开始实例化
image.png

ApplicationContextInitializer根据类文档,这个接口的主要功能是:
在Spring上下文被刷新之前进行初始化的操作。典型地比如在Web应用中,注册Property Sources或者是激活Profiles。Property Sources比较好理解,就是配置文件。Profiles是Spring为了在不同环境下(如DEV,TEST,PRODUCTION等),加载不同的配置项而抽象出来的一个实体。

紧接着开始设置监听器:
image.png
与上面的步骤相同,读取配置文件:
image.png

ApplicationListener是spring的事件接口,事件一套属于spring的观察者模式,咱们写个小例子:
定义一个event
image.png

定义响应者,当登录成功之后,我们缓存账户信息
image.png

mock 当登录之后,我们发一个事件,这样我登录的验证逻辑和登录成功之后要做的事情是分开的
image.png

紧接着需要做的事情就是,找到主main函数
image.png

我们看下,找的方法,略屌:
image.png
运行时异常的栈桢中获取 吊炸天
这样SpringApplication的构造方法就执行完毕了

紧接着执行run方法:
image.png


// 运行run方法
public ConfigurableApplicationContext run(String... args) { // 计时工具 StopWatch stopWatch = new StopWatch(); stopWatch.start(); ConfigurableApplicationContext context = null; Collection<SpringBootExceptionReporter> exceptionReporters = new ArrayList<>(); // 设置java.awt.headless系统属性为true - 没有图形化界面 configureHeadlessProperty(); // KEY 1 - 获取SpringApplicationRunListeners SpringApplicationRunListeners listeners = getRunListeners(args); // 发出开始执行的事件 listeners.starting(); try { ApplicationArguments applicationArguments = new DefaultApplicationArguments( args); // KEY 2 - 根据SpringApplicationRunListeners以及参数来准备环境 ConfigurableEnvironment environment = prepareEnvironment(listeners, applicationArguments); configureIgnoreBeanInfo(environment); // 准备Banner打印器 - 就是启动Spring Boot的时候打印在console上的ASCII艺术字体 Banner printedBanner = printBanner(environment); // KEY 3 - 创建Spring上下文 context = createApplicationContext(); // 准备异常报告器 exceptionReporters = getSpringFactoriesInstances( SpringBootExceptionReporter.class, new Class[] { ConfigurableApplicationContext.class }, context); // KEY 4 - Spring上下文前置处理 prepareContext(context, environment, listeners, applicationArguments, printedBanner); // KEY 5 - Spring上下文刷新 refreshContext(context); // KEY 6 - Spring上下文后置处理 afterRefresh(context, applicationArguments); // 发出结束执行的事件 listeners.finished(context, null); // 停止计时器 stopWatch.stop(); if (this.logStartupInfo) { new StartupInfoLogger(this.mainApplicationClass) .logStarted(getApplicationLog(), stopWatch); } return context; } catch (Throwable ex) { handleRunFailure(context, listeners, exceptionReporters, ex); throw new IllegalStateException(ex); } } 

从getRunListeners来看也是执行上面的流程读取配置文件实例化:
image.png

SpringApplicationRunListeners它主要是负责发布SpringApplicationEvent事件的,它会利用一个内部的ApplicationEventMulticaster在上下文实际被刷新之前对事件进行处理。至于具体的应用场景,后面用到的时候再来分析;
接下来的步骤配置环境,这里都做了域隔离
image.png
image.png
记得最开始的spring.profiles.active么,就是在这决定如何操作的
image.png
打印控制台最开始的banner信息

createApplicationContext创建上下文

protected ConfigurableApplicationContext createApplicationContext() { Class<?> contextClass = this.applicationContextClass; if (contextClass == null) { try { contextClass = Class.forName(this.webEnvironment ? DEFAULT_WEB_CONTEXT_CLASS : DEFAULT_CONTEXT_CLASS); } catch (ClassNotFoundException ex) { throw new IllegalStateException( "Unable create a default ApplicationContext, " + "please specify an ApplicationContextClass", ex); } } return (ConfigurableApplicationContext) BeanUtils.instantiate(contextClass); } // WEB应用的上下文类型 public static final String DEFAULT_WEB_CONTEXT_CLASS = "org.springframework.boot.context.embedded.AnnotationConfigEmbeddedWebApplicationContext"; 

上下文类图:
image.png

接下来做前置上文的操作:prepareContext

private void prepareContext(ConfigurableApplicationContext context, ConfigurableEnvironment environment, SpringApplicationRunListeners listeners, ApplicationArguments applicationArguments, Banner printedBanner) { // 将环境和上下文关联起来 context.setEnvironment(environment); // 为上下文配置Bean生成器以及资源加载器(如果它们非空) postProcessApplicationContext(context); // 调用初始化器 applyInitializers(context); // 触发Spring Boot启动过程的contextPrepared事件 listeners.contextPrepared(context); if (this.logStartupInfo) { logStartupInfo(context.getParent() == null); logStartupProfileInfo(context); } // 添加两个Spring Boot中的特殊单例Beans - springApplicationArguments以及springBootBanner context.getBeanFactory().registerSingleton("springApplicationArguments", applicationArguments); if (printedBanner != null) { context.getBeanFactory().registerSingleton("springBootBanner", printedBanner); } // 加载sources - 对于DemoApplication而言,这里的sources集合只包含了它一个class对象 Set<Object> sources = getSources(); Assert.notEmpty(sources, "Sources must not be empty"); // 加载动作 - 构造BeanDefinitionLoader并完成Bean定义的加载 load(context, sources.toArray(new Object[sources.size()])); // 触发Spring Boot启动过程的contextLoaded事件 listeners.contextLoaded(context); } 

配置Bean生成器以及资源加载器

protected void postProcessApplicationContext(ConfigurableApplicationContext context) { if (this.beanNameGenerator != null) { context.getBeanFactory().registerSingleton( AnnotationConfigUtils.CONFIGURATION_BEAN_NAME_GENERATOR, this.beanNameGenerator); } if (this.resourceLoader != null) { if (context instanceof GenericApplicationContext) { ((GenericApplicationContext) context) .setResourceLoader(this.resourceLoader); } if (context instanceof DefaultResourceLoader) { ((DefaultResourceLoader) context) .setClassLoader(this.resourceLoader.getClassLoader()); } } } 

接下来是经典的refreshContext
image.png

还有最后的callRunners,它的作用是整个容器ready的时候去做一些事情,例如以前大家一定使用过
image.png
在具体的 业务域去初始化一些全局的东西,这样不是很好

可以监听容器事件的同时,可以使用runners
image.png
这就大致完成了初始化

 

转载于:https://www.cnblogs.com/TestMa/p/10649052.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值