Posted by Lucky Xue on 2020-06-02

定义Spring Bean

什么是BeanDefinition?
BeanDefinition是Spring Framwork中定义的Bean的配置元信息接口,包括:

  • Bean的类名
  • Bean行为配置元素,如作用域、自动绑定的模式、生命周期回调等
  • 其他Bean引用,又可称作合作者(Collaborators)或者依赖(Dependencies)
  • 配置设置,比如Bean属性(Properties)

BeanDefinition元信息

属性(Property)
Class | Bean全类名,必须是具体类,不能用抽象类或接口
Name | Bean的名称或者ID
Scope | Bean的作用域(如:singleton、prototype等)
Constructor arguments | Bean构造器参数(用于依赖注入)
Propertes | Bean属性设置(用于

BeanDefinition构建

  • 通过BeanDefinitionBuilder
  • 通过AbstractBeanDefinition以及派生类

通过BeanDefinitionBuilder构建

1
2
3
4
5
6
7
8
9
// 1.通过 BeanDefinitionBuilder 构建
BeanDefinitionBuilder beanDefinitionBuilder = BeanDefinitionBuilder.genericBeanDefinition(User.class);
// 通过属性设置
beanDefinitionBuilder
.addPropertyValue("id", 1)
.addPropertyValue("name", "小马哥");
// 获取 BeanDefinition 实例
BeanDefinition beanDefinition = beanDefinitionBuilder.getBeanDefinition();
// BeanDefinition 并非 Bean 终态,可以自定义修改

通过AbstractBeanDefinition以及派生类构建

1
2
3
4
5
6
7
8
9
10
11
12
13
// 2. 通过 AbstractBeanDefinition 以及派生类
GenericBeanDefinition genericBeanDefinition = new GenericBeanDefinition();
// 设置 Bean 类型
genericBeanDefinition.setBeanClass(User.class);
// 通过 MutablePropertyValues 批量操作属性
MutablePropertyValues propertyValues = new MutablePropertyValues();
// propertyValues.addPropertyValue("id", 1);
// propertyValues.addPropertyValue("name", "小马哥");
propertyValues
.add("id", 1)
.add("name", "小马哥");
// 通过 set MutablePropertyValues 批量操作属性
genericBeanDefinition.setPropertyValues(propertyValues);

命令Spring Bean

Bean 的名称

每个 Bean 拥有一个或多个标识符(identifiers),这些标识符在 Bean 所在的容器必须是唯一
的。通常,一个 Bean 仅有一个标识符,如果需要额外的,可考虑使用别名(Alias)来扩充。
在基于 XML 的配置元信息中,开发人员可用 id 或者 name 属性来规定 Bean 的 标识符。通常
Bean 的 标识符由字母组成,允许出现特殊字符。如果要想引入 Bean 的别名的话,可在
name 属性使用半角逗号(“,”)或分号(“;”) 来间隔。
Bean 的 id 或 name 属性并非必须制定,如果留空的话,容器会为 Bean 自动生成一个唯一的
名称。Bean 的命名尽管没有限制,不过官方建议采用驼峰的方式,更符合 Java 的命名约定。

Bean 名称生成器(BeanNameGenerator)

  • 由 Spring Framework 2.0.3 引入,框架內建两种实现:
    DefaultBeanNameGenerator:默认通用 BeanNameGenerator 实现
  • AnnotationBeanNameGenerator:基于注解扫描的 BeanNameGenerator 实现,起始于
    Spring Framework 2.5,关联的官方文档:
    With component scanning in the classpath, Spring generates bean names for unnamed components,
    following the rules described earlier: essentially, taking the simple class name and turning its initial
    character to lower-case. However, in the (unusual) special case when there is more than one
    character and both the first and second characters are upper case, the original casing gets preserved.
    These are the same rules as defined by java.beans.Introspector.decapitalize (which Spring uses here).

Spring Bean别名

Bean 别名(Alias)的价值
• 复用现有的 BeanDefinition
• 更具有场景化的命名方法,比如:

BeanDefinition 注册

  • XML 配置元信息
    • <bean name=”…” … />
  • Java 注解配置元信息
    • @Bean
    • @Component
    • @Import
  • Java API 配置元信息
    • 命名方式:BeanDefinitionRegistry#registerBeanDefinition(String,BeanDefinition)
    • 非命名方式:
    BeanDefinitionReaderUtils#registerWithGeneratedName(AbstractBeanDefinition,Be
    anDefinitionRegistry)
    • 配置类方式:AnnotatedBeanDefinitionReader#register(Class…)
