Spring Bean 基础
定义 Spring Bean
什么是 BeanDefinition?
BeanDefinition 是Spring Framework 中定义 Bean 的配置元信息接口,包含:
- Bean 类名;
- Bean 的行为元素,如作用域、自动绑定模式,生命周期回调等;
- 配置信息,比如 Bean 属性(Properties)
BeanDefinition 元信息
Class
:Bean 全类名,必须是具体类,不能用抽象或接口;Name:Bean
的名称或者 ID;Scope:Bean
的作用域,如:singleton,prototypeConstrustor arguments
:Bean 构造器参数(用于依赖注入)Properties:Bean
属性设置,用来依赖注入Autowiring mode
:Bean 自动绑定模式,如通过名称 byNameLazy initialization mode
:Bean 延迟初始化模式(延迟和非延迟)Initialzation method
:Bean 初始化回调方法名称Destruction method
:Bean 销毁回调方法名称
如何构建 BeanDefinition
?
- 通过
BeanDefinitionBuilder
- 通过
AbstractBeanDefinition
以及派生类
public class BeanDefinitionCreation {
public static void main(String[] args) {
//1.通过 BeanDefinitionBuilder 构建
BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(User.class);
//通过属性设置
builder.addPropertyValue("id",1);
builder.addPropertyValue("name","白杨");
//获取实例
AbstractBeanDefinition beanDefinition = builder.getBeanDefinition();
//2.通过 AbstractionBeanDefinition 以及派生类
GenericBeanDefinition genericBeanDefinition = new GenericBeanDefinition();
//设置 Bean 类型
genericBeanDefinition.setBeanClass(User.class);
//通过 MutablePropertyValues 批量操作属性
MutablePropertyValues propertyValues = new MutablePropertyValues();
propertyValues.addPropertyValue("id",2);
propertyValues.addPropertyValue("name","baiyang");
propertyValues.add("id",3).add("name","xiaobaiyang");
//通过 set MutablePropertyValues 批量操作
genericBeanDefinition.setPropertyValues(propertyValues);
}
}
Spring Bean 命名
Bean 名称:
每个 Bean 拥有一个或多个标识符,这些标识符在 Bean 所在的容器必须是唯一的,通常一个 Bean 仅有一个标识符,如果需要额外的,可以考虑使用别名 Alias 扩充。
在基于 XML 配置元信息时,开发人员可以用 id 或 name 属性来规定 Bean 的标识符,通常 Bean 的标识符由字母组成,允许出现特殊字符。如果想要引入 Bean 的别名话,可以 name 属性使用逗号和分号来分割。
但 Bean 的 id 和 name 属性 并非定制的,如果留空的话,容器会为 Bean 自动生成唯一名称,Bean 的命名尽管没有限制,不过官方采用驼峰命名方式更符合 Java 命名规范。
Bean 默认生成名字的方式是通过 BeanNameGenerator 实现的。
Bean名称生成器(BeanNameGenerator)
有 Spring Framework 2.0.3 引入,框架内有两种实现:
- DefaultBeanNameGenerator:默认通过 BeanNameGenerator 实现;
- AnnotationBeanNameGenerator:基于注解扫描的 BeanNameGenerator 实现。
Bean 别名的价值和注册 Bean
- 复用现有的 BeanDefinition
- 更具有场景化的命名方法,比如:
<alias name="myApp-dataSource" alias="subsystemA-dataSource"/> <alias name="myApp-dataSource" alias="subsystemB-dataSource"/>
@Import(AnnotationBeanDefinitionDemo.Config.class) //通过 Import 进行导入
public class AnnotationBeanDefinitionDemo {
public static void main(String[] args) {
//创建 BeanFactory 容器
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext();
//注册 配置类
applicationContext.register(Config.class);
//通过 BeanDefinition 注册 Api
registerUserBeanDefinition(applicationContext,"xiao-baiyang");
registerUserBeanDefinition(applicationContext);
//启动 Spring 上下文
applicationContext.refresh();
Map<String, Config> configType = applicationContext.getBeansOfType(Config.class);
Map<String, User> userType = applicationContext.getBeansOfType(User.class);
System.out.println("Config 所有 Bean 的实例" + configType);
System.out.println("User 所有 Bean 的实例" + userType);
//1.通过 @Bean 方式定义
//2.通过 @Component 方式
//3.通过 @Import 导入
//显示关闭 Spring 应用上下文
applicationContext.close();
}
/**
* 命名 Bean 的注册方式
* @param registry
* @param beanName
*/
public static void registerUserBeanDefinition(BeanDefinitionRegistry registry ,String beanName){
BeanDefinitionBuilder builder = genericBeanDefinition(User.class);
builder.addPropertyValue("id",1L);
builder.addPropertyValue("name","白杨");
//判断 beanName 是否存在
if (StringUtils.hasText(beanName)) {
//注册 BeanDefinition
registry.registerBeanDefinition(beanName,builder.getBeanDefinition());
}else {
BeanDefinitionReaderUtils.registerWithGeneratedName(builder.getBeanDefinition(),registry);
}
}
public static void registerUserBeanDefinition(BeanDefinitionRegistry registry) {
registerUserBeanDefinition(registry,null);
}
@Component //定义当前类作为 Spring Bean (组件)
public static class Config {
//通过 Java 注解方式,定义一个 Bean
@Bean(name = {"user","bai-yang"})
public User user() {
User user = new User();
user.setId(2L);
user.setName("baiyang");
return user;
}
}
}
实例化和初始化 Spring Bean
常规方式:
- 通过构造器
- 通过静态工厂方法
- 通过 Bean 工厂方法
- 通过 FactoryBean
Bean初始化:
-
基于 PostConstruct 标注方法
-
实现 InitializingBean 接口的 afterPropertiesSet()
-
自定义初始化方法
XML 配置:
<bean init-method = "init"/>
Java 注解:@Bean(initMethod = “init”)
Java API:AbstractBeanDefinition#setInitMethodName(String)
延迟初始化加载 Spring Bean
Bean 延迟初始化:
- XML 配置:<bean lazy-init:“true”/>
- Java 注解 @Lazy(true)
销毁 Spring Bean
- @PreDestory 标注方法
- 实现 DisposableBean 接口的 destory() 方法
- 自定义销毁方法
- XML 配置:
<bean destory = "destory"/>
- Java 注解:@Bean(destory = “destory”)
- Java API:API:AbstractBeanDefinition#setDestroyMethodName(String)
- XML 配置:
垃圾回收 Spring Bean
- 关闭 Spring 容器应用上下文
- 执行 GC
- Spring Bean 覆盖的 finalize() 方法被回调