【Spring Boot】SpringBoot自动装配-Import
目录
- 一、前言
- 二、 定义
- 三、使用说明
- 3.1 创建项目
- 3.1.1 导入依赖
- 3.1.2 创建User类
- 3.2 测试导入Bean
- 3.2.1 修改启动类
- 3.3 测试导入配置类
- 3.3.1 创建UserConfig类
- 3.3.2 修改启动类
- 3.4 测试导入ImportSelector
- 3.4.1 创建UseImportSelector类
- 3.4.2 修改启动类
- 3.4.3 启动测试
- 3.5 测试导入ImportBeanDefinitionRegistrar类
- 3.5.1 创建UserImportBeanDefinitionRegistrar
- 3.5.2 修改启动类
- 3.6 小结
- 四、 改进
- 4.1 创建注解
- 4.2 修改启动类
- 五、 验证
- 5.1 创建项目
- 5.2 创建user模块
- 5.2.1 导入依赖
- 5.2.2 创建User类
- 5.2.3 修改启动类
- 5.3 创建book-manage模块
- 5.3.1 导入依赖
- 5.3.2 修改启动类
- 六、 在user模块中添加Enable注解
- 七、小结


一、前言
@Import导入的类会被Spring加载到IOC容器中。而@Import提供4中用法:
-
导入Bean
-
导入配置类
-
导入 ImportSelector 实现类。一般用于加载配置文件中的类
-
导入 ImportBeanDefinitionRegistrar 实现类。
二、 定义
@Import注解定义如下,其内部只有一个参数为Class对象数组
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Import {Class<?>[] value();
}
三、使用说明
通过一个简单的小例子测试一下@Import是不是真的能实现Bean的注入
3.1 创建项目
3.1.1 导入依赖
这里我们除了springboot依赖,再添加个lombok依赖
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>2.5.3</version><relativePath/> <!-- lookup parent from repository --></parent><groupId>com.ldx</groupId><artifactId>import-annotation</artifactId><version>0.0.1-SNAPSHOT</version><name>import-annotation</name><description>Demo project for Spring Boot</description><properties><java.version>1.8</java.version></properties><dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter</artifactId></dependency><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><optional>true</optional></dependency></dependencies><build><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId><configuration><excludes><exclude><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId></exclude></excludes></configuration></plugin></plugins></build>
</project>
3.1.2 创建User类
package com.ldx.importannotation;import lombok.AllArgsConstructor;
import lombok.Data;/*** 用户信息实体* @author ludangxin* @date 2021/8/1*/
@Data
@AllArgsConstructor
public class User {public User() {this.name = "李四";this.age = 13;}private String name;private Integer age;
}
3.2 测试导入Bean
3.2.1 修改启动类
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.annotation.Import;@Slf4j
// 注入UserBean
@Import(value = User.class)
@SpringBootApplication
public class ImportAnnotationApplication {public static void main(String[] args) {ConfigurableApplicationContext applicationContext = SpringApplication.run(ImportAnnotationApplication.class, args);User user = applicationContext.getBean(User.class);log.info("user info ==={}",user);}
}
3.3 测试导入配置类
3.3.1 创建UserConfig类
import org.springframework.context.annotation.Bean;/*** 用户配置类* @author ludangxin* @date 2021/8/1*/
public class UserConfig {@Beanpublic User getUser(){return new User();}
}
3.3.2 修改启动类
将启动类上的@Import的value指向UserConfig类
@Import(value = UserConfig.class)
UserBean注入成功。
3.4 测试导入ImportSelector
3.4.1 创建UseImportSelector类
import org.springframework.context.annotation.ImportSelector;
import org.springframework.core.type.AnnotationMetadata;/*** 用户Bean选择器配置类* @author ludangxin* @date 2021/8/1*/
public class UseImportSelector implements ImportSelector {@Overridepublic String[] selectImports(AnnotationMetadata importingClassMetadata) {// 指定User类的全限类名return new String[]{"com.ldx.importannotation.User"};}
}
3.4.2 修改启动类
将启动类上的@Import的value指向UseImportSelector类
@Import(value = UseImportSelector.class)
3.4.3 启动测试
UserBean注入成功。
3.5 测试导入ImportBeanDefinitionRegistrar类
3.5.1 创建UserImportBeanDefinitionRegistrar
package com.ldx.importannotation;import org.springframework.beans.factory.config.BeanDefinition;
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;/*** 用户Bean定义注册配置类* @author ludangxin* @date 2021/8/1*/
public class UserImportBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar {@Overridepublic void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {// 创建User类型的Bean的定义BeanDefinition beanDefinition = BeanDefinitionBuilder.rootBeanDefinition(User.class).getBeanDefinition();// 将创建的UserBean定义注册到SpringRegistry中,其名称为userregistry.registerBeanDefinition("user", beanDefinition);}
}
3.5.2 修改启动类
将启动类上的@Import的value指向UserImportBeanDefinitionRegistrar类
@Import(value = UserImportBeanDefinitionRegistrar.class)
3.6 小结
简介中介绍的四种方式都可以注入UserBean。
好处:
- 导入指定的Bean或配置类。例如:由于业务需要将包路径或者需要加载的Bean类不在@ComponentScan的扫描范围内,这时候我们就可以通过@Import来实现Bean的注入。
- ImportSelector方式是制定需要加载类的全限类名。这时候我们就可以将我们的需要装载的类写到配置文件中,比如某个txt中,然后项目启动的时候读取txt中的全限类名,实现Bean的装载。SpringBoot就是使用这种方式实现的自动装配。
四、 改进
上面的例子通过使用@Import注解实现了spring bean的自动注入。但是装载Bean每次都得指定Bean的类或者配置类,在生产环境中我们在使用第三方Jar的时候根本不知道应该使用哪个配置文件或者压根就不知道配置文件的名称。这时我们其实可以扩展一个注解来优化这个问题。
4.1 创建注解
package com.ldx.importannotation;import org.springframework.context.annotation.Import;
import java.lang.annotation.*;/*** 启用User配置信息注解* @author ludangxin* @date 2021/8/1*/
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
// 指定需要导入的UserBean的配置类
@Import(UseImportSelector.class)
public @interface EnableUser {}
4.2 修改启动类
注掉之前的@Import,使用刚创建的@EnableUser注解
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.annotation.Import;@Slf4j
//@Import(value = UserImportBeanDefinitionRegistrar.class)
@EnableUser
@SpringBootApplication
public class ImportAnnotationApplication {public static void main(String[] args) {ConfigurableApplicationContext applicationContext = SpringApplication.run(ImportAnnotationApplication.class, args);User user = applicationContext.getBean(User.class);log.info("user info ==={}",user);}
}
UserBean注入成功。
思考🤔
SpringBoot项目中能不能直接获取或者使用Jar包中的Bean呢?
五、 验证
5.1 创建项目
user模块为Bean的提供者,book-manage通过引入user模块Jar,来验证项目中能不能直接使用Jar中的Bean
5.2 创建user模块
5.2.1 导入依赖
没啥特别的依赖
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>2.5.3</version><relativePath/> <!-- lookup parent from repository --></parent><groupId>com.ldx</groupId><artifactId>user</artifactId><version>0.0.1-SNAPSHOT</version><name>user</name><description>Demo project for Spring Boot</description><properties><java.version>1.8</java.version></properties><dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter</artifactId></dependency><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><optional>true</optional></dependency></dependencies><build><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId><configuration><excludes><exclude><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId></exclude></excludes></configuration></plugin></plugins></build></project>
5.2.2 创建User类
package com.ldx.user;import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.util.ArrayList;
import java.util.List;/*** 用户信息类* @author ludangxin* @date 2021/8/1*/
@Data
@NoArgsConstructor
@AllArgsConstructor
public class User {private Integer id;private String name;/*** 角色状态吗 1.管理员 2.老师 3.学生*/private Character role;private Integer age;public User getUserInfo() {return new User(66, "张三", '3', 21);}/*** 获取其任课老师信息*/public List<User> getTeachers() {List<User> users = new ArrayList<>();User user = new User();user.setId(2);user.setName("王麻子");user.setAge(45);user.setRole('2');User user1 = new User();user1.setId(3);user1.setName("李四");user1.setAge(35);user1.setRole('2');users.add(user);users.add(user1);return users;}
}
5.2.3 修改启动类
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.annotation.Bean;@Slf4j
@SpringBootApplication
public class UserApplication {public static void main(String[] args) {ConfigurableApplicationContext applicationContext = SpringApplication.run(UserApplication.class, args);User user = applicationContext.getBean(User.class);user.getTeachers().forEach(obj ->log.info("user teacher info ==={} ", obj));}@Beanpublic User getUser() {return new User();}
}
5.3 创建book-manage模块
5.3.1 导入依赖
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>2.5.3</version><relativePath/> <!-- lookup parent from repository --></parent><groupId>com.ldx</groupId><artifactId>book-manage</artifactId><version>0.0.1-SNAPSHOT</version><name>book-manage</name><description>Demo project for Spring Boot</description><properties><java.version>1.8</java.version></properties><dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter</artifactId></dependency><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><optional>true</optional></dependency><!-- user模块依赖 --><dependency><groupId>com.ldx</groupId><artifactId>user</artifactId><version>0.0.1-SNAPSHOT</version></dependency></dependencies><build><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId><configuration><excludes><exclude><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId></exclude></excludes></configuration></plugin></plugins></build></project>
5.3.2 修改启动类
直接获取User Bean 并调用getUserInfo方法
import com.ldx.user.User;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ConfigurableApplicationContext;@Slf4j
@SpringBootApplication
public class BookManageApplication {public static void main(String[] args) {ConfigurableApplicationContext applicationContext = SpringApplication.run(BookManageApplication.class, args);User user = applicationContext.getBean(User.class);log.info("user info === {}", user.getUserInfo());}}
六、 在user模块中添加Enable注解
import org.springframework.context.annotation.Import;
import java.lang.annotation.*;/*** 启用User配置信息注解* @author ludangxin* @date 2021/8/1*/
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import(User.class)
public @interface EnableUser {}
七、小结
不能直接在当前项目中使用Jar中的Bean(SpringBoot默认使用ImportSelector的方式加载META-INF/spring.factories中指定的配置类,会导致只需要导入相应的第三方Jar就可以使用其环境中的Bean)
可以在当前项目中使用Jar包中提供的Enable注解来导入Jar的Bean配置
相关文章:

【Spring Boot】SpringBoot自动装配-Import
目录 一、前言二、 定义三、使用说明3.1 创建项目3.1.1 导入依赖3.1.2 创建User类 3.2 测试导入Bean3.2.1 修改启动类 3.3 测试导入配置类3.3.1 创建UserConfig类3.3.2 修改启动类 3.4 测试导入ImportSelector3.4.1 创建UseImportSelector类3.4.2 修改启动类3.4.3 启动测试 3.5…...

C++:opencv计算轮廓周长--cv::arcLength
cv::arcLength 是 OpenCV 中用于计算轮廓的周长或曲线长度的函数。它是计算图像轮廓特征时非常有用的工具,特别是在处理形状分析、对象检测等任务时。 函数原型 double cv::arcLength(const cv::InputArray& curve, bool closed);curve: 输入的曲线或轮廓&…...

探索学习Python的最佳开发环境和编辑器
Python,作为目前最受欢迎的编程语言之一,因其简洁明了的语法和强大的功能性而备受开发者喜爱。无论是数据科学、机器学习、Web开发还是自动化脚本,Python都有着广泛的应用。选择合适的开发环境和编辑器对于提高编程效率和学习体验至关重要。 …...

【Pycharm】Pycharm创建Django提示pip版本需要升级
目录 1、现象 2、分析 3、本质 前言:经常使用pycharm创建django、flask等项目时候提示pip版本需要升级,解决方案 1、现象 使用Pycharm创建Django项目提示安装Django超时,报错建议pip升级22升级到24 2、分析 之前使用命令升级了pip到了24…...

模拟退火算法(SA算法)求解实例---旅行商问题 (TSP)
目录 一、采用SA求解 TSP二、 旅行商问题2.1 实际例子:求解 6 个城市的 TSP2.2 **求解该问题的代码**2.3 代码运行过程截屏2.4 代码运行结果截屏(后续和其他算法进行对比) 三、 如何修改代码?3.1 减少城市坐标,如下&am…...

衡石分析平台使用手册--替换衡石 metadb
替换衡石 metadb 在使用 HENGSHI SENSE 服务过程中,可以根据业务需要替换 HENGSHI 自带的 metadb。本文讲述使用云服务 PostgreSQL 替代衡石 metadb 的过程。 准备工作 在进行配置前,请在云服务 PostgreSQL 上完成如下准备工作。 [必须] 配置衡石…...

【Unity学习心得】如何制作俯视角射击游戏
提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录 前言一、导入素材二、制作流程 1.制作地图2.实现人物动画和移动脚本3.制作单例模式和对象池4.制作手枪pistol和子弹bullet和子弹壳bulletShell5.制作散弹枪shotgun总…...

【资料分析】常见的坑
in 比较或计数类问题 差别大的基期比较,可以直接用现期进行比较 注意单位可能不同! 注意顺序是从小到大还是从大到小 以及老问题,名字本身就叫XX增量,XX增加值,而非还要另外去算的东东 给出的图表可能是不完整的 2…...

GitLab权限及设置
之前很少关注这些,项目的权限,一般由专门的管理人员设置。 但自己创建的项目自己可以设置权限。下面是一些笔记。 GitLab中用户权限_gitlab 权限-CSDN博客 开发中遇到要将自己这块的代码上传到Git,由其他组的同事拉取后继续开发。上传代码后…...

算法练习题24——查找杨辉三角中的组合数
题目描述 杨辉三角中的每个元素是一个组合数。第 ( i ) 行的第 ( j ) 个元素表示组合数 ( C(i, j) ) ,即从 ( i ) 个元素中选 ( j ) 个元素的组合方式。已知一个正整数 ( N ),要求在杨辉三角中找到这个数,并输出它在杨辉三角中的具体位置。位…...

string类的模拟实现
实现string的模拟实现分为三个文件,分别为:string.h、sting.cpp、test.cpp string.h 其中包含一些短小常用的函数的实现,头文件,函数的声明 #include<iostream> #include<string> #include<assert.h>using n…...

如何训练机器学习力场
机器学习力场(MLFF)的训练主要依赖于通过量子力学计算生成的高质量训练数据集,并利用不同的机器学习算法来拟合分子系统中的势能面(Potential Energy Surface, PES)和原子间作用力。这种训练过程包括数据准备、特征提取…...

AI创作新手册:精通Prompt提示词的提问策略
文章目录 🍊AI创作核心:提示词 Prompt 的重要性1. 什么是提示词工程?1.1 提示词的作用原理1.2 提示词工程师的薪资与行业前景1.3 提示词工程的适用性 2. 提示词的编写技巧3. 常见的提示词框架3.1 CO-STAR 框架3.2 BORKE 框架 4. 提示词的实际…...

gingivitis
gingivitis 牙龈炎 1)这个是啥不知道 2)七叶莲片 3)甲硝唑芬布芬胶囊 4)盐酸左氧氟沙星胶囊 5)纳珍 开始学习记录医生开的药。日常备药记录一下。【不要乱吃药哈】...

