小马哥讲Spring核心编程思想-spring bean 基础
前言
没有
一、BeanDefinition
是什么
BeanDefinition 是 Spring 中的一个核心概念,它用于描述一个 Bean 实例的属性和行为,并提供了创建和管理 Bean 实例的基础信息。
BeanDefinition 描述了一个 Bean 实例的基本信息,包括 Bean 的类型、属性、构造函数参数、初始化方法、销毁方法等。IOC 容器根据这些信息来创建和管理 Bean 实例,使得开发者无需手动创建和管理 Bean 实例,从而实现了控制反转。
元信息
如下图
BeanDefinition 构建
- 通过 BeanDefinitionBuilder
BeanDefinitionBuilder beanDefinitionBuilder = BeanDefinitionBuilder.genericBeanDefinition(User.class);
- 通过 AbstractBeanDefinition 以及派生类
GenericBeanDefinition genericBeanDefinition = new GenericBeanDefinition();
// 设置 Bean 类型
genericBeanDefinition.setBeanClass(User.class);
二、spring bean的名称
每个 Bean 拥有一个或多个标识符(identifiers),这些标识符在 Bean 所在的容器必须是唯一的。通常,一个 Bean 仅有一个标识符,如果需要额外的,可考虑使用别名(Alias)来扩充。
在基于 XML 的配置元信息中,开发人员可用 id 或者 name 属性来规定 Bean 的 标识符。通常 Bean 的 标识符由字母组成,允许出现特殊字符。
Bean 的 id 或 name 属性并非必须制定,如果留空的话,容器会为 Bean 自动生成一个唯一的名称。
Bean 名称生成器(BeanNameGenerator)由 Spring Framework 2.0.3 引入,框架內建两种实现:DefaultBeanNameGenerator:默认通用 BeanNameGenerator 实现
三、spring bean的别名
将 Spring 容器中 “user” Bean 关联/建立别名 - “xz-user”
<alias name="user" alias="xz-user" />
然后取的时候就可以用 user 或 别名 xz-user 取了
// 启动 Spring 应用上下文
BeanFactory beanFactory = new ClassPathXmlApplicationContext("classpath:/META-INF/bean-definitions-context.xml");
// 通过别名 xiaomage-user 获取曾用名 user 的 bean
User user = beanFactory.getBean("user", User.class);
User xzUser = beanFactory.getBean("xz-user", User.class);
// 结果为 true
System.out.println("xz-user 是否与 user Bean 相同:" + (user == xzUser));
四、将 BeanDefinition 注册到 Ioc 容器
- XML方式
- Java注解方式(@Bean、@Component、@Import)
- Java API 配置元信息(命名方式、非命名方式、配置类方式)
public static void registerUserBeanDefinition(BeanDefinitionRegistry registry, String beanName) {
BeanDefinitionBuilder beanDefinitionBuilder = BeanDefinitionBuilder.genericBeanDefinition(User.class);
beanDefinitionBuilder
.addPropertyValue("id", 1L)
.addPropertyValue("name", "小马哥");
// 判断如果 beanName 参数存在时
if (StringUtils.hasText(beanName)) {
// 注册 BeanDefinition(命名方式)
registry.registerBeanDefinition(beanName, beanDefinitionBuilder.getBeanDefinition());
} else {
// 非命名 Bean 注册方法
BeanDefinitionReaderUtils.registerWithGeneratedName(beanDefinitionBuilder.getBeanDefinition(), registry);
}
// 配置类方式
// DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
// 基于 Java 注解的 AnnotatedBeanDefinitionReader 的实现
// AnnotatedBeanDefinitionReader beanDefinitionReader = new AnnotatedBeanDefinitionReader(beanFactory);
// 注册当前类(非 @Component class)
// beanDefinitionReader.register(AnnotatedBeanDefinitionParsingDemo.class);
}
五、实例化Spring Bean
这里不记录实现代码,因为一般不会去使用。
-
常规方式
1、通过构造器(配置元信息:XML、Java 注解和 Java API)
2、通过静态工厂方法(配置元信息:XML和 Java API)
3、通过 Bean 工厂方法(配置元信息:XML和 Java API)
4、通过 FactoryBean(配置元信息:XML、Java 注解和 Java API) -
特殊方式
1、通过 ServiceLoaderFactoryBean(配置元信息:XML、Java 注解和 Java API)
2、通过 AutowireCapableBeanFactory#createBean(java.lang.Class, int, boolean)
3、通过 BeanDefinitionRegistry#registerBeanDefinition(String,BeanDefinition)
六、Bean 初始化
作用:在你的bean在初始化时,会调用该方法
- @PostConstruct 标注方法
- 实现 InitializingBean 接口的 afterPropertierSet()方法
- 自定义初始化方法
1、XML 配置:<bean init-method=“init”… />
2、Java 注解:@Bean(initMethod=“init”)
3、Java APl: AbstractBeanDefinition#setinitMethodName(String)
如果三种方式都进行了配置,对应的执行顺序则为 @PostConstruct、afterPropertierSet()方法、自定义初始化方法
补充:
Bean 延迟初始化
实现方式:
- XML 配置:<bean lazy-init=“true”… />
- Java 注解:@Lazy(true)
和非延迟初始化的区别:延迟初始化是使用的时候才去创建,非延迟就是先准备好,用的时候直接用
七、Bean 销毁
作用:在bean销毁时,调用该方法
实现方式和 Bean 的初始化类似
- @PreDestroy 标注方法
- 实现 DisposableBean 接口的 destroy()方法
- 自定义销毁方法
1、XML 配置:<bean destroy=“destroy”… />
2、Java 注解:@Bean(destroy=“destroy”)
3、Java API:AbstractBeanDefinition#setDestroyMethodName(String)
八、回收 Spring Bean
只有关闭了 Spring 容器 才会回收 Spring Bean