032:SpringBoot大体流程源码分析
- 1 SpringBoot快速开发底层实现原理
- 2 SpringBoot去除XML,采用注解方式原理
- 3 SpringBoot内置Tomcat服务器原理
- 4 SpringBootStarter基本思想介绍
- 5 SpringBoot自定义Starter插件01
- 6 SpringBoot自定义Starter插件02
1 SpringBoot快速开发底层实现原理
课程内容:
1.SpringBoot底层设计原理与思想
2.如何自定义SpringBootStarter
3.模拟手写SpringBoot核心思想
SpringBoot核心理念:
- 能够实现帮助开发者快速整合第三方框架(Spring、Mybatis、Hibernate)
原理:Maven依赖封装整合和自定义starter(springboot快速整合第三方框架依赖spring-boot-starter-xxx)。
2 SpringBoot去除XML,采用注解方式原理
- 完全去除xml配置,采用注解配置
原理:SpringBoot其实根据Spring体系原生的注解实现包装。
@SpringBootApplication封装@Configuration目的,方便开发者在启动类中main函数下面写@Bean将第三方依赖注入到ioc容器中。
3 SpringBoot内置Tomcat服务器原理
3.不需要外部容器,内嵌入服务器(tomcat)
原理:Java语言创建tomcat服务器,然后将本地class文件交给tomcat加载。
案例:注解方式启动SpringMVC将SpringMVC交给内部tomcat运行。
引入依赖
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.0.4.RELEASE</version>
<scope>compile</scope>
</dependency>
<!-- https://mvnrepository.com/artifact/javax.servlet/javax.servlet-api -->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.1.0</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.apache.tomcat.embed</groupId>
<artifactId>tomcat-embed-core</artifactId>
<version>8.5.28</version>
</dependency>
<!-- Tomcat对jsp支持 -->
<dependency>
<groupId>org.apache.tomcat</groupId>
<artifactId>tomcat-jasper</artifactId>
<version>8.5.16</version>
</dependency>
</dependencies>
相关代码
@EnableWebMvc
@Configuration
@ComponentScan("com.mayikt.controller")
public class SpringMvcConfig {
}
@RestController
public class IndexController {
//@RestController 等同于@Controller+@ResponseBody
@RequestMapping("/")
public String index() {
return "mayikt";
}
}
public class WebInitializer implements WebApplicationInitializer {
@Override
public void onStartup(javax.servlet.ServletContext servletContext) throws ServletException {
// 1. 创建SpringMVC容器
AnnotationConfigWebApplicationContext app = new AnnotationConfigWebApplicationContext();
// 2. 注册我们的配置文件
app.register(SpringMvcConfig.class);
// 注册我们的
DispatcherServlet dispatcherServlet = new DispatcherServlet(app);
ServletRegistration.Dynamic dynamic = servletContext.addServlet("dispatcherServlet", dispatcherServlet);
dynamic.addMapping("/");
dynamic.setLoadOnStartup(1);// 最优先启动
}
}
public class TomcatTest {
public static void main(String[] args) throws LifecycleException, ServletException {
//创建Tomcat服务器
Tomcat tomcatServer = new Tomcat();
//指定端口号
tomcatServer.setPort(9090);
//读取项目路径
StandardContext ctx = (StandardContext) tomcatServer.addWebapp("/", new File("src/main").getAbsolutePath());
//禁止重新载入
ctx.setReloadable(false);
//class文件读取地址
File additionWebInfClasses = new File("target/classes");
//创建webroot
WebResourceRoot resources = new StandardRoot(ctx);
//tomcat内部读取class执行
resources.addPreResources(new DirResourceSet(resources, "/target/classes", additionWebInfClasses.getAbsolutePath(), "/"));
tomcatServer.start();
//异步等待请求执行
tomcatServer.getServer().await();
}
}
运行结果:
4 SpringBootStarter基本思想介绍
Starter是Spring Boot中的一个非常重要的概念,Starter相当于模块,它能将模块所需的依赖整合起来并对模块内的Bean根据环境(条件)进行自动配置。使用者只需要依赖相应功能的Starter,无需做过多的配置和依赖,Spring Boot就能自动扫描并加载相应的模块。
例如,在Maven的依赖中加入spring-boot-starter-web就能使项目支持Spring MVC,并且Spring Boot还为我们做了很多默认配置,无需再依赖spring-web、spring-webmvc等相关包及做相关配置就能够立即使用起来。
Starter其实就是SpringBoot对第三方常用框架组件的命名方式。
官方命名格式为: spring-boot-starter-{name}
非官方建议命名格式:{name}-spring-boot- starter
5 SpringBoot自定义Starter插件01
假设开发一个框架解决token幂等问题,支持springboot版本,需要配置redis连接
构建自定义starter插件:token-redis-spring-boot-starter
引入maven依赖
<!-- springboot-parent -->
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.0.0.RELEASE</version>
</parent>
<dependencies>
<!-- Compile dependencies -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-autoconfigure</artifactId>
</dependency>
<!-- 能够让我们编写的配置文件在 其他人引用的时候有一定提示-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
</dependency>
</dependencies>
相关代码
@ConfigurationProperties(prefix = "mayikt")
public class TokenProperties {
private String tokenRedisHost;
private String tokenRedisPwd;
// mayikt.tokenRedisHost 写法错误
// mayikt.tokenRedisPwd
/*
tokenRedisHost=token-redis-host
mayikt.token-redis-host
定义配置文件的key的时候没有大写 都是为小写
*/
public void setTokenRedisHost(String tokenRedisHost) {
this.tokenRedisHost = tokenRedisHost;
}
public void setTokenRedisPwd(String tokenRedisPwd) {
this.tokenRedisPwd = tokenRedisPwd;
}
public String getTokenRedisHost() {
return tokenRedisHost;
}
public String getTokenRedisPwd() {
return tokenRedisPwd;
}
}
@Configuration
@EnableConfigurationProperties(TokenProperties.class)
public class TokenAutoConfiguration {
@Bean
public TokenService tokenService(){
return new TokenService();
}
}
public class TokenService {
@Autowired
private TokenProperties tokenProperties;
public String getToken() {
System.out.println("模拟生成token");
return tokenProperties.getTokenRedisHost() + "," + tokenProperties.getTokenRedisPwd();
}
}
6 SpringBoot自定义Starter插件02
- 在resource目录下新建META-INF/spring.factories文件,内容:org.springframework.boot.autoconfigure.EnableAutoConfiguration=com.mayikt.config.TokenAutoConfiguration(spring容器在启动的时候默认读取该文件内容)。
- 将该jar包打入maven仓库中,项目同级控制台输入命令: mvn clean install
新建项目test_springboot测试打入的jar包
引入maven依赖
<!-- springboot-parent -->
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.0.0.RELEASE</version>
</parent>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>com.mayikt</groupId>
<artifactId>token-redis-spring-boot-starter</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
</dependencies>
application.yml
mayikt:
token-redis-host: 127.0.0.1
token-redis-pwd: 123456
启动测试类
@RestController
@SpringBootApplication
public class IndexController {
@Autowired
private TokenService tokenService;
@RequestMapping(value = "/token")
private String getToken(){
return tokenService.getToken();
}
public static void main(String[] args) {
SpringApplication.run(IndexController.class);
}
}
测试结果: