概述
一、引言
在SpringBoot还没有普及之前,我们创建Spring+SpringMVC项目的时候,首先要配置web.xml、Spring.xml、SpringMVC.xml
三个配置文件。对于下面的包扫描配置,就是把该包下的带有@Controller、@Service、@Repository、@Component
注解的组件注册到Spring容器中,在该标签中,还有include-filter、exclude-filter
属性。
<context:component-scan base-package="com.scorpios"></context:component-scan>
在SpringBoot中,我们用@Configuration
注解==配置类代替了xml文件,用@ComponentScan
注解代替了<context:component-scan>
标签,它们的意思等价。
在介绍向容器中注册组件之前,我们先来介绍一下include-filter
中的自定义规则
//excludeFilters = Filter[] :指定扫描的时候按照什么规则 排除哪些组件
//includeFilters = Filter[] :指定扫描的时候 只需要包含 哪些组件
//FilterType.ANNOTATION:按照注解
//FilterType.ASSIGNABLE_TYPE:按照给定的类型
//FilterType.CUSTOM:使用自定义规则
@Configuration
//@ComponentScan value:指定要扫描的包
@ComponentScan(value="com.scorpios",includeFilters = {
// @Filter(type=FilterType.ANNOTATION,classes={Controller.class}),
// @Filter(type=FilterType.ASSIGNABLE_TYPE,classes={BookService.class}),
@Filter(type=FilterType.CUSTOM,classes={MyTypeFilter.class})},
useDefaultFilters = false)
public class MainConfig {
// 给容器中注册一个Bean; 类型为返回值的类型,id默认是用方法名作为id
@Bean("person")
public Person person(){
return new Person("lisi", 20);
}
}
这里需要注意的是:在使用只扫描特定includeFilters属性时,要把useDefaultFilters设置为false。下面重点看一下自定义规则MyTypeFilter
。
public class MyTypeFilter implements TypeFilter {
/**
* metadataReader:读取到的,当前正在扫描的类的信息
* metadataReaderFactory:可以获取到其他任何类信息的
*/
@Override
public boolean match(MetadataReader metadataReader,
MetadataReaderFactory metadataReaderFactory)
throws IOException {
//获取当前类注解的信息
AnnotationMetadata annotationMetadata = metadataReader.getAnnotationMetadata();
//获取当前正在扫描的类的类信息
ClassMetadata classMetadata = metadataReader.getClassMetadata();
//获取当前类资源(类的路径)
Resource resource = metadataReader.getResource();
String className = classMetadata.getClassName();
System.out.println("--->"+className);
// 如果类名中包含er,则加入到Spring容器中,否则不加入容器
if(className.contains("er")){
return true;
}
return false;
}
}
二、向Spring容器中注册组件的四种方式
1、包扫描+组件标注注解
这种方式是我们最常使用的方式,对我们自己写的组件,只需要加上下面四类注解即可,@Controller、@Service、@Repository、@Component
。这里就不做过多介绍。
2、@Bean
这种方式,在SpringBoot中也最经常使用,无论是自己定义的,还是第三方的组件(比如数据源的配置),都可以直接使用该注解。这里需要注意的是:@Bean修饰方法,类型为返回值的类型,容器中组件的id默认是用方法名作为id。这里也不做过多的介绍。
3、@Import——快速给容器中导入一个组件
已知一个Color类,若要把这个类注入到Spring容器中,除了上面的两种方式,还有哪些方式呢?
public class Color {
String color;
}
(1)、@Import(要导入到容器中的组件):容器中就会自动注册这个组件,id默认是全类名;
如果想把Color注册到Spring容器中,第一种方式,使用@Import注解,只需要做如下配置即可:
@Configuration
@Import({Color.class})
public class MainConfig{
}
(2)、ImportSelector:返回需要导入的组件的全类名数组;
如果想把Color注册到Spring容器中,第二种方式,使用ImportSelector接口,需要做如下配置:
@Configuration
@Import({MyImportSelector.class}))
public class MainConfig{
}
public class MyImportSelector implements ImportSelector {
//返回值,就是到导入到容器中的组件全类名
//AnnotationMetadata:当前标注@Import注解的类的所有注解信息
@Override
public String[] selectImports(AnnotationMetadata importingClassMetadata) {
//方法不要返回null值
return new String[]{"com.scorpios.bean.Color","com.scorpios.bean.Blue"};
}
}
selectImports返回类的全类名数组,就会把返回的类全都放入Spring容器中。
(3)、ImportBeanDefinitionRegistrar:手动注册bean到容器中
如果想把Color注册到Spring容器中,第三种方式,使用ImportBeanDefinitionRegistrar接口,需要做如下配置:
@Configuration
@Import({MyImportBeanDefinitionRegistrar.class}))
public class MainConfig{
}
public class MyImportBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar {
/**
* AnnotationMetadata:当前类的注解信息
* BeanDefinitionRegistry:BeanDefinition注册类;
* 把所有需要添加到容器中的bean;
* 调用BeanDefinitionRegistry.registerBeanDefinition手工注册进来
*/
@Override
public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata,
BeanDefinitionRegistry registry) {
boolean definition = registry.containsBeanDefinition("com.scorpios.bean.Color");
boolean definition2 = registry.containsBeanDefinition("com.scorpios.bean.Blue");
if(definition && definition2){
//指定Bean定义信息;(Bean的类型)
RootBeanDefinition beanDefinition = new RootBeanDefinition(RainBow.class);
//注册一个Bean,指定bean名
registry.registerBeanDefinition("rainBow", beanDefinition);
}
}
}
4、使用Spring提供的 FactoryBean(工厂Bean);
默认获取到的是工厂bean调用getObject创建的对象。
//创建一个Spring定义的FactoryBean
public class ColorFactoryBean implements FactoryBean<Color> {
//返回一个Color对象,这个对象会添加到容器中
@Override
public Color getObject() throws Exception {
System.out.println("ColorFactoryBean...getObject...");
return new Color();
}
@Override
public Class<?> getObjectType() {
return Color.class;
}
//true:这个bean是单实例,在容器中保存一份
//false:多实例,每次获取都会创建一个新的bean;
@Override
public boolean isSingleton() {
return false;
}
}
三、补充
@Conditional注解
作用:按照一定的条件进行判断,满足条件给容器中注册Bean 。自定义的条件类需要实现Condition接口,并实现其中的match()方法,可作用于类或者方法上
如果当前操作系统是Windows,会导入这个WindowsCondition这个组件,反之,不会导入这个组件。
// 类中组件统一设置。满足当前条件,这个类中配置的所有bean注册才能生效;
@Conditional({WindowsCondition.class})
@Configuration
public class MainConfig {
@Bean("bill")
public Person person(){
return new Person("Bill Gates",62);
}
}
//判断是否windows系统
public class WindowsCondition implements Condition {
@Override
public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
Environment environment = context.getEnvironment();
String property = environment.getProperty("os.name");
if(property.contains("Windows")){
return true;
}
return false;
}
}
最后
以上就是美好硬币为你收集整理的向Spring容器中注册组件的几种方式的全部内容,希望文章能够帮你解决向Spring容器中注册组件的几种方式所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复