1
2
3
4
5
6
7
8
9
public static void main(String[] args) {
// 配置 XML 配置文件
// 启动 Spring 应用上下文
BeanFactory beanFactory = new ClassPathXmlApplicationContext("classpath:/META-INF/bean-definitions-context.xml");
// 通过别名 xiaomage-user 获取曾用名 user 的 bean
User user = beanFactory.getBean("user", User.class);
User xiaomageUser = beanFactory.getBean("xiaomage-user", User.class);
System.out.println("xiaomage-user 是否与 user Bean 相同:" + (user == xiaomageUser));
}
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
public class AnnotationBeanDefinitionDemo1 {

public static void main(String[] args) {
// 创建 BeanFactory 容器
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext();
// 注册 Configuration Class(配置类)
applicationContext.register(Config.class);
// 启动 Spring 应用上下文
applicationContext.refresh();
// 按照类型依赖查找
System.out.println("Config 类型的所有 Beans" + applicationContext.getBeansOfType(Config.class));
System.out.println("User 类型的所有 Beans" + applicationContext.getBeansOfType(User.class));
// 显示地关闭 Spring 应用上下文
applicationContext.close();
}

public static class Config {
// 1. 通过 @Bean 方式定义
/**
* 通过 Java 注解的方式,定义了一个 Bean
*/
@Bean(name = {"user", "xiaomage-user"})
public User user() {
User user = new User();
user.setId(1L);
user.setName("小马哥");
return user;
}
}
}
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
public class AnnotationBeanDefinitionDemo2 {

public static void main(String[] args) {
// 创建 BeanFactory 容器
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext();
// 注册 Configuration Class(配置类)
applicationContext.register(Config.class);
// 启动 Spring 应用上下文
applicationContext.refresh();
// 按照类型依赖查找
System.out.println("Config 类型的所有 Beans" + applicationContext.getBeansOfType(Config.class));
System.out.println("User 类型的所有 Beans" + applicationContext.getBeansOfType(User.class));
// 显示地关闭 Spring 应用上下文
applicationContext.close();
}

// 2. 通过 @Component 方式
@Component // 定义当前类作为 Spring Bean(组件)
public static class Config {
// 1. 通过 @Bean 方式定义
/**
* 通过 Java 注解的方式,定义了一个 Bean
*/
@Bean(name = {"user", "xiaomage-user"})
public User user() {
User user = new User();
user.setId(1L);
user.setName("小马哥");
return user;
}
}
}
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
// 3. 通过 @Import 来进行导入
@Import(AnnotationBeanDefinitionDemo.Config.class)
public class AnnotationBeanDefinitionDemo3 {

public static void main(String[] args) {
// 创建 BeanFactory 容器
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext();
// 注册 Configuration Class(配置类)
applicationContext.register(AnnotationBeanDefinitionDemo3.class);
// 启动 Spring 应用上下文
applicationContext.refresh();
// 按照类型依赖查找
System.out.println("Config 类型的所有 Beans" + applicationContext.getBeansOfType(Config.class));
System.out.println("User 类型的所有 Beans" + applicationContext.getBeansOfType(User.class));
// 显示地关闭 Spring 应用上下文
applicationContext.close();
}

// 2. 通过 @Component 方式
@Component // 定义当前类作为 Spring Bean(组件)
public static class Config {
// 1. 通过 @Bean 方式定义
/**
* 通过 Java 注解的方式,定义了一个 Bean
*/
@Bean(name = {"user", "xiaomage-user"})
public User user() {
User user = new User();
user.setId(1L);
user.setName("小马哥");
return user;
}
}
}