BeanFactory 功能介绍
BeanFactory 是核心容器,负责管理 Bean 对象
- BeanFactory 接口的功能只有一个 getBean() 方法
- BeanFactory 的实现类(DefaultListableBeanFactory)包含:控制反转、基本的依赖注入、Bean 生命周期的各种功能,不能只考虑接口功能
@SpringBootApplicationpublic class SpringApplicationMain {@SneakyThrowspublic 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. 注册BeanDefinitionBeanDefinitionRegistry 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. 创建 BeanDefinitionBeanDefinition beanDefinition = BeanDefinitionBuilder.genericBeanDefinition(MyConfig.class).setScope("singleton").getBeanDefinition();// 3. 向容器中添加 BeanDefinition,自定义组件名beanFactory.registerBeanDefinition("myComponentName", beanDefinition);// 4. 输出容器中的 Beanfor (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);// 同样需要先处理@BeanRootBeanDefinition configurationAnnotationProcessorBeanDefinition = new RootBeanDefinition(ConfigurationClassPostProcessor.class);beanFactory.registerBeanDefinition(ConfigurationClassPostProcessor.class.getSimpleName(), configurationAnnotationProcessorBeanDefinition);// 再处理@AutowiredRootBeanDefinition 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重复的情况:更新beanDefinitionMapif (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 注解 |