SpringBoot学习笔记三-原理分析

SpringBoot学习笔记三-原理分析

  • SpringBoot自动装配
    • 1.1 案例
    • 1.2 通过注解方式管理Bean
    • 1.3 小结
    • 1.4 Enable注解
    • 1.5 Import注解
      • 1.5.1 ImportSelector实现类
      • 1.5.2 导入ImportBeanDefinitionRegistrar
    • 1.5 EnableAutoConfiguration
    • 1.6 案例

SpringBoot自动装配

当再pom.xml中导入对应的依赖,那么就可以在SpringBoot的IOC容器中获取该依赖中相应的Bean实例:
比如导入redis依赖:

<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-redis</artifactId></dependency>

那么可以在IOC容器获取bean实例redisTemplate:

ConfigurableApplicationContext context = SpringApplication.run(SpringConditionApplication.class, args);
Object redisTemplate = context.getBean("redisTemplate");
System.out.println(redisTemplate);

1.1 案例

Condition案例:通过设定条件来决定手动创建的Bean是否导入IOC容器
条件:当Jedis在类路径上可用时,才能将创建的Bean注入IOC容器:

(1)首先编写condition类

		package com.rql.condition;import org.springframework.context.annotation.Condition;import org.springframework.context.annotation.ConditionContext;import org.springframework.core.type.AnnotatedTypeMetadata;public class ClassCondition implements Condition {@Overridepublic boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {//1.判断Jedis坐标是否导入boolean flag = true;try {Class<?> aClass = Class.forName("redis.clients.jedis.Jedis");} catch (ClassNotFoundException e) {flag=false;}return flag;}}

在配置类中,根据ClassCondition 中的matches方法的返回值来决定是否将Bean注入IOC容器

		package com.rql.config;import com.rql.condition.ClassCondition;import com.rql.domain.User;import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.Conditional;import org.springframework.context.annotation.Configuration;@Configurationpublic class UserConfig {@Bean@Conditional(ClassCondition.class)public User user() {return new User();}}

最后,获取注入的Bean实例:

		ConfigurableApplicationContext context = SpringApplication.run(SpringConditionApplication.class, args);Object user = context.getBean("user");System.out.println(user);

可以发现,如果没有在pom.xml导入Jedis依赖的话,那么matches方法返回的值就为false,那么Bean User就会注入失败,最终结果会报错,找不到对应的Bean实例。

1.2 通过注解方式管理Bean

通过注解的方式可以让条件的复用性更强:
(1)首先,在配置类中,将注入user到IOC容器,这里设置了条件:

@Configuration
public class UserConfig {@Bean@ConditionOnClass("redis.clients.jedis.Jedis")public User user() {return new User();}
}

(2)定义了一个自定义的注解(annotation)叫做 ConditionOnClass。注解在Java中是一种元数据(metadata)机制,它允许你为代码添加额外的信息,这些信息可以在运行时被读取和处理。ConditionOnClass 注解被用于条件性地创建或配置Spring框架中的Bean。

@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Conditional(ClassCondition.class)
public @interface ConditionOnClass {String[] value();
}

(3)创建ClassCondition 类需要实现 Condition 接口,并定义条件逻辑

public class ClassCondition implements Condition {/**** @param context 上下文对象,用于获取环境,IOC容器,ClassLoader对象* @param metadata 注解元对象,可以用于获取注解定义的属性值* @return*/@Overridepublic boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {//1.判断Jedis坐标是否导入Map<String, Object> map = metadata.getAnnotationAttributes(ConditionOnClass.class.getName());System.out.println(map);String[] value = (String[]) map.get("value");boolean flag = true;for (String s : value) {try {Class.forName(s);} catch (ClassNotFoundException e) {flag=false;}}return flag;}
}

1.3 小结

在这里插入图片描述

1.4 Enable注解

下面主要演示在两个不同的module下,一个module使用另一个module的Bean实例:
(1)首先创建两个module
在这里插入图片描述
(2)在spring-enable-other中创建并注入bean user
在这里插入图片描述

package com.rql.domain;public class User {
}
@Configuration
public class UserConfig {@Beanpublic User user() {return new User();}
}

@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import(UserConfig.class)
public @interface EnableUser {
}

然后在spring-enable上使用user

@SpringBootApplication
//@Import(UserConfig.class)
@EnableUser
public class SpringEnableApplication {public static void main(String[] args) {ConfigurableApplicationContext context = SpringApplication.run(SpringEnableApplication.class, args);Object user = context.getBean("user");System.out.println(user);}}

其实,这里本质还是使用了@Import注解,因为在EnableUser中使用了@Import导入了UserConfig类。所以在spring-enable中通过@EnableUser可以加载到user实例

1.5 Import注解

在这里插入图片描述

1.5.1 ImportSelector实现类

(1)导入ImportSelector实现类

创建类并实现ImportSelector接口:

public class MyImportSelector implements ImportSelector {@Overridepublic String[] selectImports(AnnotationMetadata importingClassMetadata) {return new String[]{"com.rql.domain.User","com.rql.domain.Role"};}
}

(2)直接通过Import注解导入,即可

@SpringBootApplication
//@Import(UserConfig.class)
//@EnableUser
@Import(MyImportSelector.class)
public class SpringEnableApplication {public static void main(String[] args) {ConfigurableApplicationContext context = SpringApplication.run(SpringEnableApplication.class, args);Object user = context.getBean("user");System.out.println(user);Object role = context.getBean("role");System.out.println(role);}}

1.5.2 导入ImportBeanDefinitionRegistrar

(1)同样,创建类,继承ImportBeanDefinitionRegistrar接口

public class MyImportBeanDefinitionRegister implements ImportBeanDefinitionRegistrar {@Overridepublic void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry, BeanNameGenerator importBeanNameGenerator) {AbstractBeanDefinition beanDefinition = BeanDefinitionBuilder.rootBeanDefinition(User.class).getBeanDefinition();registry.registerBeanDefinition("user", beanDefinition);//这里直接将Bean注册到IOC容器中}
}

(2)在类中导入MyImportBeanDefinitionRegister ,即可获取Bean

@SpringBootApplication
//@Import(UserConfig.class)
//@EnableUser
//@Import(MyImportSelector.class)
@Import(MyImportBeanDefinitionRegister.class)
public class SpringEnableApplication {public static void main(String[] args) {ConfigurableApplicationContext context = SpringApplication.run(SpringEnableApplication.class, args);
//        Object user = context.getBean("user");
//        System.out.println(user);Object role = context.getBean("user");System.out.println(role);}
}

上述的四种用法主要目的都是将Bean注入到IOC容器,具体涉及到的应用场景后续再补充。

1.5 EnableAutoConfiguration

在这里插入图片描述

1.6 案例

在这里插入图片描述在这里插入图片描述
(1)创建redis-spring-boot-autoconfigure模块

在这里插入图片描述

(2)创建redis-spring-boot-starter模块,并依赖于redis-spring-boot-autoconfigure模块

在这里插入图片描述在这里插入图片描述

(3)在redis-spring-boot-autoconfigure模块初始化Jedis的Bean,并定义META-INF/spring.factories文件
在这里插入图片描述
RedisProperties:

@ConfigurationProperties(prefix = "redis")//用于将配置文件中的属性绑定到Java对象上。
public class RedisProperties {private String host="127.0.0.1";private Integer port=6379;public String getHost() {return host;}public void setHost(String host) {this.host = host;}public Integer getPort() {return port;}public void setPort(Integer port) {this.port = port;}@Overridepublic String toString() {return "RedisProperties{" +"host='" + host + '\'' +", port=" + port +'}';}
}

spring.factories文件


org.springframework.boot.autoconfigure.EnableAutoConfiguration=com.rql.redis.config.RedisAutoConfiguration

Spring Boot在启动时自动加载并应用com.rql.redis.config.RedisAutoConfiguration这个类。这个类的bean会在Spring容器中自动注册。

(4)在测试模块导入自定义的redis-starter依赖,并获取Jedis的Bean,操作redis

首先,需要另一个模块导入自定义的redis-starter依赖:

     <dependency><groupId>com.rql</groupId><artifactId>redis-spring-boot-starter</artifactId><version>0.0.1-SNAPSHOT</version></dependency>

然后获取Jedis的Bean,操作redis

        Jedis jedis = context.getBean(Jedis.class);System.out.println(jedis);jedis.set("name","itcast");String name = jedis.get("name");System.out.println(name);

上述的过程其实就是在模拟SpringBoot自动装配的原理,通过自定义启动类并进行相应的配置。使用时,只需将自定义的启动类导入,即可获取自定义的Bean实例。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/804581.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

活动发布会新闻通稿如何写?

传媒如春雨&#xff0c;润物细无声&#xff0c;大家好&#xff0c;我是51媒体网胡老师。 撰写活动发布会的新闻通稿需要遵循一定的结构和内容要点&#xff0c;以确保信息的准确性、完整性和吸引力。以下是撰写活动发布会新闻通稿的基本步骤和建议&#xff1a; 标题&#xff1…

【智能算法】长鼻浣熊优化算法(COA)原理及实现

目录 1.背景2.算法原理2.1算法思想2.2算法过程 3.结果展示4.参考文献 1.背景 2023年&#xff0c;M Dehghani等人受到长鼻浣熊自然行为启发&#xff0c;提出了长鼻浣熊优化算法&#xff08;Coati Optimization Algorithm&#xff0c;COA&#xff09;。 2.算法原理 2.1算法思想…

C语言 函数——函数封装与程序的健壮性

目录 函数封装&#xff08;Encapsulation&#xff09; 如何增强程序的健壮性&#xff1f; 如何保证不会传入负数实参&#xff1f; 函数设计的基本原则 函数封装&#xff08;Encapsulation&#xff09; 外界对函数的影响——仅限于入口参数 函数对外界的影响——仅限于一个…

C++:内联函数inline,auto关键字,基于范围的for循环,nullpter

文章目录 1.内联函数 inline1.1 概念1.2查看方法1.3 特性1.4 题外话&#xff1a;宏 2.auto关键字2.1 auto 简介2.2 auto使用细则 3. 基于范围的for循环4. nullpter 1.内联函数 inline 1.1 概念 inline int Add(int x, int y) {return x y; } int main(){int ret 0;ret Add…

Vue input密码输入框自定义密码眼睛icon

我们用的饿了么UI组件库里,密码输入框的icon是固定不变的,如下所示: 点击"眼睛"这个icon不变,现在需求是UI给的设计稿里,密码输入框的"眼睛"有如下两种: 代码如下: <el-input:key="passwordType"ref="password"

重装系统前备份笔记

一、点查看自定义快捷键可以定义一些快速启动方式 然后用不习惯的快捷键也能在这里改 二、android studio 快捷键导出备份 导入方法&#xff1a; android studio &#xff0d;>file->import setting ->选择jar包即可 导出studio的设置方法&#xff1a; android …

假期别闲着:REST API实战演练之创建Rest API

1、创建实体类&#xff0c;模拟实体对象 创建一个类&#xff0c;模拟数据数据库来存储数据&#xff0c;这个类就叫Person。 其代码如下&#xff1a; package com.restful;public class Person {private String name;private String about;private int birthYear;public Perso…

【jQuery】jQuery框架

目录 1.jQuery基本用法 1.1选择器 1.2jQuery对象 1.3事件绑定 1.4链式编程 1.5过滤方法 1.6样式操纵 1.6属性操纵 1.7操作value 1.8查找方法 1.9类名操纵 1.10事件进阶 1.11触发事件 1.12window事件绑定 2.节点操作与动画 2.1获取位置 2.2滚动距离 2.3显示/隐…

LangChain-15 Manage Prompt Size 管理上下文大小,用Agent的方式询问问题,并去百科检索内容,总结后返回

背景描述 这一节内容比较复杂&#xff1a; 涉及到使用工具进行百科的检索&#xff08;有现成的插件&#xff09;有AgentExecutor来帮助我们执行后续由于上下文过大&#xff0c; 我们通过计算num_tokens&#xff0c;来控制我们的上下文 安装依赖 pip install --upgrade --qu…

「每日跟读」英语常用句型公式 第7篇

「每日跟读」英语常用句型公式 第7篇 1. He might as well ___ 其实可以___(也无妨) We might as well walk to school (我们其实可以走去学校) We might as well give up (我们其实可以放弃) You might as well go home (你其实可以回家) You might as well listen to h…

数据库设计说明书(Word模板)

2 数据库环境说明 3 数据库的命名规则 4 逻辑设计 5 物理设计 5.1 表汇总 5.2 表结构设计 6 数据规划 6.1 表空间设计 6.2 数据文件设计 6.3 表、索引分区设计 6.4 优化方法 7 安全性设计 7.1 防止用户直接操作数据库 7.2 用户帐号加密处理 7.3 角色与权限控制 8 数据库管理与维…

标准C库文件操作

open 系列API 和 fopen系列API的区别 1.来源: -open 是UNIX系统调用函数(包括LINUX系统)&#xff0c;返回的是文件描述符 -fopen是ANSIC标准的C语言库函数&#xff0c;在不同系统重调用不同内核的API 2.移植性: fopen 是C标准函数&#xff0c;具有良好的移植性&#xff1b; 而…

photomaker:customizing realistic human photos via stacked id embedding

PhotoMaker: 高效个性化定制人像照片文生图 - 知乎今天分享我们团队最新的工作PhotoMaker的技术细节。该工作开源5天Githubstar数已过6千次&#xff0c;已列入Github官方Trending榜第一位&#xff0c;PaperswithCode热度榜第一位&#xff0c;HuggingFace Spaces趋势榜第一位。项…

Vue2 —— 学习(四)

一、收集表单数据 &#xff08;一&#xff09;介绍 前面其实已经 学过了 v-model 双向绑定事件&#xff0c;能获取到表单中的内容到 vm 实例对象中 但是前面只是收集文本框&#xff0c;下面学习一下 各种类型表单数据收集 &#xff08;单/多 选&#xff0c;下拉框&#xff0…

关闭TED报ORA-28365: wallet is not open

关闭钱包报 实际状态是open状态&#xff1a; V$ENCRYPTION_WALLET.STATUS列如果不为CLOSED&#xff0c;重启后也不能是CLOSED&#xff0c;或者清理完成后&#xff0c;再次初始化报“Master Key已存在”错误。 获取UNDO表空间大小 SQL> show parameter undo_tablespace NA…

Elastic:加速生成式人工智能体验

作者&#xff1a;Matt Riley 搜索驱动的人工智能和开发人员工具专为速度和规模而打造。 在大型语言模型&#xff08;LLM&#xff09;和生成式 AI 的每日突破中&#xff0c;开发者站在了这场运动的最前沿&#xff0c;影响着它的方向和可能性。在这篇博客中&#xff0c;我将分享…

第十三篇【传奇开心果系列】Python自动化办公库技术点案例示例:深度解读Python自动化操作PPT

传奇开心果博文系列 系列博文目录Python自动化办公库技术点案例示例系列 博文目录前言一、 Python自动化操作PPT能力介绍二、常用库介绍三、创建新PPT示例代码四、编辑现有PPT示例代码五、批量处理示例代码六、数据驱动生成示例代码七、合并与拆分示例代码八、母版和版式操作示…

词频统计程序

使用Hadoop MapReduce处理文本文件&#xff0c;Mapper负责将文本分割为单词&#xff0c;然后Reducer对每个单词进行计数&#xff0c;最后将结果写入输出文件。 // 定义WordCount公共类 public class WordCount {// 主入口方法&#xff0c;处理命令行参数public static void m…

计算机视觉技术:深度学习在美颜SDK中的应用探索

当下&#xff0c;计算机视觉技术在美颜领域的应用变得越来越重要。接下来&#xff0c;小编将讲解深度学习在美颜SDK中的应用&#xff0c;以及它如何改变我们对美颜技术的认识和期待。 一、美颜技术的发展 虽然美颜技术可以在一定程度上改善图像质量&#xff0c;但往往难以满足…

Vue - 4( 8000 字 Vue 入门级教程)

一&#xff1a; Vue 初阶 1.1 关于不同版本的 Vue Vue.js 有不同版本&#xff0c;如 vue.js 与 vue.runtime.xxx.js&#xff0c;这些版本主要针对不同的使用场景和需求进行了优化&#xff0c;区别主要体现在以下几个方面&#xff1a; 完整版 vs 运行时版&#xff1a; vue.js&…