BeanFactory 功能介绍
BeanFactory 是核心容器,负责管理 Bean 对象
- BeanFactory 接口的功能只有一个 getBean() 方法
- BeanFactory 的实现类(DefaultListableBeanFactory)包含:控制反转、基本的依赖注入、Bean 生命周期的各种功能,不能只考虑接口功能
@SpringBootApplication
public class SpringApplicationMain {
@SneakyThrows
public static void main(String[] args) {
ConfigurableApplicationContext context = SpringApplication.run(SpringApplicationMain.class, args);
ConfigurableListableBeanFactory beanFactory = context.getBeanFactory();
// 通过反射方式来获取私有成员变量
Field singletonObjectsField = DefaultSingletonBeanRegistry.class.getDeclaredField("singletonObjects");
singletonObjectsField.setAccessible(true);
Map<String, Object> singletonObjects = (Map<String, Object>) singletonObjectsField.get(beanFactory);
// 事先已经通过注解为Spring容器中注入两个以"component_"开头的组件, 这里过滤得到
singletonObjects.entrySet().stream()
.filter(e -> e.getKey().startsWith("component_"))
.forEach(e -> System.out.println(e.getKey() + " = " + e.getValue()));
}
}
文章主线
DefaultListableBeanFactory(默认实现类)
手动向 BeanFactory 容器中注入 BeanDefinition(Bean对象)
方式一
public class BeanFactoryApplication {
public static void main(String[] args) {
DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
// 1. 注册BeanDefinition
BeanDefinitionRegistry registry = beanFactory;
RootBeanDefinition studentBeanDefinition = new RootBeanDefinition(Student.class);
RootBeanDefinition teacherBeanDefinition = new RootBeanDefinition(Teacher.class);
registry.registerBeanDefinition("studentBean", studentBeanDefinition);
registry.registerBeanDefinition("teacherBean", teacherBeanDefinition);
// 2. 依赖注入的两种方式(二选一即可)
// 2.1 通过构造器方式进行依赖关系的注入
ConstructorArgumentValues argumentValues = new ConstructorArgumentValues();
argumentValues.addIndexedArgumentValue(0, teacherBeanDefinition);
argumentValues.addIndexedArgumentValue(1, "student");
studentBeanDefinition.setConstructorArgumentValues(argumentValues);
// 2.2 通过setter方法进行依赖关系的注入
// MutablePropertyValues propertyValues = new MutablePropertyValues();
// propertyValues.addPropertyValue(new PropertyValue("teacher", teacherBeanDefinition));
// propertyValues.addPropertyValue(new PropertyValue("name", "student"));
// studentBeanDefinition.setPropertyValues(propertyValues);
Student student = beanFactory.getBean(Student.class);
System.out.println(student);
}
}
方式二
public class SpringApplicationMain {
//TODO: 此时的 BeanFactory 缺乏解析 @Bean 和 @Configuration 等注解的能力
public static void main(String[] args) {
// 1. 默认的 BeanFactory 容器
DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
// 2. 创建 BeanDefinition
BeanDefinition beanDefinition = BeanDefinitionBuilder
.genericBeanDefinition(MyConfig.class)
.setScope("singleton")
.getBeanDefinition();
// 3. 向容器中添加 BeanDefinition,自定义组件名
beanFactory.registerBeanDefinition("myComponentName", beanDefinition);
// 4. 输出容器中的 Bean
for (String beanDefinitionName : beanFactory.getBeanDefinitionNames()) {
System.out.println(beanDefinitionName);
}
}
}
使用 BeanFactoryPostProcessor 解析 @Bean 注解
此时 BeanFactory 并没有具备解析 @Configuration 和 @Bean 的能力,还需要额外做两件事情:
- 添加专门处理 @Configuration 的 BeanFactoryPostProcessor(后置处理器),这里也就是 ConfigurationClassPostProcessor
- 让这些 BeanFactoryPostProcessor 作用到 BeanFactory 中的对象
public class BeanPostProcessorDemo {
public static void main(String[] args) {
DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
RootBeanDefinition myConfig = new RootBeanDefinition(MyConfig.class);
beanFactory.registerBeanDefinition(MyConfig.class.getName(), myConfig);
// AnnotationConfigUtils.registerAnnotationConfigProcessors(beanFactory);
// 1. 模拟上面方法的行为:注册固定的几个BeanDefinition,封装到BeanDefinitionHolder中
Set<BeanDefinitionHolder> beanDefinitionHolders = new LinkedHashSet<>(8);
RootBeanDefinition configurationClassPostProcessorBeanDefinition = new RootBeanDefinition(ConfigurationClassPostProcessor.class);
String configurationBeanName = ConfigurationClassPostProcessor.class.getName();
beanFactory.registerBeanDefinition(configurationBeanName, configurationClassPostProcessorBeanDefinition);
BeanDefinitionHolder beanDefinitionHolder = new BeanDefinitionHolder(configurationClassPostProcessorBeanDefinition, configurationBeanName);
beanDefinitionHolders.add(beanDefinitionHolder);
// @Configuration对应BeanFactoryPostProcessor,注解和处理器之间并不是一对一的关系,而是多对一
// 2. 将BeanFactoryPostProcessor应用到BeanFactory工厂上
Map<String, BeanFactoryPostProcessor> beanFactoryPostProcessorMap = beanFactory.getBeansOfType(BeanFactoryPostProcessor.class);
beanFactoryPostProcessorMap.values().forEach(beanFactoryPostProcessor -> {
beanFactoryPostProcessor.postProcessBeanFactory(beanFactory);
});
for (String beanName : beanFactory.getBeanDefinitionNames()) {
System.out.println("beanName = " + beanName);
}
}
}
流程:
- 在 @Configuration 注解对应的 BeanFactoryPostProcessor 的处理过程中,存在 this.environment = new StandardEnvironment() 设置 Environment 对象的语句。
- 关键代码 ConfigurationClassParser 中的 doProcessConfigurationClass() 方法,其中先处理 @Configuration 标注的配置类上的其它注解,例如 @Import、@ImportSource 等。在方法的最后部分才去处理 @Bean 注解,称之为 BeanMethod。在解析 @Bean 得到的 BeanDefinition 没有设置 BeanClass
- @Configuration 标注的配置类被作为 @Bean 标注的 BeanMethod 产生的 BeanDefinition 的 FactoryBean,也就是说 @Configuration 作为 @Bean 的工厂,而这个方法(BeanMethod)本身作为 FactoryMethod。小结:@Bean 标注在方法上可以产生 BeanDefinition,对于这个 BeanDefinition 而言,方法所在的配置类就是 FactoryBean,方法就是 FactoryMethod。
- processCommonDefinitionAnnotations 方法是在解析和 BeanDefinition 有关的其它属性值,例如 lazyInit,primary 等。
- 在 @Configuration 注解处理完之后,会使用 Enhancer 来对配置类进行增强(动态代理)。对于 Spring 框架没有将 Cglib 作为外部依赖引入,而是在项目内重写(从包路径可以看出),这种方式称为内嵌 cglib。那内嵌 tomcat 也是如此。在 enhanceConfigurationClasses 方法的逻辑中,会通过 beanDef.setBeanClass(enhancedClass); 用生成的代理类来替换掉 beanDef 中的目标类(MyConfig.class)来作为 beanDefinition的 beanClass。
疑问:
BeanNameGenerator generator = (BeanNameGenerator)
sbr.getSingleton(AnnotationConfigUtils.CONFIGURATION_BEAN_NAME_GENERATOR);
这里的 getSingleton() 似乎也是从 BeanFactory 中获取的,但是并没有注入啊,并且在前面 debug 的过程中也发现此时的容器中只有两个 BeanDefinition。答:所以这里返回的是 null。
AnnotatedBeanDefinition 对应什么?在多个地方看到判断
目前已知的信息:使用 @Bean 创建出来的 BeanDefinition 属于 ConfigurationClassBeanDefinition,这是一个私有内部类,继承了 RootBeanDefinition,并且实现了 AnnotatedBeanDefinition 接口。从 AnnotatedBeanDefinition 中的方法可以看出,可以得到 Metadata 和 FactoryMethodMetadata,分别对应所属于的类和方法。
abd.resolveBeanClass(this.beanClassLoader);
这行代码返回值并没有使用,单纯为了检查是否合法吗?
使用 BeanPostProcessor 解析 @Autowired 注解
// TODO: 为什么多了一个ImportRegistry对象?
// 总结:BeanFactory不会做的事情
// 1. 不会主动调用 BeanFactoryPostProcessor
// 2. 不会主动添加 BeanPostProcessor
// 3. 不会解析BeanFactory
// 4. 不会解析#{}和${}
public class AutowiredAnnotationBeanPostProcessorDemoV3 {
public static void main(String[] args) {
DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
RootBeanDefinition configurationBeanDefinition = new RootBeanDefinition(MyConfigV3.class);
beanFactory.registerBeanDefinition(MyConfigV3.class.getSimpleName(), configurationBeanDefinition);
// 同样需要先处理@Bean
RootBeanDefinition configurationAnnotationProcessorBeanDefinition = new RootBeanDefinition(ConfigurationClassPostProcessor.class);
beanFactory.registerBeanDefinition(ConfigurationClassPostProcessor.class.getSimpleName(), configurationAnnotationProcessorBeanDefinition);
// 再处理@Autowired
RootBeanDefinition autowiredAnnotationProcessorBeanDefinition = new RootBeanDefinition(AutowiredAnnotationBeanPostProcessor.class);
beanFactory.registerBeanDefinition(AutowiredAnnotationBeanPostProcessor.class.getSimpleName(), autowiredAnnotationProcessorBeanDefinition);
Map<String, BeanFactoryPostProcessor> beanFactoryPostProcessorMap = beanFactory.getBeansOfType(BeanFactoryPostProcessor.class);
beanFactoryPostProcessorMap.values().forEach(beanFactoryPostProcessor -> {
beanFactoryPostProcessor.postProcessBeanFactory(beanFactory);
});
// !!!注意:这里不能调用getBean(),因为还没有添加BeanPostProcessor,此时创建的Bean没有被BeanPostProcessor增强就放入到Spring容器中,
// 后面再获取Bean也是直接从容器中获取,不会再经历Bean的生命周期去创建一次
// Map<String, Object> beansBeforePostProcessor = beanFactory.getBeansOfType(Object.class);
// beansBeforePostProcessor.forEach((beanName, bean) -> {
// System.out.println("=======================================");
// System.out.println("beanName = " + beanName);
// System.out.println("bean = " + bean);
// });
// 之前registerBeanDefinition只是将这个类型作为BeanDefinition,
// 只有调用addBeanPostProcessor()才代表将其作为BeanPostProcessor
// 这里和BeanFactoryPostProcessor是有区别的
Map<String, BeanPostProcessor> beanPostProcessorMap = beanFactory.getBeansOfType(BeanPostProcessor.class);
beanPostProcessorMap.values().forEach(beanFactory::addBeanPostProcessor);
// 在这里相当于提前调用了一遍getBean()
beanFactory.preInstantiateSingletons();
Map<String, Object> beansAfterPostProcessor = beanFactory.getBeansOfType(Object.class);
beansAfterPostProcessor.forEach((beanName, bean) -> {
System.out.println("=======================================");
System.out.println("beanName = " + beanName);
System.out.println("bean = " + bean);
});
}
}
不同 BeanPostProcessor 之间的排序规则
源码解析
注册 Bean(registerBeanDefinition 方法)
BeanDefinition 实例都保存在 BeanFactory 的 Map<String, BeanDefinition> 结构中,因此只需要记录 beanName,就可以从 BeanFactory 中获取到 BeanDefinition 实例。
字段 | 描述 |
---|---|
scope | 默认提供 singleton 和 prototype 两种,其它类型属于 web 的扩展 |
parentName | 父 Bean 对象的 beanName |
beanClassName | Bean 对象的全类名 |
lazyInit | Bean 对象是否懒加载 |
dependsOn | 依赖的所有 Bean 的 beanName |
primary | Bean 是否是同类型优先级最高的 |
factoryBeanName | FactoryBean 的 beanName |
factoryMethodName | 工厂方法名 |
constructorArgumentValues | 构造器参数 |
mutablePropertyValues |
如果alreadyCreated集合中存在BeanDefinition,那么会加锁
因为Map是无序的,因此使用beanDefinitionNames来保存添加BeanDefinition的顺序
public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition)
throws BeanDefinitionStoreException {
if (beanDefinition instanceof AbstractBeanDefinition) {
((AbstractBeanDefinition) beanDefinition).validate();
}
BeanDefinition existingDefinition = this.beanDefinitionMap.get(beanName);
// beanName重复的情况:更新beanDefinitionMap
if (existingDefinition != null) {
// 如果不允许Bean覆盖,即不允许出现两个重名的Bean,那么抛出异常。这是默认配置的情况
if (!isAllowBeanDefinitionOverriding()) {
throw new BeanDefinitionOverrideException(beanName, beanDefinition, existingDefinition);
}
this.beanDefinitionMap.put(beanName, beanDefinition);
}
else {
// alreadyCreated中存在BeanDefinition的情况,会为beanDefinitionMap加锁
// TODO: 这里是一段重点代码,多次出现类似加锁的情况,为什么要加锁?为什么要这么处理?
// 判断是否有其它的Bean开始初始化
if (hasBeanCreationStarted()) {
synchronized (this.beanDefinitionMap) {
this.beanDefinitionMap.put(beanName, beanDefinition);
List<String> updatedDefinitions = new ArrayList<>(this.beanDefinitionNames.size() + 1);
updatedDefinitions.addAll(this.beanDefinitionNames);
updatedDefinitions.add(beanName);
this.beanDefinitionNames = updatedDefinitions;
removeManualSingletonName(beanName);
}
}
else {
// 一般情况下进入到该分支
this.beanDefinitionMap.put(beanName, beanDefinition);
this.beanDefinitionNames.add(beanName);
removeManualSingletonName(beanName);
}
this.frozenBeanDefinitionNames = null;
}
if (existingDefinition != null || containsSingleton(beanName)) {
resetBeanDefinition(beanName);
}
else if (isConfigurationFrozen()) {
clearByTypeCache();
}
}
使用 BeanFactoryPostProcessor 解析 @Configuration 配置类
附录
BeanFactoryPostProcessor 层次体系
BeanPostProcessor 体系
BeanPostProcessor | 描述 |
---|---|
AutowiredAnnotationBeanPostProcessor | 解析 @Autowired 注解 |
CommonAnnotationBeanPostProcessor | 解析 @Resource 等 JDK 注解 |