Spring注解@Import实现多模块中Bean的导入
2021-04-01 15:27
标签:multi ini policy figure 同学会 sel assm 情况 接口 很多时候我们的Spring项目使用多模块,或者我们需要将自己特定的类库打成依赖。默认情况下Spring Boot应用只会扫描main方法所在的包路径下的Bean和通过 Maven多目录项目 今天我们将借助于 以上是我们在 我们可以很容易地利用 我们也可以通过 第一个方法 但是 实现 然后把 最后标记在Spring Boot启动类上: 这里我特意增加了一个 最后我们写个测试: 经过测试断言成立,同时控制台将注解元数据 也就是说 另外还有一个 Spring注解@Import实现多模块中Bean的导入 标签:multi ini policy figure 同学会 sel assm 情况 接口 原文地址:https://blog.51cto.com/14901317/2523046spring.factories
进行注册发现自动装配到Spring IoC中去。像下面这个Maven项目中,如果Spring Boot的Main类在cn.felord.yaml
包下的话cn.felord.common
包的Spring Bean是无法被扫描注册到Spring IoC容器中的。@Import
注解和相关的一些接口来实现特定路径下的Spring Bean的导入。2. @Import
@Import
注解主要提供配置类导入的功能。我们可以从Spring Boot的很多@EnableXX
注解中发现它的影子,例如开启缓存注解@EnableCaching
、开启异步注解@EnableAsync
等等。它提供了半自动的功能,让我们可以即使引入了对应的依赖时也可以手动来控制一些配置的生效。package cn.felord.common;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* @author felord.cn
*/
public class CommonConfiguration {
@Bean
public FooService fooService(){
return () -> "@Import";
}
}
cn.felord.common
下实现的一个配置,目的是将FooService
的实现注册为Spring Bean
。可能很多同学会想到使用@ComponentScan("cn.felord.common")
来实现,这当然是可以实现的。问题在于这个声明讲所有在cn.felord.common
包下的Spring Bean都注册了,控制的粒度比较粗。如果我们想控制的粒度细一些,指定哪些被导入哪些不被导入,使用 @Import
就再好不过了。@Import
可以将@Configuration
标记的类、ImportSelector
的实现类以及ImportBeanDefinitionRegistrar
的实现类导入。在Spring 4.2版本以后,普通的类(如上面代码中的CommonConfiguration
)也可以被导入,将其注册为Spring Bean。@Import(CommonConfiguration.class)
@Import
注解开发出一些@EnableXX
注解来控制一些功能是否生效。/**
* @author felord.cn
* @since 10:35
**/
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import(CommonConfiguration.class)
public @interface EnableCommon {
}
ImportSelector
接口来实现更加强大的功能3. ImportSelector
ImportSelector
接口是按照给定的标准,通常是根据一到多个注解参数来决定那个配置类应该被导入。也就是说我们可以在上面的@EnableCommon
注解中添加注解参数来实现更加灵活的导入。public interface ImportSelector {
/**
* 基于导入的配置类的注解元信息来检出并决定哪些类应该被导入。
* 返回被导入的类的全限定名数组,如果没有则返回一个空数组。
*/
String[] selectImports(AnnotationMetadata importingClassMetadata);
/**
* 返回一个谓词接口,该接口制定了一个对类全限定名的排除规则来过滤一些候选的导入类,默认不排除过滤。
*
* @since 5.2.4
*/
@Nullable
default Predicate
selectImports
我们大致上可以理解为通过importingClassMetadata
提供的信息来决定哪些类导入。如果存在第二个方法getExclusionFilter
的实现。会对selectImports
方法的返回值进行过滤,最终输出哪些配置类可以导入Spring IoC。importingClassMetadata
从哪里来可能是我们最想知道的,我们来一探究竟。先写一个配置类:/**
* @author felord.cn
* @since 10:27
**/
public class BarConfiguration {
@Bean
public Function
ImportSelector
:/**
* @author felord.cn
* @since 10:19
**/
public class CommonImportSelector implements ImportSelector {
@Override
public String[] selectImports(AnnotationMetadata importingClassMetadata) {
System.out.println("importingClassMetadata.getAnnotationTypes() = " + importingClassMetadata.getAnnotationTypes());
return new String[]{CommonConfiguration.class.getName(), BarConfiguration.class.getName()};
}
}
@EnableCommon
注解扩展一下:/**
* @author felord.cn
* @since 10:35
**/
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import(CommonImportSelector.class)
public @interface EnableCommon {
boolean isBar() default false;
}
@EnableCommon
@EnableAsync
@SpringBootApplication
public class SpringSelectorApplication {
public static void main(String[] args) {
SpringApplication.run(SpringSelectorApplication.class, args);
}
}
@EnableAsync
注解来看看能否打印出来。@SpringBootTest
class SpringSelectorApplicationTests {
@Resource
Function
importingClassMetadata
的结果打印了出来:importingClassMetadata.getAnnotationTypes() = [cn.felord.common.EnableCommon,
org.springframework.boot.autoconfigure.SpringBootApplication, org.springframework.scheduling.annotation.EnableAsync]
importingClassMetadata
包含了@Import
所依附的配置类上的所有注解。这意味着我们可以拿到对应注解的元信息并作为我们动态导入的判断依据。举个例子:/**
* @author felord.cn
* @since 10:19
**/
public class CommonImportSelector implements ImportSelector {
@Override
public String[] selectImports(AnnotationMetadata importingClassMetadata) {
// 当存在注解 EnableCommon 时 取其useBar 布尔值 true 导入 BarConfiguration
// 其它任何情况将导入 CommonConfiguration 和 BarConfiguration
if (importingClassMetadata.hasAnnotation(EnableCommon.class.getName())) {
MultiValueMap
ImportSelector
的变种接口DeferredImportSelector
。它的特点是所有的配置(@Configuration
)类都处理完才进行选择导入,而ImportSelector
正相反。另外 DeferredImportSelector
还提供了分组过滤、排序的功能。在导入条件配置@Conditional
时特别有用。4. 总结
@Import
注解的相关系列非常有用,特别是项目分包,多模块之间的Spring Bean管理,自定义Spring Boot Starter等场景中。
文章标题:Spring注解@Import实现多模块中Bean的导入
文章链接:http://soscw.com/index.php/essay/70986.html