开源 AI 智能名片小程序:开启内容营销新境界
摘要:本文深入探讨了在当今数字化时代,内容营销的重要性以及如何实现让用户主动找你的最佳效果。通过引入开源 AI 智能名片小程序这一创新工具,阐述了其在明确目标用户群体、迎合用户需求痛点和打造风格特色方面的独特优势,为企业…...

p12docker 进入容器的命令和拷贝的命令
进入当前正在运行的容器 第一种方式是执行docker exec -it 8d57ffda7a29 /bin/bash这个时候可以根据docker容器的id进入到指定id的容器当中***(这个是比较常用的)*** 老师的笔记 第二种方式是docker attach 8d57ffda7a29 这里还是直接引用老师的笔记吧 从容器内部拷贝文…...

代码随想录Day 45|leetcode题目:115.不同的子序列、583. 两个字符串的删除操作、72. 编辑距离
提示:DDU,供自己复习使用。欢迎大家前来讨论~ 文章目录 题目题目一: 115.不同的子序列解题思路:1. 确定dp数组(dp table)以及下标的含义2. 确定递推公式3. dp数组如何初始化4. 确定遍历顺序5. 举例推导dp数…...

浮点数在内存中的存储详解(超详细)
目录 1. 浮点数存储规则 2. IEEE754规定: 3. 关于M的说明: 4. 关于E的说明: 5. 关于S的说明: 6.浮点数从内存中取出(三种情况) 情况1:E不全为0或不全为1 情况2:E全为0 情况3&a…...

