SpringBoot(高级原理分析)(上)

本文涉及的产品
Redis 开源版,标准版 2GB
推荐场景:
搭建游戏排行榜
云数据库 Tair(兼容Redis),内存型 2GB
简介: SpringBoot(高级原理分析)(上)

①. 自动配置

①. condition

1>. condition


①. 什么是Condition?

1.什么是condition?


  • ①. condition是在Spring4.0增加的条件判断功能,通过这个功能可以实现选择性的创建Bean操作


  • ②. 自定义条件


自定义条件:

(1).定义条件类:自定义实现Condition接口,重写matches方法,在matches方法中进行逻辑判断,返回boolean值。matches方法两个参数:

context:上下文对象,可以获取属性值,获取类加载器,获取BeanFactory等

metadata:元数据对象,用于获取注解属性

(2).SpringBoot提供的常见条件注解:

ConditionalOnProperty:判断配置文件是否有对应属性和值才初始化Bean

ConditionalOnClass:判断坏境中是否有对应字节码文件才初始化Bean

ConditionalOnMissingBean:判断坏境中没有对应Bean才初始化Bean

上面这些可以在如下找到:

image.png


②. 案例1

2. 案例1


  • ①. 需求:在Spring的IOC容器中有一个User的Bean,现要求:

    导入Jedis坐标后,加载该Bean,没导入,则不加载


  • ②. 具体代码实现:

image.png

@Configuration
public class UserConfig {
    @Bean
    @Conditional(UserCondition.class)
    public User getUser(){
        return new User();
    }
}
package com.itheima.condition;
import org.springframework.context.annotation.Condition;
import org.springframework.context.annotation.ConditionContext;
import org.springframework.core.env.Environment;
import org.springframework.core.type.AnnotatedTypeMetadata;
import java.util.Map;
public class UserCondition implements Condition {
    /*
    * matches()方法
    * 如果返回值是true,那么会创建相对应的对象
    * 如果方法返回值是false,那么则不会创建相对应的对象
    * 1.conditionContext:上下文对象。用于获取坏境,IOC容器,ClassLoader对象
    * 2.annotatedTypeMetadata:注解的元对象。可以用于获取注解定义的属性值
    * */
    @Override
    public boolean matches(ConditionContext conditionContext, AnnotatedTypeMetadata annotatedTypeMetadata) {
        /*
         * 需求: 1.导入Jedis坐标后创建bean
         * 思路: 判断redis.clients.jedis.Jedis;文件是否存在
         * */
        /*
        Environment environment = conditionContext.getEnvironment();
        environment.getProperty();
        * */
        boolean flag=true;
        try {
            Class<?> cls = Class.forName("redis.clients.jedis.Jedis");
        } catch (ClassNotFoundException e) {
            flag=false;
        }
        return flag;
    }
}


③. 案例2

3. 案例2


  • ①. 需求:在Spring的IOC容器中有一个User的Bean,现要求:

    将类的判断定义为动态的判断哪个字节码文件可以动态指定(ConditionOnClass)


  • ②. 代码演示:


image.png

@Configuration
public class UserConfig {
    @Bean
    //@Conditional(UserCondition.class)
    @ConditionOnClass("redis.clients.jedis.Jedis")
    public User getUser(){
        return new User();
    }
}
@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Conditional(UserCondition.class)
public @interface ConditionOnClass {
    String[]value();
}
public class UserCondition implements Condition {
    /*
    * matches()方法
    * 如果返回值是true,那么会创建相对应的对象
    * 如果方法返回值是false,那么则不会创建相对应的对象
    * 1.conditionContext:上下文对象。用于获取坏境,IOC容器,ClassLoader对象
    * 2.annotatedTypeMetadata:注解的元对象。可以用于获取注解定义的属性值
    * */
    @Override
    public boolean matches(ConditionContext conditionContext, AnnotatedTypeMetadata annotatedTypeMetadata) {
        /*
         * 需求: 1.导入Jedis坐标后创建bean
         * 思路: 判断redis.clients.jedis.Jedis;文件是否存在
         * */
        /*
        Environment environment = conditionContext.getEnvironment();
        environment.getProperty();
        * */
       /* boolean flag=true;
        try {
            Class<?> cls = Class.forName("redis.clients.jedis.Jedis");
        } catch (ClassNotFoundException e) {
            flag=false;
        }
        return flag;*/
        //2.需求:导入通过注解属性值value指定坐标后创建Bean
        //获取注解属性值 value
        Map<String, Object> map = annotatedTypeMetadata.getAnnotationAttributes(ConditionOnClass.class.getName());
        System.out.println(map);
        String[]value = (String[]) map.get("value");
        boolean flag=true;
        try {
            for (String className : value) {
                Class<?> cls = Class.forName(className);
            }
        } catch (ClassNotFoundException e) {
            flag=false;
        }
        return flag;
    }
}


