目录
一、前言
@Import导入的类会被Spring加载到IOC容器中。而@Import提供4中用法:
- 导入Bean
- 导入配置类
- 导入 ImportSelector 实现类。一般用于加载配置文件中的类
- 导入 ImportBeanDefinitionRegistrar 实现类。
二、 定义
@Import注解定义如下,其内部只有一个参数为Class对象数组
@Target(ElementType.TYPE)@Retention(RetentionPolicy.RUNTIME)@Documentedpublic@interfaceImport{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 forSpringBoot</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类
packagecom.ldx.importannotation;importlombok.AllArgsConstructor;importlombok.Data;/**
* 用户信息实体
* @author ludangxin
* @date 2021/8/1
*/@Data@AllArgsConstructorpublicclassUser{publicUser(){this.name ="李四";this.age =13;}privateString name;privateInteger age;}
3.2 测试导入Bean
3.2.1 修改启动类
importlombok.extern.slf4j.Slf4j;importorg.springframework.boot.SpringApplication;importorg.springframework.boot.autoconfigure.SpringBootApplication;importorg.springframework.context.ConfigurableApplicationContext;importorg.springframework.context.annotation.Import;@Slf4j// 注入UserBean@Import(value =User.class)@SpringBootApplicationpublicclassImportAnnotationApplication{publicstaticvoidmain(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类
importorg.springframework.context.annotation.Bean;/**
* 用户配置类
* @author ludangxin
* @date 2021/8/1
*/publicclassUserConfig{@BeanpublicUsergetUser(){returnnewUser();}}
3.3.2 修改启动类
将启动类上的@Import的value指向UserConfig类
@Import(value =UserConfig.class)
UserBean注入成功。
3.4 测试导入ImportSelector
3.4.1 创建UseImportSelector类
importorg.springframework.context.annotation.ImportSelector;importorg.springframework.core.type.AnnotationMetadata;/**
* 用户Bean选择器配置类
* @author ludangxin
* @date 2021/8/1
*/publicclassUseImportSelectorimplementsImportSelector{@OverridepublicString[]selectImports(AnnotationMetadata importingClassMetadata){// 指定User类的全限类名returnnewString[]{"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
packagecom.ldx.importannotation;importorg.springframework.beans.factory.config.BeanDefinition;importorg.springframework.beans.factory.support.BeanDefinitionBuilder;importorg.springframework.beans.factory.support.BeanDefinitionRegistry;importorg.springframework.context.annotation.ImportBeanDefinitionRegistrar;importorg.springframework.core.type.AnnotationMetadata;/**
* 用户Bean定义注册配置类
* @author ludangxin
* @date 2021/8/1
*/publicclassUserImportBeanDefinitionRegistrarimplementsImportBeanDefinitionRegistrar{@OverridepublicvoidregisterBeanDefinitions(AnnotationMetadata importingClassMetadata,BeanDefinitionRegistry registry){// 创建User类型的Bean的定义BeanDefinition beanDefinition =BeanDefinitionBuilder.rootBeanDefinition(User.class).getBeanDefinition();// 将创建的UserBean定义注册到SpringRegistry中,其名称为user
registry.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 创建注解
packagecom.ldx.importannotation;importorg.springframework.context.annotation.Import;importjava.lang.annotation.*;/**
* 启用User配置信息注解
* @author ludangxin
* @date 2021/8/1
*/@Target(ElementType.TYPE)@Retention(RetentionPolicy.RUNTIME)@Documented// 指定需要导入的UserBean的配置类@Import(UseImportSelector.class)public@interfaceEnableUser{}
4.2 修改启动类
注掉之前的@Import,使用刚创建的@EnableUser注解
importlombok.extern.slf4j.Slf4j;importorg.springframework.boot.SpringApplication;importorg.springframework.boot.autoconfigure.SpringBootApplication;importorg.springframework.context.ConfigurableApplicationContext;importorg.springframework.context.annotation.Import;@Slf4j//@Import(value = UserImportBeanDefinitionRegistrar.class)@EnableUser@SpringBootApplicationpublicclassImportAnnotationApplication{publicstaticvoidmain(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 forSpringBoot</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类
packagecom.ldx.user;importlombok.AllArgsConstructor;importlombok.Data;importlombok.NoArgsConstructor;importjava.util.ArrayList;importjava.util.List;/**
* 用户信息类
* @author ludangxin
* @date 2021/8/1
*/@Data@NoArgsConstructor@AllArgsConstructorpublicclassUser{privateInteger id;privateString name;/**
* 角色状态吗 1.管理员 2.老师 3.学生
*/privateCharacter role;privateInteger age;publicUsergetUserInfo(){returnnewUser(66,"张三",'3',21);}/**
* 获取其任课老师信息
*/publicList<User>getTeachers(){List<User> users =newArrayList<>();User user =newUser();
user.setId(2);
user.setName("王麻子");
user.setAge(45);
user.setRole('2');User user1 =newUser();
user1.setId(3);
user1.setName("李四");
user1.setAge(35);
user1.setRole('2');
users.add(user);
users.add(user1);return users;}}
5.2.3 修改启动类
importlombok.extern.slf4j.Slf4j;importorg.springframework.boot.SpringApplication;importorg.springframework.boot.autoconfigure.SpringBootApplication;importorg.springframework.context.ConfigurableApplicationContext;importorg.springframework.context.annotation.Bean;@Slf4j@SpringBootApplicationpublicclassUserApplication{publicstaticvoidmain(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));}@BeanpublicUsergetUser(){returnnewUser();}}
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 forSpringBoot</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方法
importcom.ldx.user.User;importlombok.extern.slf4j.Slf4j;importorg.springframework.boot.SpringApplication;importorg.springframework.boot.autoconfigure.SpringBootApplication;importorg.springframework.context.ConfigurableApplicationContext;@Slf4j@SpringBootApplicationpublicclassBookManageApplication{publicstaticvoidmain(String[] args){ConfigurableApplicationContext applicationContext =SpringApplication.run(BookManageApplication.class, args);User user = applicationContext.getBean(User.class);
log.info("user info === {}", user.getUserInfo());}}
六、 在user模块中添加Enable注解
importorg.springframework.context.annotation.Import;importjava.lang.annotation.*;/**
* 启用User配置信息注解
* @author ludangxin
* @date 2021/8/1
*/@Target(ElementType.TYPE)@Retention(RetentionPolicy.RUNTIME)@Documented@Import(User.class)public@interfaceEnableUser{}
七、小结
不能直接在当前项目中使用Jar中的Bean(SpringBoot默认使用ImportSelector的方式加载META-INF/spring.factories中指定的配置类,会导致只需要导入相应的第三方Jar就可以使用其环境中的Bean)
可以在当前项目中使用Jar包中提供的Enable注解来导入Jar的Bean配置
版权归原作者 从零开始的-CodeNinja之路 所有, 如有侵权,请联系我们删除。