Maven下载安装
下载 下载地址:Maven – Download Apache Maven 选择合适的版本进行下载 windows&Linux安装 1, 解压apache-maven-3.6.1.rar即安装完成 2, 配置环境变量MAVEN_HOME为安装路径,并将MAVEN_HOME的bin目录配置到PATH下 3,…...

Qt:Q_GLOBAL_STATIC实现单例(附带单例使用和内存管理)
前言 本文主要写Q_GLOBAL_STATIC实现单例以及单例的释放,网上很多教程只有单例的创建,但是并没有告诉我们单例的内存管理,这就很头疼。 正文 使用 Qt 的 Q_GLOBAL_STATIC // Singleton.h #ifndef SINGLETON_H #define SINGLETON_H#includ…...

URL.createObjectURL 与 FileReader:Web 文件处理两大法宝的对比
URL.createObjectURL 与 FileReader:Web 文件处理两大法宝的对比 在Web开发中,处理用户上传的文件是一项常见且重要的任务。URL.createObjectURL和FileReader是两种常用于此目的的Web API,它们各有特点,适用于不同的场景。本文将…...

零基础考过软考信息系统项目管理师经验分享
选择适合的课程:如果你是零基础,建议找一些专门针对新手的课程,讲解通俗易懂。 刷题至关重要:软考的题库很庞大,多做题是必须的。 做好笔记和复习:上课时要做好笔记,课后及时复习,…...

