Spring Bean基础
1.定义Spring Bean
BeanDefinition是Spring Framework中定义Bean配置的元信息接口,包含:
- Bean的类名
- Bean的行为配置,如作用域、自动绑定的模式、生命周期回调等
- 其他Bean的引用,又可称为合作者(Colloborators)或者依赖(Dependency)
- 配置设置,比如Bean属性(Properties)
2.BeanDefinition元信息
BeanDefinition元信息 | |
---|---|
属性 | 说明 |
Class | Bean全类名,必须是具体类,不能使用抽象类或接口 |
Name | Bean的名称或ID |
Scope | Bean的作用域(如Sigleton、Prototype) |
Constructor arguments | Bean构造器参数(用于依赖注入) |
Properties | Bean的属性设置(用于依赖注入) |
Autowiring mode | Bean自动绑定模式(如:通过名称 ByName) |
Lazy initislization mode | Bean延迟初始化模式(延迟和非延迟) |
Initialization method | Bean 初始化回调方法名称 |
Destruction method | Bean销毁回调方法名称 |
BeanDefinition构建:
- 通过BeanDefinitionBuilder
- 通过AbstractBeanDefinition以及派生类
| BeanDefinition接口及其实现类 |
| —- |
|
|
public class BeanDefinitionDemo {
public static void main(String[] args) {
//1、通过 BeanDefinitionBuilder 构建 BeanDefinition
BeanDefinitionBuilder beanDefinitionBuilder = BeanDefinitionBuilder.genericBeanDefinition(User.class);
beanDefinitionBuilder
.setScope("singleton")
.addPropertyValue("id", 1)
.addPropertyValue("name", "黑岩射手");
AbstractBeanDefinition beanDefinition = beanDefinitionBuilder.getBeanDefinition();
//2、通过AbstractBeanDefinition以及派生类
AbstractBeanDefinition abstractBeanDefinition = new GenericBeanDefinition();
abstractBeanDefinition.setBeanClass(User.class);
abstractBeanDefinition.setScope("singleton");
abstractBeanDefinition.setPropertyValues(new MutablePropertyValues().add("id", 2).add("name", "Dead Master"));
}
}
3.命名Spring Bean
Bean的名称
- 每个Bean拥有一个或多个标识符(identifiers),这些标识符在Bean所在的容器必须是唯一的。通常,一个Bean仅有一个标识符,如果需要额外的,可考虑使用别名(Alias)来扩充。
- 在基于XML的配置元信息中,开发人员可用id或者name属性来规定Bean的标识符。通常Bean的标识符由字母组成,允许出现特殊字符。如果要想引入Bean的别名的话,可在name属性使用半角逗号(“,”)或分号(“;”)来间隔。
- Bean的id或name属性并非必须制定,如果留空的话,容器会为Bean自动生成一个唯一的名称。Bean的命名尽管没有限制,不过官方建议采用驼峰的方式,更符合Java的命名约定。
Bean的名称命名底层实现
Bean名称生成器(BeanNameGenerator)由Spring Framework 2.0.3引入,框架內建两种实现:
- DefaultBeanNameGenerator:默认通用BeanNameGenerator实现
- AnnotationBeanNameGenerator:基于注解扫描的BeanNameGenerator实现,起始于Spring
| BeanNameGenerater接口及其实现 |
| —- |
|
|
4.SpringBean的别名
Bean别名(Alias)的价值
- 复用现有的BeanDefinition
- 更具有场景化的命名方法,比如:
```xml
```java
public class BeanAliasDemo {
public static void main(String[] args) {
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("classpath:META-INF/spring-bean-definition.xml");
// 根据Bean别名查找Bean
User blackRockShooter = (User) applicationContext.getBean("blackRockShooter");
// 根据Bean名称查找Bean
User user = (User) applicationContext.getBean("user");
System.out.println(blackRockShooter==user); //true
}
}
5.注册Spring Bean
BeanDefinition注册
- XML配置元信息
- Java注解配置元信息
- @Bean
- @Component
- @Import
- Java API配置元信息
- 命名方式:BeanDefinitionRegistry#registerBeanDefinition(String,BeanDefinition)
- 非命名方式:
- BeanDefinitionReaderUtils#registerWithGeneratedName(AbstractBeanDefinition,BeanDe
finitionRegistry)
- BeanDefinitionReaderUtils#registerWithGeneratedName(AbstractBeanDefinition,BeanDe
- 配置类方式:AnnotatedBeanDefinitionReader#register(Class…) ```java /**
{@link Import}注解注册Bean */ @Import(AnnotationBeanDefinitionDemo.Config.class) public class AnnotationBeanDefinitionDemo {
public static void main(String[] args) {
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(); applicationContext.register(Config.class);
AbstractBeanDefinition beanDefinition = BeanDefinitionBuilder.genericBeanDefinition(User.class)
.addPropertyValue("id", 1)
.addPropertyValue("name", "逢坂大河")
.getBeanDefinition();
// java API 方式注册Bean —— 命名方式
applicationContext.registerBeanDefinition("tiger", beanDefinition);
// java API 方式注册Bean —— 非命名方式
BeanDefinitionReaderUtils.registerWithGeneratedName(beanDefinition, applicationContext);
// 配置类方式 AnnotatedBeanDefinitionReader#registerBean
AnnotatedBeanDefinitionReader annotatedBeanDefinitionReader = new AnnotatedBeanDefinitionReader(applicationContext);
annotatedBeanDefinitionReader.registerBean(Config.class);
// 启动容器
applicationContext.refresh();
applicationContext.getBeansOfType(User.class).forEach((beanName, user) -> System.out.println(beanName + " : " + user));
System.out.println(applicationContext.getBean(Config.class).getUser(3, "魔法小樱"));
}
/**
* {@link Component} 注解注册Bean
*/
@Component
public static class Config {
/**
* {@link Bean} 注解方式注册Bean
*/
@Bean
public User user() {
return new User(2, "black-rock-shooter");
}
public User getUser(int id, String name) {
return new User(id, name);
}
}
} ``` 外部单例对象注册
Java API配置元信息
常规方式
- 通过构造器(配置元信息:XML、Java注解和Java API)
- 通过静态工厂方法(配置元信息:XML和Java API)
- 通过Bean工厂方法(配置元信息:XML和Java API)
- 通过FactoryBean(配置元信息:XML、Java注解和Java API)
特殊方式
@PostConstruct标注方法
- 实现InitializingBean接口的afterPropertiesSet()方法
- 自定义初始化方法
- XML配置:
- Java注解:@Bean(initMethod=”init”)
- Java API:AbstractBeanDefinition#setInitMethodName(String)
- XML配置:
初始化回调方法执行顺序:
- 调用@PostConstruct注释的方法
- 调用实现InitializingBean回调接口定义的afterPropertiesSet()方法
- 调用一个自定义配置的init()方法
8.延迟初始化Spring Bean
Bean延迟初始化(Lazy Initialization)
- XML配置:
- Java注解:@Lazy(true
9.销毁Spring Bean
Bean销毁(Destroy)
- @PreDestroy标注方法
- 实现DisposableBean接口的destroy()方法
- 自定义销毁方法
- XML配置:
- Java注解:@Bean(destroy=”destroy”)
- Java API:AbstractBeanDefinition#setDestroyMethodName(String
- XML配置:
销毁回调方法执行顺序:
- 调用@PreDestroy注释的方法
- 调用实现DisposableBean回调接口的destroy()方法
-
10.垃圾回收Spring Bean
Bean垃圾回收(GC)
关闭Spring容器(应用上下文)
- 执行GC
- Spring Bean覆盖的finalize()方法被回调
11.面试题精选
- 如何注册一个Spring Bean?
答:通过BeanDefinition和外部单体对象来注册
- 什么是Spring BeanDefinition?
BeanDefinition是Spring Framework中定义Bean配置的元信息接口,包含:
- Bean的类名
- Bean的行为配置,如作用域、自动绑定的模式、生命周期回调等
- 其他Bean的引用,又可称为合作者(Colloborators)或者依赖(Dependency)
- 配置设置,比如Bean属性(Properties)
- Spring容器是怎样管理注册Bean
IoC配置元信息读取和解析、依赖查找和注入以及Bean生命周期等。