②. 监听机制


2>.监听机制(了解)


  • SpringBoot的web坏境中默认使用tomcat作为内置服务器,其实SpringBoot提供了4中内置服务器供我们选择,我们可以很方便的进行切换。


  • spring-boot-autoConfigure–》web–》embedded

image.png


  • ③. 代码演示如下(如要切换jetty):


<dependencies>
        <!--移除tomcat的依赖-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
            <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>
    </dependencies>


③. @Enable * 注解原理


3>. @Enable * 注解原理


①. 问题的提出:SpringBoot工程是否可以直接获取jar包中定义的Bean?

不能,ComponentScan只能扫描引导类所在包及子包


②. 解决方案:

(1).使用@ComponentScan进行包扫描

(2).@Import注解,加载类,这些类都会被Spring创建,并放入IOC容器

(3).可以对@Import进行封装,这样就可以不需要知道@Import()里面填写什么东西


④. @Import

4>. @Import


①. 导入Bean


②. 导入配置类


③. 导入ImportSelector实现类,一般用于加载配置文件中的类

//这是工程和User类是同一个工程,@Import 则是另一个工程
public class MyImportSelector implements ImportSelector {
    @Override
    public String[] selectImports(AnnotationMetadata annotationMetadata) {
        //这里的 "com.itheima.domain.User" 是全限类名
        return new String[]{"com.itheima.domain.User"};
    }
}
@SpringBootApplication
//@Import(User.class)
@Import(MyImportSelector.class)
public class SpringbootApplication {
    public static void main(String[] args) {
        ConfigurableApplicationContext context = SpringApplication.run(SpringbootApplication.class, args);
        User user= context.getBean(User.class);
        /*Map<String, User> map = context.getBeansOfType(User.class);
        System.out.println(map);*/
        System.out.println(user);
    }
}


  • ④. 导入ImportBeanDefinitionRegistrar 的实现类(了解)


⑤. @EnableAutoConfiguration

5>. @EnableAutoConfiguration 掌握


①. EnableAutoConfiguration 中的@Import 在SpringBoot中流程分析:

image.png

image.png

image.png

  • ②. @EnableAutoConfiguration注解内部使用@Import({AutoConfigurationImportSelector.class})来加载配置类


  • ③. 配置文件位置:META-INF/spring.factories,该配置文件中定义了大量的配置类,当SpringBoot应用启动时,会自动加载这些配置类,初始化Bean


  • ④. 并不是所有的Bean都会被初始化,在配置类中使用Condition来加载满足条件的Bean
