在原生的 SpringFramework 中,装配组件有三种方式:
@Component
等(Spring2.5+)@Configuration
与 @Bean
(Spring3.0+)@EnableXXX
与 @Import
(Spring3.1+)其中使用 @Component
及衍生注解很常见,咱开发中常用的套路,不再赘述。
但模式注解只能在自己编写的代码中标注,无法装配jar包中的组件。为此可以使用 @Configuration
与 @Bean
,手动装配组件(如上一篇的 @Configuration
示例)。
但这种方式一旦注册过多,会导致编码成本高,维护不灵活等问题。
SpringFramework 提供了模块装配功能,通过给配置类标注 @EnableXXX
注解,再在注解上标注 @Import
注解,即可完成组件装配的效果。
下面介绍模块装配的使用方式。
创建几个颜色的实体类,如Red,Yellow,Blue,Green,Black等。
新建 @EnableColor 注解,并声明 @Import
。(注意注解上有三个必须声明的元注解)
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface EnableColor {
}
@Import
可以传入四种类型:普通类、配置类、ImportSelector
的实现类,ImportBeanDefinitionRegistrar
的实现类。具体如文档注释中描述:
public @interface Import {
/**
* {@link Configuration @Configuration}, {@link ImportSelector},
* {@link ImportBeanDefinitionRegistrar}, or regular component classes to import.
*/
Class>[] value();
}
value中写的很明白了,可以导入配置类、ImportSelector
的实现类,ImportBeanDefinitionRegistrar
的实现类,或者普通类。
下面介绍 @Import
的用法。
5.1.1 导入普通类
直接在 @Import
注解中标注Red类:
@Import({Red.class})
public @interface EnableColor {
}
之后启动类标注 @EnableColor,引导启动IOC容器:
@EnableColor
@Configuration
public class ColorConfiguration {
}
public class App {
public static void main(String[] args) throws Exception {
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(ColorConfiguration.class);
String[] beanDefinitionNames = ctx.getBeanDefinitionNames();
Stream.of(beanDefinitionNames).forEach(System.out::println);
}
}
控制台打印:
org.springframework.context.annotation.internalConfigurationAnnotationProcessor
org.springframework.context.annotation.internalAutowiredAnnotationProcessor
org.springframework.context.annotation.internalCommonAnnotationProcessor
org.springframework.context.event.internalEventListenerProcessor
org.springframework.context.event.internalEventListenerFactory
colorConfiguration
com.example.demo.enablexxx.Red
可见Red类已经被注册。
5.1.2 导入配置类
新建 ColorRegistrarConfiguration,并标注 @Configuration
:
@Configuration
public class ColorRegistrarConfiguration {
@Bean
public Yellow yellow() {
return new Yellow();
}
}
之后在 @EnableColor 的 @Import
注解中加入 ColorRegistrarConfiguration:
@Import({Red.class, ColorRegistrarConfiguration.class})
public @interface EnableColor {
}
重新启动IOC容器,打印结果:
org.springframework.context.annotation.internalConfigurationAnnotationProcessor
org.springframework.context.annotation.internalAutowiredAnnotationProcessor
org.springframework.context.annotation.internalCommonAnnotationProcessor
org.springframework.context.event.internalEventListenerProcessor
org.springframework.context.event.internalEventListenerFactory
colorConfiguration
com.example.demo.enablexxx.Red
com.example.demo.enablexxx.ColorRegistrarConfiguration
yellow
可见配置类 ColorRegistrarConfiguration 和 Yellow 都已注册到IOC容器中。
5.1.3 导入ImportSelector
新建 ColorImportSelector,实现 ImportSelector
接口:
public class ColorImportSelector implements ImportSelector {
@Override
public String[] selectImports(AnnotationMetadata importingClassMetadata) {
return new String[] {Blue.class.getName(), Green.class.getName()};
}
}
之后在 @EnableColor 的 @Import
注解中加入 ColorImportSelector:
@Import({Red.class, ColorRegistrarConfiguration.class, ColorImportSelector.class})
public @interface EnableColor {
}
重新启动IOC容器,打印结果:
org.springframework.context.annotation.internalConfigurationAnnotationProcessor
org.springframework.context.annotation.internalAutowiredAnnotationProcessor
org.springframework.context.annotation.internalCommonAnnotationProcessor
org.springframework.context.event.internalEventListenerProcessor
org.springframework.context.event.internalEventListenerFactory
colorConfiguration
com.example.demo.enablexxx.Red
com.example.demo.enablexxx.ColorRegistrarConfiguration
yellow
com.example.demo.enablexxx.Blue
com.example.demo.enablexxx.Green
ColorImportSelector 没有注册到IOC容器中,两个新的颜色类被注册。
5.1.4 导入ImportBeanDefinitionRegistrar
新建 ColorImportBeanDefinitionRegistrar,实现 ImportBeanDefinitionRegistrar
接口:
public class ColorImportBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar {
@Override
public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
registry.registerBeanDefinition("black", new RootBeanDefinition(Black.class));
}
}
之后在 @EnableColor 的 @Import
注解中加入 ColorImportBeanDefinitionRegistrar:
@Import({Red.class, ColorRegistrarConfiguration.class, ColorImportSelector.class, ColorImportBeanDefinitionRegistrar.class})
public @interface EnableColor {
}
重新启动IOC容器,打印结果:
org.springframework.context.annotation.internalConfigurationAnnotationProcessor
org.springframework.context.annotation.internalAutowiredAnnotationProcessor
org.springframework.context.annotation.internalCommonAnnotationProcessor
org.springframework.context.event.internalEventListenerProcessor
org.springframework.context.event.internalEventListenerFactory
colorConfiguration
com.example.demo.enablexxx.Red
com.example.demo.enablexxx.ColorRegistrarConfiguration
yellow
com.example.demo.enablexxx.Blue
com.example.demo.enablexxx.Green
black
由于在注册Black的时候要指定Bean的id,而上面已经标明了使用 "black" 作为id,故打印的 beanDefinitionName 就是black。
以上就是 SpringFramework 的手动装配方法。