0%

SpringBoot—容器中组件注册

这里讲述了SpringBoot的容器功能的组件添加,包括「配置类、Full模式与Lite模式、条件装配与测试类」

配置类概述(@Configuration)

@Configuration写在类上,用于标记这是“配置类”。配置类方法中用@Bean注册组件,配置类本身也是组件
PS:配置类相当于曾经的配置文件

Full模式与Lite模式

该标签可以有参数@Configuration(proxyBeanMethods = true/false)用于控制是否为“代理组件方法”。二者区别

  • Lite模式:
    【保证每个@Bean方法被调用多少次返回的组件都是单实例的】,用于【配置类组件之间无依赖关系】
  • Full模式:
    【每个@Bean方法被调用多少次返回的组件都是新创建的】用于【配置类组件之间有依赖关系】

    组件注册(@Bean)

    配置类里面使用@Bean标注在方法上给容器注册组件,默认是单实例的。

注册时,默认以方法名 = 组件id返回类型 = 组件类型返回的值 = 组件在容器中的实例
自定义组件名:如果在@Bean("name")则组件名(组件ID)就设定为name

配置类示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
/*已经有了User类和Pet类,位于`com.xxx.xxx.boot.bean`包下*/

@Configuration(proxyBeanMethods = false) //配置类 lite模式
public class MyConfig {

@Bean
public User user01(){
User zhangsan = new User("zhangsan", 18);
//user组件依赖了Pet组件:lite模式下,这是一个全新的组件
zhangsan.setPet(tomcatPet());
return zhangsan;
}

@Bean("tom")//定义组件名
public Pet tomcatPet(){
return new Pet("tomcat");
}
}

组件注册(@Import)

@Configuration使用@Import({构造器, 构造器})的方式也可以注册对应类型的组件,此时组件名为“全类名
示例:

1
2
/*写在类之前*/
@Import({User.class, DBHelper.class})

条件装配(@Conditional)

这个注解的意思是,只有满足给定条件,对应代码才生效。十分常用的功能。
打开@Conditional的依赖树,看以看到很多子注解
各种条件装配

下面以@ConditionalOnBean为例展示用法(示例上上一个大体相同,只是加了注解和**@Import**):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
/*已经有了User类和Pet类,位于`com.xxx.xxx.boot.bean`包下*/

@Import({User.class, DBHelper.class})
@Configuration(proxyBeanMethods = false) //配置类 lite模式
public class MyConfig {

@ConditionalOnBean(name = "com.atguigu.boot.bean.User")
// 条件装配注解,如果容器有name=com.atguigu.boot.bean.User的组件这个user01 组件才注册代码才生效
@Bean
public User user01(){
User zhangsan = new User("zhangsan", 18);
//user组件依赖了Pet组件:lite模式下,这是一个全新的组件
zhangsan.setPet(tomcatPet());
return zhangsan;
}

@Bean("tom")//定义组件名
public Pet tomcatPet(){
return new Pet("tomcat");
}
}

测试类的写法

在主函数写测试类,对应上述示例。测试类如下:

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
28
29
30
31
32
33
34
35
36
37
38
39
@SpringBootApplication
public class MainApplication {
public static void main(String[] args) {
//1、返回IOC容器
ConfigurableApplicationContext run = SpringApplication.run(MainApplication.class, args);
//-------------------------------------------------------------
//2、遍历容器里的组件
String[] names = run.getBeanDefinitionNames();
for(String name : names){
System.out.println(name);
}
//-------------------------------------------------------------
//3、从容器中获取组件 getBean(组件名, 类型)
Pet tom1 = run.getBean("tom", Pet.class);
Pet tom2 = run.getBean("tom", Pet.class);
//这里判断了在 full 和 lite 下,组件是非时同一个
System.out.println("组件" + (tom1 == tom2));
//这里证明了 “Configuration也是一个组件”
System.out.println(run.getBean(MyConfig.class));
//-------------------------------------------------------------
//4、从容器中获取组件名 getBeanNamesForType(类型)
String[] beanNamesForType = run.getBeanNamesForType(User.class);
System.out.println("=========");
for (String s : beanNamesForType) {
System.out.println(s);
}
//-------------------------------------------------------------
//5、组件存在判断(条件装配) containsBean("name")
boolean tom = run.containsBean("tom");
System.out.println("tom:"+tom);

boolean user01 = run.containsBean("user01");
System.out.println("user01:"+user01);

boolean tom22 = run.containsBean("tom22");
System.out.println("tom22:" + tom22);

}
}

其中使用的方法:

方法名 说明
ConfigurableApplicationContext run = SpringApplication.run(MainApplication.class, args); 【标准写法】返回IOC容器
String[] run.getBeanDefinitionNames() 返回容器中所有组件名的String数组
String[] run.getBeanNamesForType(xxx.class) 返回容器所有“给定类型”的组件名String数组
类型 run.getBean(组件名, 类型) 返回对应组件名与类型的组件
boolean run.containsBean(“组件名”) 返回容器是否存在对应名字的组件