Bean Definition
是 Spring 中定义 Bean 的配置元信息接口
- Bean 的类名
- Bean 行为配置元素,如作用域、自动绑定的模式、生命周期、回调等等
- Bean 的其他引用,依赖(Dependencies)或 合作者(Collaborators)
- 配置设置,如 Bean 的属性信息(Properties)
BeanDefinition 元信息
属性 | 说明 |
---|---|
Class | Bean 全类名,不能是抽象类或者接口,只能为具体类 |
Name | Bean 的名称或者ID |
Scope | Bean 的作用域(Singleton 或 prototype) |
Constructor arguments | Bean 的构造器参数(依赖注入) |
Properties | Bean 的成员属性(依赖注入) |
Autowiring mode | Bean 自动绑定模式(byName | byType) |
Lazy initialization mode | Bean 懒加载设置 |
Initialization method | Bean 初始化回调方法名称 |
Destruction method | Bean 销毁回调方法名称 |
BeanDefinition 的构建
- 通过 BeanDefinitionBuilder
- 通过 AbstractBeanBefinition 以及派生类
/**
* {@link org.springframework.beans.factory.config.BeanDefinition} 构建示例
* @author felix
* @date 2020/12/19
*/
public class BeanDefinitionCreationDemo {
public static void main(String[] args) {
// 1.通过 BeanDefinitionBuilder 构建
// generic 是较为常见的配置
BeanDefinitionBuilder beanDefinitionBuilder = BeanDefinitionBuilder.genericBeanDefinition(User.class);
// 通过属性设置
beanDefinitionBuilder.addPropertyValue("id", 34);
beanDefinitionBuilder.addPropertyValue("name", "three");
// 获取 BeanDefinition 实例
AbstractBeanDefinition beanDefinition = beanDefinitionBuilder.getBeanDefinition();
// 后续也可以继续进行补充 BeanDefinition 并非最终状态
// 2.通过 AbstractBean
GenericBeanDefinition genericBeanDefinition = new GenericBeanDefinition();
// 设置bean类型
genericBeanDefinition.setBeanClass(User.class);
// 通过 MutablePropertyValues 批量操作属性
MutablePropertyValues propertyValues = new MutablePropertyValues();
propertyValues.add("id", 34)
.add("name", "four");
// 通过 set MutablePropertyValues 批量操作属性
genericBeanDefinition.setPropertyValues(propertyValues);
}
}
BeanDefinition 的注册
XML 配置元信息
<bean name=""/>
Java 注解配置元信息
- @Bean
- @Component
- @Import
/**
* 通过 @Component 的方式定义
*/
@Component
public class Config {
/**
* 通过 @Bean 的方式定义
*/
@Bean(name = {"user", "three"})
public User user() {
User user = new User();
user.setName("dudu");
user.setId(22L);
return user;
}
}
/**
* 通过 @Import 的方式定义
*/
@Import(Config.class)
public class AnnotationBeanDefinitionDemo {
public static void main(String[] args) {
// 创建 BeanDefinition 容器
AnnotationConfigApplicationContext annotationConfigApplicationContext = new AnnotationConfigApplicationContext();
// 注册 Configuration Class (配置类)
annotationConfigApplicationContext.register(AnnotationBeanDefinitionDemo.class);
// @Component 需要配合扫描注解 @Import则不需要
annotationConfigApplicationContext.scan("spring/bean/configTest");
// 启动应用上下文
annotationConfigApplicationContext.refresh();
// 通过 Bean 类型获取
Map<String, Config> beansOfType = annotationConfigApplicationContext.getBeansOfType(Config.class);
beansOfType.forEach((key,value)->{
System.out.println(key+":"+value);
});
User user = annotationConfigApplicationContext.getBean("user", User.class);
System.out.println(user);
// 显示的关闭 Spring 应用上下文
annotationConfigApplicationContext.close();
}
}
Java API 配置元信息(自己手动配置 BeanDefinition 并手动注册)
- 命名方式:
BeanDefinitionRegistry#registerBeanDefinition(String,BeanDefinition)
- 非命名方式:
BeanDefinitionReaderUtils#registerWithGeneratedName(AbstractBeanDefinition,BeanDefinitionRegistry)
- 配置类方式:
AnnotatedBeanDefinitionReader#register(Class)
Bean 的名称
Bean 的名称
- 每个 Bean 通常只会有一个标识符(identifiers),在容器中保持唯一。
- 如需要多个需要使用别名 (Alias)来完成
在XML配置元信息中的 name 属性中使用 「,」或「;」来隔开即可
或
<alias name="user" alias="three-user"/>
标签的形式在注解中会使用 AnnotationBeanDefinition
Bean 名称生成器
- DefaultBeanNameGenerator:是默认的 BeanNameGenerator 的实现
Bean 的实例化
常规方式
- 通过构造器(配置元信息:XML、Java 注解、Java API)
- 通过静态工厂方法(配置元信息:XML)
public class User {
private Long id;
private String name;
public static User createUser(){
return new User();
}
}
<bean id="user-by-static-method" class="spring.ioc.overview.domain.User" factory-method="createUser"/>
- 通过 Bean 工厂方法 —工厂模式(配置元信息:XML、Java API)
调用对应实体类的静态构造方法
public interface UserFactory {
default User createUser() {
return User.createUser();
}
}
public class UserFactoryImpl implements UserFactory {}
<bean id="user-by-instance-method" class="spring.bean.factory.UserFactoryImpl" factory-bean="userFactory" factory-method="createUser"/>
<bean id="userFactory" class="spring.bean.factory.UserFactoryImpl"/>
- 通过 FacotoryBean —抽象工厂(配置元信息:XML、Java 注解、Java API)
public class UserFactoryBean implements FactoryBean {
@Override
public Object getObject() throws Exception {
return User.createUser();
}
@Override
public Class<?> getObjectType() {
return User.class;
}
}
<bean id="user-by-factory-bean" class="spring.bean.factory.UserFactoryBean"/>
特殊方式
- 通过
ServiceLoaderFactoryBean
(配置元信息:XML、Java 注解、Java API) - 通过
AutowireCapableBeanFactory#createBean(Class,int,boolean)
- 通过
BeanDefinitionRegistry#registerBeanDefinition(String,BeanDefinition)
Bean 的初始化
- @PostConstruct 标注方法
- 实现 InitializingBean 接口的 afterPropertiesSet() 方法
- 自定义初始化方法(@Bean(initMethod ="") || )
public class DefaultUserFactory implements UserFactory, InitializingBean {
/**
* 1.基于 @PostConstruct 注解
*/
@PostConstruct
public void init() {
System.out.println("@PostConstruct");
}
/**
* 基于 @Bean 去指定 initial
*/
public void initUserFactory() {
System.out.println("@Bean(initMethod = initUserFactory)");
}
/**
* 基于 Spring 官方{@link org.springframework.beans.factory.InitializingBean} 接口实现
*/
@Override
public void afterPropertiesSet() throws Exception {
System.out.println("InitializingBean#afterPropertiesSet()");
}
}
方法执行的先后顺序如下
基于自定义指定初始化方法其实是在 AbstractBeanDefinition 去设置的
Bean 的延迟初始化
- XML 配置:
- Java 注解:@Lazy(true)
可以看懂延迟加载与非延迟加载在注册的时候是没有区别的,但是对于依赖查找和依赖注入来说,非延迟加载在应用上下文启动前就加载完成了
Bean 的销毁
- @PreDestroy 标注方法
- 实现 DisposableBean 接口的 destory() 方法
- Java API:AbstractBeanDefinition#setDestroyMethodName(String)