机器学习课程学习周报十二
机器学习课程学习周报十二 文章目录 机器学习课程学习周报十二摘要Abstract一、机器学习部分1.1 fGAN: General Framework of GAN1.2 CycleGAN1.3 Auto-Encoder1.4 概率论复习(一) 总结 摘要 本周的学习内容涵盖了fGAN框架、CycleGAN、自编码器以及概率…...

python多线程程序设计 之二
python多线程程序设计 之二 线程同步机制lock对象acquirereleaselocked RLock对象条件变量条件变量应用实列实列代码 线程同步机制 lock对象 原语锁是一种同步原语,锁定时不属于特定线程。在Python中,它是目前可用的最低级别的同步原语,由_…...

k8s用StatefulSet部署redis
redis-config.yaml (配置文件) apiVersion: v1 kind: ConfigMap metadata:name: redis-config data:redis.conf: |# Redis general configuration bind 0.0.0.0 protected-mode no port 6379 dir /data appendonly yesse…...

flink on k8s
1.修改host文件 vi /etc/hosts 添加如下内容 这样搭集群的时候就不用记ip了 #::1 localhost localhost.localdomain localhost6 localhost6.localdomain6127.0.0.1 localhost localhost.localdomain localhost4 localhost4.localdomain4 165.154.221.97 tlb-001 k8s01 k8s-m…...

