我是靠谱客的博主 美好硬币,这篇文章主要介绍向Spring容器中注册组件的几种方式,现在分享给大家,希望可以做个参考。

一、引言

在SpringBoot还没有普及之前,我们创建Spring+SpringMVC项目的时候,首先要配置web.xml、Spring.xml、SpringMVC.xml三个配置文件。对于下面的包扫描配置,就是把该包下的带有@Controller、@Service、@Repository、@Component注解的组件注册到Spring容器中,在该标签中,还有include-filter、exclude-filter属性。

复制代码
1
2
<context:component-scan base-package="com.scorpios"></context:component-scan>

在SpringBoot中,我们用@Configuration注解==配置类代替了xml文件,用@ComponentScan注解代替了<context:component-scan>标签,它们的意思等价。

在介绍向容器中注册组件之前,我们先来介绍一下include-filter中的自定义规则

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
//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

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
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容器中,除了上面的两种方式,还有哪些方式呢?

复制代码
1
2
3
4
public class Color { String color; }
(1)、@Import(要导入到容器中的组件):容器中就会自动注册这个组件,id默认是全类名;

如果想把Color注册到Spring容器中,第一种方式,使用@Import注解,只需要做如下配置即可:

复制代码
1
2
3
4
5
@Configuration @Import({Color.class}) public class MainConfig{ }
(2)、ImportSelector:返回需要导入的组件的全类名数组;

如果想把Color注册到Spring容器中,第二种方式,使用ImportSelector接口,需要做如下配置:

复制代码
1
2
3
4
5
@Configuration @Import({MyImportSelector.class})) public class MainConfig{ }
复制代码
1
2
3
4
5
6
7
8
9
10
11
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接口,需要做如下配置:

复制代码
1
2
3
4
5
@Configuration @Import({MyImportBeanDefinitionRegistrar.class})) public class MainConfig{ }
复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
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创建的对象。

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
//创建一个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这个组件,反之,不会导入这个组件。

复制代码
1
2
3
4
5
6
7
8
9
10
11
// 类中组件统一设置。满足当前条件,这个类中配置的所有bean注册才能生效; @Conditional({WindowsCondition.class}) @Configuration public class MainConfig { @Bean("bill") public Person person(){ return new Person("Bill Gates",62); } }
复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
//判断是否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容器中注册组件内容请搜索靠谱客的其他文章。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(52)

评论列表共有 0 条评论

立即
投稿
返回
顶部