| 目录 | |
|---|---|
| Java之Spring Boot入门到精通【IDEA版】(一篇文章精通系列)【上】 | |
| Java之Spring Boot入门到精通【IDEA版】SpringBoot整合其他框架【Junit,Redis,MyBatis】(一篇文章精通系列)【中】 | |
| Java之Spring Boot入门到精通【IDEA版】SpringBoot原理分析,SpringBoot监控(一篇文章精通系列)【下】 |
- 一、SpringBoot自动配置
- 1、Condition(自定义条件)
- (1)搭建工程
- (2)获取Bean,redisTemplate
- (3)引入redis的依赖
- (4)在Spring的IOC容器中有一个User的Bean,
- 1)创建User相关内容
- 2)现要求:导入Jedis坐标后,加载该Bean,没导入,则不加载
- 2、Condition(条件)动态实现
- (1)创建ConditionOnClass (自定义注解)
- (2)修改UserConfig
- (3)使用导入的指定坐标
- (4)判断其他的坐标
- (5)使用自带的ConditionalOnProperty判断
- 3、切换内置web服务器
- (1)修改pom.xml文件引入web依赖
- (2)切换内置服务器
- 1)切换到jetty
- 4、`@Enable*` 注解
- (1)演示不能获取第三方jar当中 Bean
- 1)创建模块
- (2)获取第三方jar
- 1)第一种实现使用第三方的jar(使用`@ComponentScan`扫描cn.itbluebox.config)
- 2)第二种实现使用第三方的jar(使用`@import`注解,加载类)
- 3)第三种实现使用第三方的jar(可以对import注解进行封装)
- 5、`@lmport`注解
- (1)导入`Bean`
- (2)导入配置类
- (3)导入`importSelector`实现类。一般用于加载配置文件中的类
- (4)导入`importBeanDefinitionRegistrar`实现类。
- 6、`@EnableAutoConfiguration`注解
- 7、自定义starter步骤分析
- (1)创建`redis-spring-boot-autoconfigure`模块
- (2)创建`redis-spring-boot-starter`模块,依赖`redis-spring-boot-autoconfigure`的模块
- (3)修改创建好的两个模块对其进行瘦身
- 1)修改redis-spring-boot-starter当中的内容对其进行瘦身
- 2)修改redis-spring-boot-autoconfigure对其进行瘦身
- (3)在`redis-spring-boot-autoconfigure`模块中初始化Jedis的Bean。并定义`meta-INF/spring.factories`文件
- 1)创建RedisAutoConfiguration
- 2)创建RedisProperties
- 3)完善RedisAutoConfiguration
- 4)创建spring.factories
- (4)在测试模块中引入自定义的`redis-starter`依赖,测试获取Jedis的Bean,操作redis。
- (5)操作上述获取到的Jedis
- (6)编写配置文件设置redis的属性
- 1)设置端口号
- 2)在RedisAutoConfiguration上设置一些条件
- 二、SpringBoot监听机制
- 1、Java的监听机制
- 2、SpringBoot 监听机制
- 3、代码演示
- (1)创建模块
- (2)创建对应的监听对象
- (3)运行测试
- (4)运行测试而MySpringApplicationRunListener和MyApplicationContextInitializer的执行需要设置配置文件
- 1)MyApplicationContextInitializer
- 2)MySpringApplicationRunListener
- 三、SpringBoot启动流程分析
- 1、SpringBoot启动流程图
- 四、SpringBoot监控
- 1、创建工程
- 1)创建模块
- 2)通过上述方式已经引入了依赖
- 2、访问`http://localhost:8080/acruator`
- 3、设置开启健康
- 4、设置引入redis
- 5、监控的其他使用
- 1)actuator开启所有endpoint
- 2)我们来使用一些比较常用的
- 01)[http://localhost:8080/actuator/beans](http://localhost:8080/actuator/beans)
- 02)[http://localhost:8080/actuator/mappings](http://localhost:8080/actuator/mappings)
- 6、SpringBoot 监控-Spring Boot Admin(图形化查看监控信息)
- (1)admin-server
- 1)创建`admin-server`模块
- 2)导入依赖坐标`admin-starter-server`
- 3)在引导类上启用监控功能`@EnableAdminServer`
- 4)修改端口号
- (2)admin-client
- 1)创建admin-client模块
- 2)导入依赖坐标admin-starter-client
- 3)配置相关信息:server地址等
- 4)启动server和client服务,访问server
- 1>启动server
- 2> 启动client
- 3>访问[http://localhost:9000/applications](http://localhost:9000/applications)
- 4>性能
- 5>环境电脑的环境和配置信息
- 6>类信息
- 7>配置属性
- 8>计划任务
- 9>JVM
- 10>映射
- 5)IDEA的
Condition是在Spring 4.0增加的条件判断功能,通过这个可以功能可以实现选择性的创建Bear操作。
SpringBoot是如何知道要创建哪个Bean的?比如SpringBoot是如何知道要创建RedisTemplate的?
package cn.itbluebox.springbootcondition;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ConfigurableApplicationContext;
@SpringBootApplication
public class SpringbootConditionApplication {
public static void main(String[] args) {
//启动SpringBoot的应用,返回Spring的IOC容器
ConfigurableApplicationContext context
= SpringApplication.run(SpringbootConditionApplication.class, args);
//1、获取Bean,redisTemplate
Object bean = context.getBean("redisTemplate");
System.out.println(bean);
}
}
- 运行测试
运行报错因为,没有bean是叫redisTemplate
org.springframework.boot spring-boot-starter-data-redis
- 重新运行测试
- 创建UserConfig配置类
package cn.itbluebox.springbootcondition.config;
import cn.itbluebox.springbootcondition.domain.User;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class UserConfig {
@Bean
public User user(){
return new User();
}
}
- 获取刚刚创建的User,修改SpringbootConditionApplication
package cn.itbluebox.springbootcondition;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ConfigurableApplicationContext;
@SpringBootApplication
public class SpringbootConditionApplication {
public static void main(String[] args) {
//启动SpringBoot的应用,返回Spring的IOC容器
ConfigurableApplicationContext context
= SpringApplication.run(SpringbootConditionApplication.class, args);
Object user = context.getBean("user");
System.out.println(user);
}
}
- 运行测试
- 创建ClassCondition
package cn.itbluebox.springbootcondition.condtion;
import org.springframework.context.annotation.Condition;
import org.springframework.context.annotation.ConditionContext;
import org.springframework.core.type.AnnotatedTypemetadata;
public class ClassCondition implements Condition {
@Override
public boolean matches(ConditionContext context, AnnotatedTypemetadata metadata) {
return false;
}
}
- 修改UserConfig
现在这ClassCondition返回的是false所以不会创建user对应的Bean,只有返回true才会创建user对应的bean
package cn.itbluebox.springbootcondition.config;
import cn.itbluebox.springbootcondition.condtion.ClassCondition;
import cn.itbluebox.springbootcondition.domain.User;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Conditional;
import org.springframework.context.annotation.Configuration;
@Configuration
public class UserConfig {
@Bean
@Conditional(ClassCondition.class)//现在这ClassCondition返回的是false所以不会创建user对应的Bean
public User user(){
return new User();
}
}
-
运行测试
-
运行报错,没有找到user对应的Bean
-
修改ClassCondition将返回值修改为true
package cn.itbluebox.springbootcondition.condtion;
import org.springframework.context.annotation.Condition;
import org.springframework.context.annotation.ConditionContext;
import org.springframework.core.type.AnnotatedTypemetadata;
public class ClassCondition implements Condition {
@Override
public boolean matches(ConditionContext context, AnnotatedTypemetadata metadata) {
return true;
}
}
-
运行测试
user对应的Bean创建成功
-
引入Jedis坐标
redis.clients jedis
- 完成需求继续修改ClassCondition
package cn.itbluebox.springbootcondition.condtion;
import org.springframework.context.annotation.Condition;
import org.springframework.context.annotation.ConditionContext;
import org.springframework.core.type.AnnotatedTypemetadata;
public class ClassCondition implements Condition {
@Override
public boolean matches(ConditionContext context, AnnotatedTypemetadata metadata) {
//1、需求:导入Jedis坐标后,加载该Bean
//2、思路:判断redis.clients.jedis.Jedis.class 文件是否存在
boolean flag = true;
try {
//如果forName可以加载到对应Jedis字节码那么说明引入了Jedis的依赖
Class> cls = Class.forName("redis.clients.jedis.Jedis");
} catch (ClassNotFoundException e) {
flag = false;
e.printStackTrace();
}
return flag;
}
}
- 运行测试
- 可以获取到因为,引入了Jedis依赖
- 删除Jedis的依赖
- 再次运行
- 运行报错,并且没有创建user对应的bean
- 将类的判断定义为动态的。判断哪个字节码文件存在可以动态指定。
package cn.itbluebox.springbootcondition.condtion;
import org.springframework.context.annotation.Conditional;
import java.lang.annotation.*;
@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@documented
@Conditional(ClassCondition.class)
public @interface ConditionOnClass {
String[] value();
}
(2)修改UserConfig
package cn.itbluebox.springbootcondition.config;
import cn.itbluebox.springbootcondition.condtion.ClassCondition;
import cn.itbluebox.springbootcondition.condtion.ConditionOnClass;
import cn.itbluebox.springbootcondition.domain.User;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Conditional;
import org.springframework.context.annotation.Configuration;
@Configuration
public class UserConfig {
@Bean
// @Conditional(ClassCondition.class)//现在这ClassCondition返回的是false所以不会创建user对应的Bean
@ConditionOnClass("redis.clients.jedis.Jedis")
public User user(){
return new User();
}
}
- 运行测试
- 修改ClassCondition
package cn.itbluebox.springbootcondition.condtion;
import org.springframework.context.annotation.Condition;
import org.springframework.context.annotation.ConditionContext;
import org.springframework.core.type.AnnotatedTypemetadata;
import java.util.Map;
public class ClassCondition implements Condition {
@Override
public boolean matches(ConditionContext context, AnnotatedTypemetadata metadata) {
//需求:导入通过注解属性值value指定的坐标
//获取注解属性值 value
Map map = metadata.getAnnotationAttributes(ConditionOnClass.class.getName());
//System.out.println(map);
String[] value = (String[])map.get("value");
boolean flag = true;
try {
for(String className : value){
//如果forName可以加载到对应Jedis字节码那么说明引入了Jedis的依赖
Class> cls = Class.forName(className);
}
} catch (ClassNotFoundException e) {
flag = false;
e.printStackTrace();
}
return flag;
}
}
- 运行测试
- 修改pom.xml
com.alibaba fastjson 1.2.4
- 修改UserConfig
- 使用User对象必须引入fastjson的坐标
package cn.itbluebox.springbootcondition.config;
import cn.itbluebox.springbootcondition.condtion.ConditionOnClass;
import cn.itbluebox.springbootcondition.domain.User;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class UserConfig {
@Bean
// @Conditional(ClassCondition.class)//现在这ClassCondition返回的是false所以不会创建user对应的Bean
@ConditionOnClass("com.alibaba.fastjson.JSON")
public User user(){
return new User();
}
}
- 运行测试
- 查询成功
- 删除依赖
- 修改UserConfig
@Bean
@ConditionalOnProperty(name = "it",havingValue = "bluebox")
public User user2(){
return new User();
}
- 修改SpringbootConditionApplication
package cn.itbluebox.springbootcondition;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ConfigurableApplicationContext;
@SpringBootApplication
public class SpringbootConditionApplication {
public static void main(String[] args) {
//启动SpringBoot的应用,返回Spring的IOC容器
ConfigurableApplicationContext context
= SpringApplication.run(SpringbootConditionApplication.class, args);
Object user = context.getBean("user2");
System.out.println(user);
}
}
- 运行测试
获取不到,因为配置文件当中没有对应键值对 - 完善application.properties
it=bluebox
- 运行测试
SpringBoot提供的常用条件注解:
- ConditionalOnProperty:判断配置文件中是否有对应属性和值才初始化Bean
- ConditionalOnClass:判断环境中是否有对应字节码文件才初始化Bean
- ConditionalOnMissingBean:判断环境中没有对应Bean才初始化Bean
SpringBoot的web环境中默认使用tomcat作为内置服务器,
其实SpringBoot提供了4中内置服务器供我们选择,我们可以很方便的进行切换。
- 之前我们在启动项目的时候项目直接启动并运行完就结束了,没有Tomcat的日志信息输出
org.springframework.boot spring-boot-starter-web
-
运行测试
-
启动并一直运行并输出对应Tomcat的日志信息
-
分析一下spring-boot-starter-web的依赖情况
我们可以找到对应的Tomcat
-
排除Tomcat的依赖
自动的排除了对应的依赖
在上面我们在web当中排除了对应的Tomcat的依赖
1)切换到jetty- 修改pom.xml
org.springframework.boot spring-boot-starter-web spring-boot-starter-tomcat org.springframework.boot spring-boot-starter-jetty org.springframework.boot
- 重新运行
- 切换成功
SpringBoot中提供了很多Enable开头的注解,这些注解都是用于动态启用某些功能的。
而其底层原理是使用@lmport注解导入一些配置类,实现Bean的动态加载。
- 创建模块一
- 修改SpringbootEnableApplication
package cn.itbluebox.springbootenable;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ConfigurableApplicationContext;
@SpringBootApplication
public class SpringbootEnableApplication {
public static void main(String[] args) {
ConfigurableApplicationContext context = SpringApplication.run(SpringbootEnableApplication.class, args);
//获取Bean
Object user = context.getBean("user");
System.out.println(user);
}
}
- 创建模块二
- 修改springboot-enable-other当中的pom.xml删除一些现在用不上的依赖
- 删除springboot-enable-other现阶段用不上的类
- 编写配置类
package cn.itbluebox.config;
import cn.itbluebox.domain.User;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class UserConfig {
@Bean
public User user(){
return new User();
}
}
(2)获取第三方jar
1)第一种实现使用第三方的jar(使用@ComponentScan扫描cn.itbluebox.config)
在springboot-enable当的pom.xml添加springboot-enable-other的对应的User的依赖
cn.itbluebox springboot-enable-other 0.0.1-SNAPSHOT
- 运行测试springboot-enable当中的SpringbootEnableApplication
无法获取到user
所以光是引入其他工程的依赖是无法获取到其他工程的Bean
SpringbootEnableApplication上使用@ComponentScan("cn.itbluebox.config")需要扫描对应配置类所在的包 - 修改springboot-enable当中的SpringbootEnableApplication
package cn.itbluebox.springbootenable;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
@SpringBootApplication
@ComponentScan("cn.itbluebox.config")
public class SpringbootEnableApplication {
public static void main(String[] args) {
ConfigurableApplicationContext context = SpringApplication.run(SpringbootEnableApplication.class, args);
//获取Bean
Object user = context.getBean("user");
System.out.println(user);
}
}
运行测试
运行成功
- 修改SpringbootEnableApplication
package cn.itbluebox.springbootenable;
import cn.itbluebox.config.UserConfig;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.import;
@SpringBootApplication
//@ComponentScan("cn.itbluebox.config")
@import(UserConfig.class)
public class SpringbootEnableApplication {
public static void main(String[] args) {
ConfigurableApplicationContext context = SpringApplication.run(SpringbootEnableApplication.class, args);
//获取Bean
Object user = context.getBean("user");
System.out.println(user);
}
}
- 运行测试
在第三的springboot-enable-other当中提供对应的功能
- 创建EnableUser
package cn.itbluebox.config;
import org.springframework.context.annotation.import;
import java.lang.annotation.*;
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@documented
@import(UserConfig.class)
public @interface EnableUser {
}
- 修改springboot-enable当中的SpringbootEnableApplication
package cn.itbluebox.springbootenable;
import cn.itbluebox.config.EnableUser;
import cn.itbluebox.config.UserConfig;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.import;
@SpringBootApplication
//@ComponentScan("cn.itbluebox.config")
//@import(UserConfig.class)
@EnableUser
public class SpringbootEnableApplication {
public static void main(String[] args) {
ConfigurableApplicationContext context = SpringApplication.run(SpringbootEnableApplication.class, args);
//获取Bean
Object user = context.getBean("user");
System.out.println(user);
}
}
- 运行测试
@Enable*底层依赖于@lmport注解导入一些类,使用@import导入的类会被Spring加载到IOC容器中。而@lmport提供4中用法:
(1)导入Bean- 修改SpringbootEnableApplication
package cn.itbluebox.springbootenable;
import cn.itbluebox.config.EnableUser;
import cn.itbluebox.config.UserConfig;
import cn.itbluebox.domain.User;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.import;
@SpringBootApplication
//@ComponentScan("cn.itbluebox.config")
//@import(UserConfig.class)
//@EnableUser
@import(User.class)
public class SpringbootEnableApplication {
public static void main(String[] args) {
ConfigurableApplicationContext context = SpringApplication.run(SpringbootEnableApplication.class, args);
//获取Bean
Object user = context.getBean("user");
System.out.println(user);
}
}
-
运行测试
无法获取到
虽然通过@import(User.class)引入创建了User的对象但是并不一定是getBean的时候叫user,通过User字节码获取 -
修改springboot-enable当中的SpringbootEnableApplication
package cn.itbluebox.springbootenable;
import cn.itbluebox.config.EnableUser;
import cn.itbluebox.config.UserConfig;
import cn.itbluebox.domain.User;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.import;
@SpringBootApplication
//@ComponentScan("cn.itbluebox.config")
//@import(UserConfig.class)
//@EnableUser
@import(User.class)
public class SpringbootEnableApplication {
public static void main(String[] args) {
ConfigurableApplicationContext context = SpringApplication.run(SpringbootEnableApplication.class, args);
//获取Bean
User user = context.getBean(User.class);
System.out.println(user);
}
}
- 获取一些其他属性
package cn.itbluebox.springbootenable;
import cn.itbluebox.config.EnableUser;
import cn.itbluebox.config.UserConfig;
import cn.itbluebox.domain.User;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.import;
import java.util.Map;
@SpringBootApplication
//@ComponentScan("cn.itbluebox.config")
//@import(UserConfig.class)
//@EnableUser
@import(User.class)
public class SpringbootEnableApplication {
public static void main(String[] args) {
ConfigurableApplicationContext context = SpringApplication.run(SpringbootEnableApplication.class, args);
//获取Bean
User user = context.getBean(User.class);
System.out.println(user);
Map map = context.getBeansOfType(User.class);
System.out.println(map);
}
}
- 运行测试
- 修改springboot-enable当中的SpringbootEnableApplication
package cn.itbluebox.springbootenable;
import cn.itbluebox.config.EnableUser;
import cn.itbluebox.config.UserConfig;
import cn.itbluebox.domain.User;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.import;
import java.util.Map;
@SpringBootApplication
//@ComponentScan("cn.itbluebox.config")
//@import(UserConfig.class)
//@EnableUser
//@import(User.class)
@import(UserConfig.class)
public class SpringbootEnableApplication {
public static void main(String[] args) {
ConfigurableApplicationContext context = SpringApplication.run(SpringbootEnableApplication.class, args);
//获取Bean
User user = context.getBean(User.class);
System.out.println(user);
Map map = context.getBeansOfType(User.class);
System.out.println(map);
}
}
- 在springboot-enable-other当中创建Role对象
- 修改springboot-enable-other当中的UserConfig
- Role也会创建到Spring的IOC容器当中
package cn.itbluebox.config;
import cn.itbluebox.domain.Role;
import cn.itbluebox.domain.User;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class UserConfig {
@Bean
public User user(){
return new User();
}
@Bean
public Role role(){
return new Role();
}
}
- 完善springboot-enable当中的SpringbootEnableApplication
package cn.itbluebox.springbootenable;
import cn.itbluebox.config.EnableUser;
import cn.itbluebox.config.UserConfig;
import cn.itbluebox.domain.Role;
import cn.itbluebox.domain.User;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.import;
import java.util.Map;
@SpringBootApplication
//@ComponentScan("cn.itbluebox.config")
//@import(UserConfig.class)
//@EnableUser
//@import(User.class)
@import(UserConfig.class)
public class SpringbootEnableApplication {
public static void main(String[] args) {
ConfigurableApplicationContext context = SpringApplication.run(SpringbootEnableApplication.class, args);
//获取Bean
User user = context.getBean(User.class);
System.out.println(user);
Role role = context.getBean(Role.class);
System.out.println(role);
}
}
- 运行测试
- 在springboot-enable当中的SpringbootEnableApplication上使用@import注解的时候在springboot-enable-other当中的UserConfig上可以不使用 @Configuration注解
- 运行测试
- 源代码
public interface importSelector {
String[] selectimports(Annotationmetadata importingClassmetadata);
@Nullable
default Predicate getExclusionFilter() {
return null;
}
}
- 在springboot-enable-other当中创建MyimportSelector,去实现importSelector接口
package cn.itbluebox.config;
import org.springframework.context.annotation.importSelector;
import org.springframework.core.type.Annotationmetadata;
public class MyimportSelector implements importSelector {
@Override
public String[] selectimports(Annotationmetadata importingClassmetadata) {
return new String[]{"cn.itbluebox.domain.User","cn.itbluebox.domain.Role"};
}
}
- 修改springboot-enable当中的SpringbootEnableApplication
package cn.itbluebox.springbootenable;
import cn.itbluebox.config.EnableUser;
import cn.itbluebox.config.MyimportSelector;
import cn.itbluebox.config.UserConfig;
import cn.itbluebox.domain.Role;
import cn.itbluebox.domain.User;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.import;
import org.springframework.context.annotation.importSelector;
import java.util.Map;
@SpringBootApplication
//@ComponentScan("cn.itbluebox.config")
//@import(UserConfig.class)
//@EnableUser
//@import(User.class)
//@import(UserConfig.class)
@import(MyimportSelector.class)
public class SpringbootEnableApplication {
public static void main(String[] args) {
ConfigurableApplicationContext context = SpringApplication.run(SpringbootEnableApplication.class, args);
//获取Bean
User user = context.getBean(User.class);
System.out.println(user);
Role role = context.getBean(Role.class);
System.out.println(role);
}
}
- 运行测试
- 在springboot-enable-other当中创建
package cn.itbluebox.config;
import cn.itbluebox.domain.User;
import org.springframework.beans.factory.support.AbstractBeanDefinition;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.context.annotation.importBeanDefinitionRegistrar;
import org.springframework.core.type.Annotationmetadata;
public class MyimportBeanDefinitionRegistrar implements importBeanDefinitionRegistrar {
@Override
public void registerBeanDefinitions(Annotationmetadata importingClassmetadata, BeanDefinitionRegistry registry ) {
AbstractBeanDefinition beanDefinitionBuilder = BeanDefinitionBuilder.rootBeanDefinition(User.class).getBeanDefinition();
registry.registerBeanDefinition("user",beanDefinitionBuilder);
}
}
- 完善springboot-enable当中的SpringbootEnableApplication
package cn.itbluebox.springbootenable;
import cn.itbluebox.config.EnableUser;
import cn.itbluebox.config.MyimportBeanDefinitionRegistrar;
import cn.itbluebox.config.MyimportSelector;
import cn.itbluebox.config.UserConfig;
import cn.itbluebox.domain.Role;
import cn.itbluebox.domain.User;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.import;
import org.springframework.context.annotation.importSelector;
import java.util.Map;
@SpringBootApplication
//@ComponentScan("cn.itbluebox.config")
//@import(UserConfig.class)
//@EnableUser
//@import(User.class)
//@import(UserConfig.class)
//@import(MyimportSelector.class)
@import({MyimportBeanDefinitionRegistrar.class})
public class SpringbootEnableApplication {
public static void main(String[] args) {
ConfigurableApplicationContext context = SpringApplication.run(SpringbootEnableApplication.class, args);
//获取Bean
User user = context.getBean(User.class);
System.out.println(user);
Role role = context.getBean(Role.class);
System.out.println(role);
}
}
- 运行测试
user获取成功,但是Role没有获取成功(因为在MyimportBeanDefinitionRegistrar没有导入Role的)
- 源代码
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@documented
@Inherited
@AutoConfigurationPackage
@import({AutoConfigurationimportSelector.class})
public @interface EnableAutoConfiguration {
String ENABLED_OVERRIDE_PROPERTY = "spring.boot.enableautoconfiguration";
Class>[] exclude() default {};
String[] excludeName() default {};
}
- @EnableAutoConfiauration注解内部使用@import (AutoConficurationimportSelector.class)来加载配置类。
- 配置文件位置: meta-INF/spring.factories,该配置文件中定义了大量的配置类,当SpringBoot应用启动时,会自动加载这些配置类,初始化Bean
- 并不是所有的Bean都会被初始化,在配置类中使用Condition来加载满足条件的Bean
(注意spring.factories当中的配置类在Spring启动的时候并不会全部创建在每一个类上都有ConditionalOnClass判断是否需要加载当前对象)
案例:
需求:自定义redis-starter。要求当导入redis坐标时,SpringBoot自动创建Jedis的Bean。
实现上述需求,我们可以参考MyBatis
- 删除一些文件
- 修改pom.xml文件
4.0.0 org.springframework.boot spring-boot-starter-parent 2.5.6 cn.itbluebox redis-spring-boot-starter 0.0.1-SNAPSHOT redis-spring-boot-starter Demo project for Spring Boot 1.8 org.springframework.boot spring-boot-starter cn.itbluebox redis-spring-boot-autoconfigure 0.0.1-SNAPSHOT
- 删除启动类和测试类
- 删除一些文件
- 修改pom.xml文件
4.0.0 org.springframework.boot spring-boot-starter-parent 2.5.6 cn.itbluebox redis-spring-boot-autoconfigure 0.0.1-SNAPSHOT redis-spring-boot-autoconfigure Demo project for Spring Boot 1.8 org.springframework.boot spring-boot-starter redis.clients jedis
- 删除启动类和测试类
package cn.itbluebox.redis.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import redis.clients.jedis.Jedis;
@Configuration
public class RedisAutoConfiguration {
@Bean
public Jedis jedis(){
return new Jedis();
}
}
2)创建RedisProperties
package cn.itbluebox.redis.config;
import org.springframework.boot.context.properties.ConfigurationProperties;
@ConfigurationProperties(prefix = "redis")
public class RedisProperties {
private String host = "localhost";//设置默认值
private 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)完善RedisAutoConfiguration
package cn.itbluebox.redis.config;
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)//设置完之后RedisProperties会被Spring所识别
public class RedisAutoConfiguration {
@Bean
public Jedis jedis(RedisProperties redisProperties){
return new Jedis(redisProperties.getHost(),redisProperties.getPort());
}
}
4)创建spring.factories
org.springframework.boot.autoconfigure.EnableAutoConfiguration= cn.itbluebox.redis.config.RedisAutoConfiguration(4)在测试模块中引入自定义的redis-starter依赖,测试获取Jedis的Bean,操作redis。
- 修改springboot-enable当中pom.xml
cn.itbluebox redis-spring-boot-starter 0.0.1-SNAPSHOT
- 继续完善springboot-enable当中的SpringbootEnableApplication
package cn.itbluebox.springbootenable;
import cn.itbluebox.config.MyimportBeanDefinitionRegistrar;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.annotation.import;
import redis.clients.jedis.Jedis;
@SpringBootApplication
@import({MyimportBeanDefinitionRegistrar.class})
public class SpringbootEnableApplication {
public static void main(String[] args) {
ConfigurableApplicationContext context = SpringApplication.run(SpringbootEnableApplication.class, args);
Jedis jedis = context.getBean(Jedis.class);
System.out.println(jedis);
}
}
- 运行测试
- 启动本机的redis
在SpringbootEnableApplication操作redis存入数据,并获取数据
package cn.itbluebox.springbootenable;
import cn.itbluebox.config.MyimportBeanDefinitionRegistrar;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.annotation.import;
import redis.clients.jedis.Jedis;
@SpringBootApplication
@import({MyimportBeanDefinitionRegistrar.class})
public class SpringbootEnableApplication {
public static void main(String[] args) {
ConfigurableApplicationContext context = SpringApplication.run(SpringbootEnableApplication.class, args);
Jedis jedis = context.getBean(Jedis.class);
System.out.println(jedis);
jedis.set("name","itbluebox");
String name = jedis.get("name");
System.out.println(name);
}
}
- 运行测试
RedisProperties会绑定到对应的配置文件读取配置文件当中的信息
- 在springboot-enable当中的application.properties设置端口号
redis.port=6666
更改端口号后一定报错,但是证明配置修改成功
- 运行测试
- 修改redis-spring-boot-autoconfigure当中的RedisAutoConfiguration
package cn.itbluebox.redis.config;
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)//设置完之后RedisProperties会被Spring所识别
@ConditionalOnClass(Jedis.class)//设置Jedis存在的时候才去加载
public class RedisAutoConfiguration {
@Bean
@ConditionalOnMissingBean(name = "jedis")//如果用户定义了自己的Jedis就使用用户自定义的Jedis,没有没有定义使用当前的
public Jedis jedis(RedisProperties redisProperties){
System.out.println("RedisAutoConfiguration.....");
return new Jedis(redisProperties.getHost(),redisProperties.getPort());
}
}
- 运行测试
设置正确的端口号
运行
- 修改springboot-enable当中的SpringbootEnableApplication
package cn.itbluebox.springbootenable;
import cn.itbluebox.config.MyimportBeanDefinitionRegistrar;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.import;
import redis.clients.jedis.Jedis;
@SpringBootApplication
@import({MyimportBeanDefinitionRegistrar.class})
public class SpringbootEnableApplication {
public static void main(String[] args) {
ConfigurableApplicationContext context = SpringApplication.run(SpringbootEnableApplication.class, args);
Jedis jedis = context.getBean(Jedis.class);
System.out.println(jedis);
jedis.set("name","itbluebox2");
String name = jedis.get("name");
System.out.println(name);
}
@Bean
public Jedis jedis(){
return new Jedis("localhost",6379);
}
}
- 运行测试
没有输出RedisAutoConfiguration.....证明RedisAutoConfiguration的@ConditionalOnMissingBean(name = "jedis")生效的
SpringBoot的监听机制,其实是对Java提供的事件监听机制的封装。Java中的事件监听机制定义了以下几个角色:
- 事件: Event,继承java.util.EventObject类的对象
- 事件源:Source,任意对象Object
- 监听器:Listener,实现java.util.EventListener接口的对象
SpringBoot在项目启动时,会对几个监听器进行回调,我们可以实现这些监听器接口,在项目启动时完成—些操作。
ApplicationContextInitializer、SpringApplicationRunListener、CommandLineRunner、ApplicationRunner
- 创建包结构
- 创建MyApplicationContextInitializer
package cn.itbluebox.springbootlistener.listener;
import org.springframework.context.ApplicationContextInitializer;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.stereotype.Component;
public class MyApplicationContextInitializer implements ApplicationContextInitializer {
@Override
public void initialize(ConfigurableApplicationContext applicationContext) {
System.out.println("ApplicationContextInitializer....initialize");
}
}
- 创建MySpringApplicationRunListener
package cn.itbluebox.springbootlistener.listener;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.SpringApplicationRunListener;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.core.env.ConfigurableEnvironment;
import org.springframework.stereotype.Component;
public class MySpringApplicationRunListener implements SpringApplicationRunListener {
public MySpringApplicationRunListener(SpringApplication application, String[] args) {
}
@Override
public void starting() {
System.out.println("starting...项目启动中");
}
@Override
public void environmentPrepared(ConfigurableEnvironment environment) {
System.out.println("environmentPrepared...环境对象开始准备");
}
@Override
public void contextPrepared(ConfigurableApplicationContext context) {
System.out.println("contextPrepared...上下文对象开始准备");
}
@Override
public void contextLoaded(ConfigurableApplicationContext context) {
System.out.println("contextLoaded...上下文对象开始加载");
}
@Override
public void started(ConfigurableApplicationContext context) {
System.out.println("started...上下文对象加载完成");
}
@Override
public void running(ConfigurableApplicationContext context) {
System.out.println("running...项目启动完成,开始运行");
}
@Override
public void failed(ConfigurableApplicationContext context, Throwable exception) {
System.out.println("failed...项目启动失败");
}
}
- 创建MyCommandLineRunner
package cn.itbluebox.springbootlistener.listener;
import org.springframework.boot.CommandLineRunner;
import org.springframework.stereotype.Component;
import java.util.Arrays;
public class MyCommandLineRunner implements CommandLineRunner {
@Override
public void run(String... args) throws Exception {
System.out.println("CommandLineRunner...run");
}
}
- 创建MyApplicationRunner
package cn.itbluebox.springbootlistener.listener;
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.stereotype.Component;
import java.util.Arrays;
public class MyApplicationRunner implements ApplicationRunner {
@Override
public void run(ApplicationArguments args) throws Exception {
System.out.println("ApplicationRunner...run");
}
}
- 完善上述四个并将其注册到Spring容器当中
MyApplicationContextInitializer
package cn.itbluebox.springbootlistener.listener;
import org.springframework.context.ApplicationContextInitializer;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.stereotype.Component;
@Component
public class MyApplicationContextInitializer implements ApplicationContextInitializer {
@Override
public void initialize(ConfigurableApplicationContext applicationContext) {
System.out.println("ApplicationContextInitializer....initialize");
}
}
MyApplicationRunner
package cn.itbluebox.springbootlistener.listener;
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.stereotype.Component;
import java.util.Arrays;
@Component
public class MyApplicationRunner implements ApplicationRunner {
@Override
public void run(ApplicationArguments args) throws Exception {
System.out.println("ApplicationRunner...run");
}
}
MyCommandLineRunner
package cn.itbluebox.springbootlistener.listener;
import org.springframework.boot.CommandLineRunner;
import org.springframework.stereotype.Component;
import java.util.Arrays;
@Component
public class MyCommandLineRunner implements CommandLineRunner {
@Override
public void run(String... args) throws Exception {
System.out.println("CommandLineRunner...run");
}
}
(3)运行测试
我们观察到上述只执行了两个监听对象
MyApplicationRunner
MyCommandLineRunner
- 设置输出一下对应MyApplicationRunner和MyCommandLineRunner的args
MyApplicationRunner
package cn.itbluebox.springbootlistener.listener;
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.stereotype.Component;
import java.util.Arrays;
@Component
public class MyApplicationRunner implements ApplicationRunner {
@Override
public void run(ApplicationArguments args) throws Exception {
System.out.println("ApplicationRunner...run");
System.out.println(Arrays.asList(args.getSourceArgs()));
}
}
**MyCommandLineRunner **
package cn.itbluebox.springbootlistener.listener;
import org.springframework.boot.CommandLineRunner;
import org.springframework.stereotype.Component;
import java.util.Arrays;
@Component
public class MyCommandLineRunner implements CommandLineRunner {
@Override
public void run(String... args) throws Exception {
System.out.println("CommandLineRunner...run");
System.out.println(Arrays.asList(args));
}
}
运行测试
- 其中args对应的是参数运行时候传递的一些参数
- 设置运行时传递一些参数
- 启动运行测试
- 创建spring.factories
org.springframework.context.ApplicationContextInitializer=cn.itbluebox.springbootlistener.listener.MyApplicationContextInitializer
- 运行测试
运行成功
org.springframework.boot.SpringApplicationRunListener = cn.itbluebox.springbootlistener.listener.MySpringApplicationRunListener
- 运行测试
运行成功
SpringBoot自带监控功能Actuator,可以帮助实现对程序内部运行情况监控,比如监控状况、Bean加载情况、配置属性、日志信息等。
1、创建工程 1)创建模块
4.0.0 org.springframework.boot spring-boot-starter-parent 2.5.6 cn.itbluebox springboot-actuator 0.0.1-SNAPSHOT springboot-actuator Demo project for Spring Boot 1.8 org.springframework.boot spring-boot-starter-actuator org.springframework.boot spring-boot-starter-web org.springframework.boot spring-boot-starter-test test org.springframework.boot spring-boot-maven-plugin
而其中下面这段是SpringBoot的监控的依赖
2、访问http://localhost:8080/acruatororg.springframework.boot spring-boot-starter-actuator
启动项目
访问http://localhost:8080/actuator
http://localhost:8080/actuator/health
修改application.properties
# 开启健康检查的完整信息 management.endpoint.health.show-details=always
再次访问:http://localhost:8080/actuator/health/
引入redis的依赖
org.springframework.boot spring-boot-starter-data-redis
重新运行项目
访问:http://localhost:8080/actuator/health/
因为没有我的电脑没有开启redis所以,redis报错了
启动本机redis
再次访问:http://localhost:8080/actuator/health/
修改application.properties
management.endpoints.web.exposure.include=*
重新启动项目
再次访问:http://localhost:8080/actuator/
{
"_links": {
"self": {
"href": "http://localhost:8080/actuator",
"templated": false
},
"beans": {
"href": "http://localhost:8080/actuator/beans",
"templated": false
},
"caches-cache": {
"href": "http://localhost:8080/actuator/caches/{cache}",
"templated": true
},
"caches": {
"href": "http://localhost:8080/actuator/caches",
"templated": false
},
"health": {
"href": "http://localhost:8080/actuator/health",
"templated": false
},
"health-path": {
"href": "http://localhost:8080/actuator/health/{*path}",
"templated": true
},
"info": {
"href": "http://localhost:8080/actuator/info",
"templated": false
},
"conditions": {
"href": "http://localhost:8080/actuator/conditions",
"templated": false
},
"configprops": {
"href": "http://localhost:8080/actuator/configprops",
"templated": false
},
"configprops-prefix": {
"href": "http://localhost:8080/actuator/configprops/{prefix}",
"templated": true
},
"env": {
"href": "http://localhost:8080/actuator/env",
"templated": false
},
"env-toMatch": {
"href": "http://localhost:8080/actuator/env/{toMatch}",
"templated": true
},
"loggers": {
"href": "http://localhost:8080/actuator/loggers",
"templated": false
},
"loggers-name": {
"href": "http://localhost:8080/actuator/loggers/{name}",
"templated": true
},
"heapdump": {
"href": "http://localhost:8080/actuator/heapdump",
"templated": false
},
"threaddump": {
"href": "http://localhost:8080/actuator/threaddump",
"templated": false
},
"metrics-requiredMetricName": {
"href": "http://localhost:8080/actuator/metrics/{requiredMetricName}",
"templated": true
},
"metrics": {
"href": "http://localhost:8080/actuator/metrics",
"templated": false
},
"scheduledtasks": {
"href": "http://localhost:8080/actuator/scheduledtasks",
"templated": false
},
"mappings": {
"href": "http://localhost:8080/actuator/mappings",
"templated": false
}
}
}
2)我们来使用一些比较常用的
01)http://localhost:8080/actuator/beans
东西太多了只粘贴一部分信息
创建UserController
package cn.itbluebox.springbootactuator;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("/user")
public class UserController {
@RequestMapping("findAll")
public String findAll(){
return "SUCCESS";
}
}
重新运行测试
访问:http://localhost:8080/actuator/mappings
- Spring Boot Admin是一个开源社区项目,用于管理和监控SpringBoot应用程序。
- Spring Boot Admin有两个角色,客户端(Client)和服务端(Server)。
- 应用程序作为Spring Boot Admin Client向为Spring Boot Admin Server注册
- Spring Boot Admin Server,的UI界面将Spring Boot AdminClient的ActuatorEndpoint上的一些监控信息。
通过上述的创建方式已经自动引入了对应的依赖
开启服务
在springboot-admin-server当中的SpringbootAdminServerApplication上设置@EnableAdminServer
package cn.itbluebox.springbootadminserver;
import de.codecentric.boot.admin.server.config.EnableAdminServer;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@EnableAdminServer
@SpringBootApplication
public class SpringbootAdminServerApplication {
public static void main(String[] args) {
SpringApplication.run(SpringbootAdminServerApplication.class, args);
}
}
4)修改端口号
server.port=9000(2)admin-client 1)创建admin-client模块
通过上述的方式已经自动引入了对应的依赖
#指定admin.server的地址 spring.boot.admin.client.url=http://localhost:9000 # 开启健康检查 management.endpoint.health.show-details=always # 开启所有的配置 management.endpoints.web.exposure.include=*4)启动server和client服务,访问server 1>启动server
启动成功
创建UserController
package cn.itbluebox.springbootadminclient;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("/user")
public class UserController {
@RequestMapping("findAll")
public String findAll(){
return "SUCCESS";
}
}
重新运行springboot-admin-client
运行成功
访问http://localhost:8080/user/findAll
再次访问:http://localhost:9000/instances/4664fd8429f6/metrics
再次访问http://localhost:8080/user/findAll
被访问次数变成2
线程
| 目录 | |
|---|---|
| Java之Spring Boot入门到精通【IDEA版】(一篇文章精通系列)【上】 | |
| Java之Spring Boot入门到精通【IDEA版】SpringBoot整合其他框架【Junit,Redis,MyBatis】(一篇文章精通系列)【中】 | |
| Java之Spring Boot入门到精通【IDEA版】SpringBoot原理分析,SpringBoot监控(一篇文章精通系列)【下】 |