Java集合(八股)
这里写目录标题 Collection 接口List 接口ArrayList 简述 1. ArrayList 和 LinkedList 区别?⭐️⭐️⭐️⭐️2. ArrayList 和 Array 的区别?⭐️⭐️⭐️ArrayList 和 Vector 区别?⭐️⭐️ArrayList 的扩容机制?⭐️⭐️⭐️ Qu…...

python+adb
#!/usr/bin/python env # -*- coding: utf-8 -*- import os import sys import subprocess from time import sleepimport logging logging.basicConfig(levellogging.DEBUG) class ScreenCapture():def get_screen_size(self):"""获取手机分辨率""&q…...

AIGC文本生成
文本生成是一种人工智能技术,它基于深度学习算法,根据给定的提示信息创作出有逻辑、连贯的文本内容。 文本生成所需的输入(提示或Prompt)可以是简单的关键词、一句话概述或是更复杂的指令和上下文信息。文本生成模型通过分析大量…...

系统架构设计师教程 第5章 5.4 软件测试 笔记
5.4 软件测试 5.4.1 测试方法 ★★★★★ 软件测试方法的分类有很多种, 以测试过程中程序执行状态为依据可分为静态测试 (Static Testing,ST) 和动态测试 (Dynamic Testing,DT); 以具体实现算法细节和系统内部结构的相关情况为根据可分黑盒测试、白盒测试和灰盒测…...