SpringBoot高级

目录:
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、流程分析【了解】

  1. 掌握一个技能: 源代码debug 调试 看源码必备神器。

  2. 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、开启功能:查看所有监控健康信息

配置项怎么知道有哪些:

https://docs.spring.io/spring-boot/docs/2.3.0.RELEASE/reference/html/appendix-application-properties.html#actuator-properties

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模块:

  1. 创建admin-server模块
  2. 导入依赖坐标admin-starter-server
  3. 在引导类上开启监控功能@EnableAdminServer
  4. application.properties文件
    server.port=9000
    

(2)admin-clien模块:

  1. 创建admin-clien模块
  2. 导入依赖坐标admin-starter-clien
  3. 配置相关信息: server 地址等
  4. 启动server和client服务,访问server
  5. application.properties文件
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 202,056评论 5 474
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 84,842评论 2 378
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 148,938评论 0 335
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,296评论 1 272
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,292评论 5 363
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,413评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,824评论 3 393
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,493评论 0 256
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,686评论 1 295
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,502评论 2 318
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,553评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,281评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,820评论 3 305
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,873评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,109评论 1 258
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,699评论 2 348
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,257评论 2 341

推荐阅读更多精彩内容