在本文总结Spring Bean的部分基础内容,首先会总结BeanDefinition的职责;在了解BeanDefinition是做什么之后,再进一步总结BeanDefinition的层级结构,即总结其扩展哪些类,以及实现类;在上面基础上,进一步通过代码总结如何去注册BeanDefinition,以及如何使用BeanDefinition去生成一个Bean。
BeanDefinition Class
BeanDefinition是Spring Framework中定义Bean的配置元信息接口,描述一个bean实例应该具有属性值和方法特征(设置Bean的class name、scope、lazyInit等) 。注意,这只是一个最小的接口:主要目的是允许BeanFactoryPostProcessor缺省处理(introspect)[1]和修改属性值和其他bean元数据。
BeanDefinition 层级
通过Spring API文档可以查询BeanDefinition的层级结构,如下图所示,
将结构转化成UML进行展示,
Interface AttributeAccessor
该接口定义一个用于向任意对象附加和访问元数据的通用契约。
Interface BeanMetadataElement
定义一个bean metadata 的实现应该携带获取configuration source 对象行为的契约
Class AbstractBeanDefinition
具体的、成熟的BeanDefinition类的基类,提取出GenericBeanDefinition、RootBeanDefinition和ChildBeanDefinition的公共属性。autowire常数与在AutowireCapableBeanFactory接口中定义的常数匹配。
Interface AnnotatedBeanDefinition
扩展的BeanDefinition接口,它公开关于其bean类的注释元数据。
Class RootBeanDefinition
根bean定义表示在运行时支持Spring BeanFactory中的特定bean的合并bean定义。它可能是从相互继承的多个原始bean定义创建的,通常注册为GenericBeanDefinitions。根bean定义本质上是运行时的“统一”bean定义视图。根bean定义还可以用于在配置阶段注册单个bean定义。但是,自从spring2.5以来,通过编程注册bean定义的首选方法是使用GenericBeanDefinition类。GenericBeanDefinition的优点是,它允许动态定义父依赖项,而不是将角色“硬编码”为根bean定义。
Class ChildBeanDefinition
从父Bean继承设置的Bean定义。子bean定义对父bean定义有固定的依赖关系。子bean定义将从父bean继承构造函数参数值、属性值和方法覆盖,并具有添加新值的选项。如果指定了init方法、destroy方法和/或静态工厂方法,它们将覆盖相应的父设置。其余的设置将始终从子定义中获取:依赖、自动装配模式、依赖检查、单例、延迟init。
Class GenericBeanDefinition
GenericBeanDefinition是用于标准bean定义目的的一站式商店。与任何bean定义一样,它允许指定类以及可选的构造函数参数值和属性值。此外,可以通过“parentName”属性灵活地配置从父bean定义派生的内容。通常,使用这个GenericBeanDefinition类来注册用户可见的bean定义(后处理程序可能对其进行操作,甚至可能重新配置父名称)。如果父/子关系是预先确定的,请使用RootBeanDefinition / ChildBeanDefinition。
Class ScannedGenericBeanDefinition
对GenericBeanDefinition类的扩展,基于ASM类阅读器,支持通过AnnotatedBeanDefinition接口公开的注释元数据。
Class AnnotatedGenericBeanDefinition
对GenericBeanDefinition类的扩展,添加对通过AnnotatedBeanDefinition接口公开的注释元数据的支持。
进一步了解BeanDefinition
Bean元信息
Bean元信息有描述其类,作用域,属性值等信息,通过AbstractBeanDefinition.class 可以发现通用的Beans元信息
创建BeanDefinition
有两种方法构建一个BeanDefinition,一是通过BeanDefinitionBuilder,二是通过AbstractBeanDefinition派生类
public static void main(String[] args) {
// 1.通过 BeanDefinitionBuilder 构建
BeanDefinitionBuilder beanDefinitionBuilder = BeanDefinitionBuilder.genericBeanDefinition("testBean");
beanDefinitionBuilder
.addPropertyValue("msg", "hello world")
.addPropertyValue("describe", "this is a test bean");
// 获取 BeanDefinition 实例
BeanDefinition beanDefinition = beanDefinitionBuilder.getBeanDefinition();
System.out.println(beanDefinition.toString());
// 2. 通过 AbstractBeanDefinition的衍生类构建,此处举例通过GenericBeanDefinition来构建BeanDefinition
GenericBeanDefinition genericBeanDefinition = new GenericBeanDefinition();
genericBeanDefinition.setBeanClass(User.class);
// 通过 MutablePropertyValues 批量操作属性
MutablePropertyValues propertyValues = new MutablePropertyValues();
propertyValues.add("id", 123)
.add("name", "Jany")
.add("age", 18);
genericBeanDefinition.setPropertyValues(propertyValues);
System.out.println(genericBeanDefinition.toString());
}
注册BeanDefinition
注册BeanDefinition有三种方式,
- xml配置
- 注解配置
- API配置
这里演示API配置和注解配置的方式
API配置:
/**
* BeanDefinition 注册
* 通过创建BeanDefinitionBuilder创建BeanDefinition,然后注册成Bean 注册
* API配置
*/
public class Learn2 {
public static void main(String[] args) {
//通过BeanDefinitionBuilder创建BeanDefinition
BeanDefinitionBuilder beanDefinitionBuilder = BeanDefinitionBuilder.genericBeanDefinition("com.example.learnbean.entity.User");
beanDefinitionBuilder
.addPropertyValue("name", "Jane")
.addPropertyValue("age", 18)
.addPropertyValue("id", 31321);
BeanDefinition beanDefinition = beanDefinitionBuilder.getBeanDefinition();
// 创建 BeanFactory 容器
GenericApplicationContext applicationContext = new GenericApplicationContext();
// 根据beanDefinition注册成spring bean
applicationContext.registerBeanDefinition("testBean", beanDefinition);
// 启动 Spring 应用上下文
applicationContext.refresh();
// 根据bean name 查找Bean
System.out.println(applicationContext.getBean("testBean").toString());
// 显示地关闭 Spring 应用上下文
applicationContext.close();
}
}
注解配置:
/**
* BeanDefinition 注册
* Java注解配置
*/
// 3. 通过 @Import 来进行导入
@Import(Learn2ch3.Config.class)
public class Learn2ch3 {
public static void main(String[] args) {
// 创建 BeanFactory 容器
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext();
// 注册 Configuration Class(配置类)
applicationContext.register(Learn2ch3.class);
// 启动 Spring 应用上下文
applicationContext.refresh();
// 按照类型依赖查找
System.out.println(applicationContext.getBeansOfType(User.class));
System.out.println(applicationContext.getBeansOfType(Config.class));
// 显示地关闭 Spring 应用上下文
applicationContext.close();
}
// 2. 通过 @Component 方式
@Component// 定义当前类作为 Spring Bean
public class Config {
// 1. 通过 @Bean 方式定义
@Bean
public User user() {
User user = new User();
user.setAge(18);
user.setName("Jany");
user.setId(123123);
return user;
}
}
}