相关实践学习
基于Redis实现在线游戏积分排行榜
本场景将介绍如何基于Redis数据库实现在线游戏中的游戏玩家积分排行榜功能。
云数据库 Redis 版使用教程
云数据库Redis版是兼容Redis协议标准的、提供持久化的内存数据库服务,基于高可靠双机热备架构及可无缝扩展的集群架构,满足高读写性能场景及容量需弹性变配的业务需求。 产品详情:https://www.aliyun.com/product/kvstore &nbsp; &nbsp; ------------------------------------------------------------------------- 阿里云数据库体验:数据库上云实战 开发者云会免费提供一台带自建MySQL的源数据库&nbsp;ECS 实例和一台目标数据库&nbsp;RDS实例。跟着指引,您可以一步步实现将ECS自建数据库迁移到目标数据库RDS。 点击下方链接,领取免费ECS&amp;RDS资源,30分钟完成数据库上云实战!https://developer.aliyun.com/adc/scenario/51eefbd1894e42f6bb9acacadd3f9121?spm=a2c6h.13788135.J_3257954370.9.4ba85f24utseFl
相关文章
|
1天前
|
Java Spring
SpringBoot自动装配的原理
在Spring Boot项目中,启动引导类通常使用`@SpringBootApplication`注解。该注解集成了`@SpringBootConfiguration`、`@ComponentScan`和`@EnableAutoConfiguration`三个注解,分别用于标记配置类、开启组件扫描和启用自动配置。
30 17
|
22天前
|
Java Spring 容器
springboot @RequiredArgsConstructor @Lazy解决循环依赖的原理
【10月更文挑战第15天】在Spring Boot应用中,循环依赖是一个常见问题,当两个或多个Bean相互依赖时,会导致Spring容器陷入死循环。本文通过比较@RequiredArgsConstructor和@Lazy注解,探讨它们解决循环依赖的原理和优缺点。@RequiredArgsConstructor通过构造函数注入依赖,使代码更简洁;@Lazy则通过延迟Bean的初始化,打破创建顺序依赖。两者各有优势,需根据具体场景选择合适的方法。
40 4
|
4月前
|
Java 应用服务中间件 开发者
Java面试题:解释Spring Boot的优势及其自动配置原理
Java面试题:解释Spring Boot的优势及其自动配置原理
118 0
|
2月前
|
Java 应用服务中间件 API
Vertx高并发理论原理以及对比SpringBoot
Vertx 是一个基于 Netty 的响应式工具包,不同于传统框架如 Spring,它的侵入性较小,甚至可在 Spring Boot 中使用。响应式编程(Reactive Programming)基于事件模式,通过事件流触发任务执行,其核心在于事件流 Stream。相比多线程异步,响应式编程能以更少线程完成更多任务,减少内存消耗与上下文切换开销,提高 CPU 利用率。Vertx 适用于高并发系统,如 IM 系统、高性能中间件及需要较少服务器支持大规模 WEB 应用的场景。随着 JDK 21 引入协程,未来 Tomcat 也将优化支持更高并发,降低响应式框架的必要性。
Vertx高并发理论原理以及对比SpringBoot
|
28天前
|
Java BI API
spring boot 整合 itextpdf 导出 PDF,写入大文本,写入HTML代码,分析当下导出PDF的几个工具
这篇文章介绍了如何在Spring Boot项目中整合iTextPDF库来导出PDF文件,包括写入大文本和HTML代码,并分析了几种常用的Java PDF导出工具。
329 0
spring boot 整合 itextpdf 导出 PDF,写入大文本,写入HTML代码,分析当下导出PDF的几个工具
|
1月前
|
XML Java 应用服务中间件
【Spring】运行Spring Boot项目,请求响应流程分析以及404和500报错
【Spring】运行Spring Boot项目,请求响应流程分析以及404和500报错
144 2
|
2月前
|
Java 开发者 数据格式
【Java笔记+踩坑】SpringBoot基础4——原理篇
bean的8种加载方式,自动配置原理、自定义starter开发、SpringBoot程序启动流程解析
【Java笔记+踩坑】SpringBoot基础4——原理篇
|
4月前
|
Java Spring 容器
Spring Boot 启动源码解析结合Spring Bean生命周期分析
Spring Boot 启动源码解析结合Spring Bean生命周期分析
101 11
|
4月前
|
SQL Java 数据库连接
springboot~mybatis-pagehelper原理与使用
【7月更文挑战第15天】MyBatis-PageHelper是用于MyBatis的分页插件,基于MyBatis的拦截器机制实现。它通过在SQL执行前动态修改SQL语句添加LIMIT子句以支持分页。使用时需在`pom.xml`添加依赖并配置方言等参数。示例代码: PageHelper.startPage(2, 10); List&lt;User&gt; users = userMapper.getAllUsers(); PageInfo&lt;User&gt; pageInfo = new PageInfo&lt;&gt;(users); 这使得分页查询变得简单且能获取总记录数等信息。
|
4月前
|
Java 开发者 Spring
深入理解Spring Boot中的自动配置原理
深入理解Spring Boot中的自动配置原理
下一篇
无影云桌面