目录:
SpringBoot原理分析
SpringBoot自动配置
SpringBoot监听机制
Spring Boot启动流程分析
SpringBoot监控
SpringBoot项目部署
1、自动配置原理【难点非重点】
注意:注解大家务必会使用! Java 5 提供注解功能,Spring推出基于注解开发方式从配置文件转向全注解开发!
复习注解:
1、什么是注解?注解作用是什么?如何理解某一个注解?如何使用好注解?
注解就是一个标签,相当于胸牌,用于表示一定功能。注解是给JVM虚拟机看的。
怎么定义一个注解:Java5中,提供3个原注解来定义注解。
@Target(ElementType.TYPE) // 标识注解作用范围
@Retention(RetentionPolicy.RUNTIME) // 标识注解在什么时候有效 :源代码阶段 编译阶段 运行阶段
@Documented // 标识生成文档
所有的注解默认都有一个属性 value属性!
1.1 Condition 条件!
springboot工程启动的时候会根据你引入的起步依赖,默认加载一些配置类(@Configuration 注解修饰).
@Conditional注解可以添加在@Configuration、@Component、@Service等修饰的类上用于控制对应的Bean是否需要创建,或者添加在@Bean修饰的方法上用于控制方法对应的Bean是否需要创建。
@Conditional添加在@Configuration修饰的类上,用于控制该类和该类里面所有添加的@Bean方法对应的Bean是否需要创建。
Condition接口
/**
* context 上下文对象。用于获取环境,IOC容器,ClassLoader对象
* metadata 注解元对象。 可以用于获取注解定义的属性值
* 应用:导入通过注解值value指定坐标后创建Bean
* metadata.getAnnotationAttributes(ConditionOnClass.class.getName());
* //Class.getNume()获取全类名
* //ConditionOnClass 实现了Condition接口的注解
*/
public interface Condition {
boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata);
}
具体怎么做?
问题:
NoSuchBeanDefinitionException: No bean named 'redisTemplate' available
证明我们的springIOC容器中没有这个对象,因此我们思路:
①没有导入redis的起步依赖,(导入即可解决)
②导入了但是没下载全(仓库删除该包,从新下载)
问题:为什么我们导入redis的起步依赖就可以把redisTemplate注入到SpringIOC容器?
@Conditional 配合 Condition 接口
1、我们编写一个类实现 Condition 接口
2、需要使用@Conditional 注解
具体步骤
①配置注解:
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Conditional(ClassCondition.class)
public @interface ConditionOnClass {
String[] value();
}
②编写一个类实现Condition
public class ClassCondition implements Condition {
/**
* @param context 上下文对象: 用于获取环境/IOC容器/classloader对象
* @param metadata 注解原对象: 可以用于获取注解定义的属性值
*/
public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
//获取注解属性值 value
Map<String, Object> map
= metadata.getAnnotationAttributes(ConditionOnClass.class.getName());
String[] value = (String[]) map.get("value");
try {
for (String className : value) {
Class<?> aClass = Class.forName(className);
}
return true;
} catch (ClassNotFoundException e) {
e.printStackTrace();
return false;
}
}
}
③写一个配置类去实列化User对象
@Configuration
public class UserConfig {
@Bean
@ConditionOnClass("org.springframework.web.bind.annotation.RequestBody")
public User user(){
return new User();
}
}
④在引导类中测试是否可以拿到User对象
@SpringBootApplication
public class SpringbootQuick2Application {
public static void main(String[] args) {
ConfigurableApplicationContext context
= SpringApplication.run(SpringbootQuick2Application.class, args);
Object user = context.getBean("user");
System.out.println(user);
}
}
面试问题:
springboot 如何实现自动配置?
1、Condition 机制,条件机制(当我们触发某一个条件做一些事情)
2、springboot工程提供给用户两个操作接口:application.yml,pom.xml (启动器,起步依赖)
3、 举例子:spring-boot-stater-data-redis 启动器加入我们pom文件中,此时启动springboot项目这个时候
springboot就会通过Condition 机制 实例化我们RedisTemolate 模板 。我们就可以在程序中直接使用。
特殊注解:@Conditional 注解核心!(当我们条件满足做事情,不满足就不做) 条件取决于注解属性 value , Condition 接口。
@ConditionalOnClass
@ConditionalOnMissBean
@ConditionalOnProperty
1.2 切换内置服务器
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jetty</artifactId>
</dependency>
Condition-小结
- 自定义条件:
①定义条件类:自定义类实现Condition接口, 重写matches方法, 在matchnes方法中进行逻辑判断, 返回boolean值。matches方法两个参数:
context:上下文对象, 可以获取属性值, 获取类加载器, 获取BeanFactor y等。
metadata:元数据对象, 用于获取注解属性。
②判断条件:在初始化Bean时, 使用@Conditional(条件类.class) 注解 - Spring Boot提供的常用条件注解:
ConditionalOnProperty:判断配置文件中是否有对应属性和值才初始化Bean
ConditionalOnClass:判断环境中是否有对应字节码文件才初始化Bean
ConditionalOnMissingBean:判断环境中没有对应Bean才初始化Bean
springBoot 如何切换内置的web服务器
Spring Boot的web环境中默认使用tomcat作为内置服务器, 其实Spring Boot提供了4中内置服务器供我们选择, 我们可以很方便的进行切换。
<dependency>
<groupId>org.springframework.boot</groupId>
<artifact Id>spring-boot-starter-web</artifact Id>
<!--排除tomcat依赖-->
<exclusions>
<exclusion>
<artifactId>spring-boot-starter-tomcat</artifactId>
<groupId>org.springframework.boot</groupId>
</exclusion>
</exclusions>
</dependency>
<!--引入jetty的-->
<dependency>
<artifactId>spring-boot-starter-jetty</artifactId>
<groupId>org.springframework.boot</groupId>
</dependency>
1.3 @EnableXXX注解原理
SpringBoot中提供了很多Enable开头的注解, 这些注解都是用于动态启用某些功能的。而其底层原理是使用@Import注解导入一些配置类, 实现Bean的动态加载。
EnableXXX 使能够 (翻译为:开启XXX ,让XXX功能生效)
spring :
@ComponentScan(basePackage="com.itheima")
<context:component-scan basepackage="com.itheima">
springBoot : 经常引入第三方的依赖
@Import 注解: 解决 引入多个配置文件的问题
<import name="test1" class=".....Test1"/>
1.4 @Import 注解
@Enable*底层依赖于@Import注解导入一些类, 使用@Import导入的类会被Spring加载到IOC容器中。而@Import提供4中用法:
①导入Bed
②导入配置类
③导入Import Selector实现类。一般用于加载配置文件中的类
④导入Import Bean Definition Registrar实现类
1.5 @EnableAutoConfiguration开启自动配置
1.6 spring自动配置原理
●@EnableAutoConfiguration注解内部使用@Import(AutoConfiguration Import Selector.class) 来加载配置类。
●配置文件位置:META-INF/spring.factories, 该配置文件中定义了大量的配置类, 当SpringBoot应用启动时, 会自动加载这些配置类, 初始化Bean
●并不是所有的Bean都会被初始化, 在配置类中使用Condition来加载满足条件的Bean
1.7 自定义starter【掌握-模仿-mybatis启动器】
1.7.1 分析
1. 分别创建 redis-spring-boot-autoconfigure 模块和 redis-spring-boot-starter 模块
2. 分别删除测试依赖和测试类
3. 在redis-spring-boot-autoconfigure模块:
①创建配置类 RedisConfig (@Configuration @Bean)
这里需要用condition进行条件匹配
②创建实例类 RedisProperties (@ConfigurationProperties(prefix = "redis"))
jedis连接至少两个参数: 主机 端口
③创建META-INF/spring.factories配置类信息
这里配置键值对 EnableAutoConfiguration 指向我们自己写的配置类 RedisConfig
4. 在 redis-spring-boot-starter 模块:
①导入 redis-spring-boot-autoconfigure 依赖
1.7.2代码
(1) RedisConfig
package com.itheima.autoconfigure;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import redis.clients.jedis.Jedis;
@Configuration
@EnableConfigurationProperties(RedisProperties.class)
@ConditionalOnClass(Jedis.class)
public class RedisConfig {
@Bean
@ConditionalOnMissingBean(name = "Jedis")
public Jedis jedis(RedisProperties properties){
return new Jedis(properties.host,properties.port);
}
}
(2) RedisProperties
package com.itheima.autoconfigure;
import org.springframework.boot.context.properties.ConfigurationProperties;
@ConfigurationProperties(prefix = "redis")
public class RedisProperties {
String host = "localhost";
int port = 6379;
public String getHost() {
return host;
}
public void setHost(String host) {
this.host = host;
}
public int getPort() {
return port;
}
public void setPort(int port) {
this.port = port;
}
}
(3) spring.factories
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
com.itheima.autoconfigure.RedisConfig
2、事件监听【了解】
JavaWeb 种三个核心组件:Servlet 、 Filter 、 Listener(监听器)
Spring Boot的监听机制, 其实是对Java提供的事件监听机制的封装。Java中的事件监听机制定义了以下几个角色:
①事件:Event, 继承java.util.EventObject类的对象
②事件源:Source, 任意对象Object
③监听器:Listener, 实现java.util.EventListener接口的对象
Spring Boot在项目启动时, 会对几个监听器进行回调, 我们可以实现这些监听器接口, 在项目启动时完成一些操作。
ApplicationContext Initializer、SpringApplicationRunListener、CommandLineRunner、ApplicationRunner
监听器应用:ContextLoaderListener : 监听web服务器启动,加载spring配置文件,产生spring IOC 容器 。
1、CommandLineRunner接口 :
我们实现了这个接口,重写它的run方法,当我们springboot项目完全启动成功后执行当前run方法!
应用场景: 缓存预热。(项目一旦启动成功,我们就从数据库中取出需要加载到缓存的数据。就在这个run方法中做就可以了)
2、ApplicationRunner 接口:
我们实现了这个接口,重写它的run方法,当我们springboot项目完全启动成功后执行当前run方法!
应用场景: 缓存预热。(项目一旦启动成功,我们就从数据库中取出需要加载到缓存的数据。就在这个run方法中做就可以了)
3、SpringApplicationRunListener 接口:
定义一个类实现SpringApplicationRunListener 接口:
重写springboot整个生命周期方法
俩个参数 (不能使用自动注入@Component):
SpringApplication : 项目启动时的事件源,可以产生很多个不同的生命周期相关事件
String[] : 数组
Listener for the {@link SpringApplication} {@code run} method.
{@link SpringApplicationRunListener}s are loaded via the {@link SpringFactoriesLoader}
and should declare a public constructor that accepts a {@link SpringApplication}
instance and a {@code String[]} of arguments. A new
{@link SpringApplicationRunListener} instance will be created for each run.
4、ApplicationContextInitializer 接口
springboot 项目启动中。。。或调用该接口方法
3、流程分析【了解】
掌握一个技能: 源代码debug 调试 看源码必备神器。
-
springboot启动两个过程:
run方法 【对用户】
-
run方法的背后 -->初始化
-->准备springIOC
4、监控【了解】
SpringBoot自带监控功能Actuator, 可以帮助实现对程序内部运行情况监控, 比如监控状况、Bean加载情况、配置属性、日志信息等。
监控思想:尽早项目中存在问题-bug,便于我们项目长久运行!
1、引入监控起步依赖 spring-boot-starter-actuator
<dependency>
<groupld>org.springframework.boot</groupld>
<artifactld>spring-boot-starter-actuator</artifactld>
</dependency>
2、项目启动提供一个地址 :http://localhost:8080/actuator
3、开启功能:查看所有监控健康信息
配置项怎么知道有哪些:
4.2 监控的图形化界面使用
- Spring Boot Admin是一个开源社区项目, 用于管理和监控SpringBoot应用程序。
- Spring Boot Admin有两个角色, 客户端(Client) 和服务端(Server) 。
- 应用程序作为Spring Boot Admin Client向为Spring Boot Admin Server注册
- Spring Boot Admin Server的UI界面将Spring Boot Admin Client的Actuator Endpoint上的一些监控信息。
(1) admin-server模块:
- 创建admin-server模块
- 导入依赖坐标admin-starter-server
- 在引导类上开启监控功能@EnableAdminServer
- application.properties文件
server.port=9000
(2)admin-clien模块:
- 创建admin-clien模块
- 导入依赖坐标admin-starter-clien
- 配置相关信息: server 地址等
- 启动server和client服务,访问server
- application.properties文件