共计 2500 个字符,预计需要花费 7 分钟才能阅读完成。
向 Spring 容器中注册组件是最常见的操作,不过组件注册的方式有很多种,可以选择合适的方式进行注册。
1. @ComponentScan
注解
这种方式会将指定包下配置了 @Component
、@Controller
、@Service
、@Repository
的组件注册到容器中。
另外 @ComponentScan
注册组件可以指定和排除
某些类或者用注解标记的某些类。
例如:
// 这里的 @Configuration 注解其实也是一个 @Component
@Configuration
@ComponentScan(
value = {"com.amjun.annotation.register.register_01"},
excludeFilters = {
@ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE, classes= MyService.class)
}
)
public class Config {}
这种方式一般用于将自己编写的代码进行注册,因为第三方的代码可能不包含这些注解。
2. @Bean
注解
@Bean
注解是一个常见的注解,它等价于 xml 配置文件中的
例如:
@Configuration
public class Config {
@Lazy
@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
@Bean
public Person person(){
return new Person("zs", 18);
}
}
还可以可以通过 @Scope
配置注册到容器是单例还是多例,通过 @Lazy
控制是否懒加载创建。(spring 默认是直接初始化放入容器中,使用该注解后需要时再创建)
3. @Import
注解
@Import
允许将一个或多个类注册到 Spring 容器中,这些类会被作为 Bean 进行管理。关于它的使用,有以下几种方式。
- 导入普通类
该普通类可以是什么都没有标注的类,也可以是自己或第三方标注了 @Configuration
的配置类。
@Configuration
@Import(Person.class)
public class Config {
}
或者:
@Configuration
@Import(TestImportConfig.class)
public class Config {
}
@Configuration
public class TestImportConfig {
@Bean
public Person person(){
return new Person("zs", 18);
}
}
- 使用
ImportSelector
动态选择类
ImportSelector
是一个接口,允许根据条件动态选择导入的类。
@Configuration
@Import(MyImportSelector.class)
public class Config_02 {
}
public class MyImportSelector implements ImportSelector {
@Override
public String[] selectImports(AnnotationMetadata importingClassMetadata) {
return new String[]{"com.amjun.annotation.register.register_03.Person"};
}
}
selectImports
方法返回的类名会被动态加载到应用上下文中,它的返回是一个数组,意味着可以批量注册。
- 使用
ImportBeanDefinitionRegistrar
ImportBeanDefinitionRegistrar
是一个接口,通过实现 registerBeanDefinitions
接口,拿到 BeanDefinitionRegistry
进行手动注册。
所有需要注册到 spring 容器中的组件,扫描后会组装成一个个
BeanDefinition
,并注册到BeanDefinitionRegistry
中,再进行初始化。
@Configuration
@Import(MyImportBeanDefinitionRegistrar.class)
public class Config_03 {
}
public class MyImportBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar {
@Override
public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
RootBeanDefinition beanDefinition = new RootBeanDefinition(Person.class);
registry.registerBeanDefinition("person", beanDefinition);
}
}
4. FactoryBean
接口
FactoryBean
是 spring 提供的特殊接口,实现了 FactoryBean
接口的类,从 spring 容器中获取时,不是返回对象本身,而是 getObject()
方法返回的对象。这就提供了一种扩展的可能,可以在这个方法里定制创建复杂的逻辑。
@Configuration
public class Config {
@Bean
public PersonFactoryBean person(){
return new PersonFactoryBean();
}
}
public class PersonFactoryBean implements FactoryBean<Person> {
@Override
public Person getObject() throws Exception {
return new Person("lisi", 100);
}
@Override
public Class<?> getObjectType() {
return Person.class;
}
}