1.BeanFactory
1.1 什么是BeanFactory
简单来说它是 ApplicationContext 的父接口,也是 Spring 的核心容器, 主要的 ApplicationContext 容器实现都【组合】了 BeanFactory 的功能,【组合】是指 ApplicationContext 的一个重要成员变量就是 BeanFactory
1.2 BeanFactory的作用
① 观察接口查看,表面上只有 getBean 方法
② 实际上控制反转、基本的依赖注入、直至 Bean 的生命周期的各种功能,都由它的实现类提供
③ 例子中通过反射查看了它的成员变量 singletonObjects,内部包含了所有的单例 bean
1.3 ApplicationContext
那么ApplicationContext 比 BeanFactory 多点啥?
① ApplicationContext 组合并扩展了 BeanFactory 的功能
② 国际化、通配符方式获取一组 Resource 资源、整合 Environment 环境、事件发布与监听(四个接口)
2. 容器实现
主要讲下面几种:
① DefaultListableBeanFactory:是 BeanFactory 最重要的实现,像控制反转和依赖注入功能,都是它来实现
② AnnotationConfigApplicationContext,Spring boot 中非 web 环境容器
③ AnnotationConfigServletWebServerApplicationContext,Spring boot 中 servlet web 环境容器
2.1 DefaultListableBeanFactory
下面展示如何手动实现 DefaultListableBeanFactory 容器
① beanFactory 可以通过 registerBeanDefinition 注册一个 bean definition 对象
-
我们平时使用的配置类、xml、组件扫描等方式都是生成 bean definition 对象注册到 beanFactory 当中
-
bean definition 描述了这个 bean 的创建蓝图:scope 是什么、用构造还是工厂创建、初始化销毁方法是什么,等等
DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory(); // bean 的定义(class, scope, 初始化, 销毁) AbstractBeanDefinition beanDefinition = BeanDefinitionBuilder.genericBeanDefinition( Config.class).setScope("singleton").getBeanDefinition(); beanFactory.registerBeanDefinition("config", beanDefinition);
② beanFactory 手动添加 beanFacoty 后处理器:需要手动触发所有已注册的 BeanFactoryPostProcessor,让它们在 Spring 容器真正实例化任何普通 Bean 之前,有机会去“加工”或“修改”容器中的 Bean 定义(BeanDefinition),beanFactory 需要手动调用 beanFactory 后处理器对它做增强
- 例如通过解析 @Bean、@ComponentScan 等注解,来补充一些 bean definition
③ beanFactory 手动添加 bean 后处理器,需要手动触发所有已注册的 BeanPostProcessor ,以便对后续 bean 的创建过程提供增强
- 例如 @Autowired,@Resource 等注解的解析都是 bean 后处理器完成的
- bean 后处理的添加顺序会对解析结果有影响,见视频中同时加 @Autowired,@Resource 的例子
// 给 BeanFactory 手动添加一些常用的后处理器(beanFacoty 后处理器 和 bean 后处理器 )
AnnotationConfigUtils.registerAnnotationConfigProcessors(beanFactory);
// BeanFactory 后处理器主要功能,补充了一些 bean 定义,手动激活
beanFactory.getBeansOfType(BeanFactoryPostProcessor.class).values()
.forEach(beanFactoryPostProcessor -> {
beanFactoryPostProcessor.postProcessBeanFactory(beanFactory);
});
// Bean 后处理器, 针对 bean 的生命周期的各个阶段提供扩展,手动激活
beanFactory.getBeansOfType(BeanPostProcessor.class).values().stream()
.sorted(beanFactory.getDependencyComparator())
.forEach(beanPostProcessor -> {
beanFactory.addBeanPostProcessor(beanPostProcessor);
});
④ 手动调用方法来初始化单例
beanFactory.preInstantiateSingletons();
2.2 容器实现的流程总结
① 利用 BeanDefinitionBuilder 创建 BeanDefinition()
② 将 BeanDefinition 注册到 BeanFacotry (这里采用 DefaultListableBeanFactory 实现)
③ BeanFacotry 实现的功能都很基础,所以我们需要补充一些功能
④ 利用工具类 AnnotationConfigUtils.registerAnnotationConfigProcessors(beanFactory) 添加后处理器
⑤ 当前后处理器只是存在于 BeanDefinition 中,并没有生效工作
⑥ 激活使 BeanFactory 后处理器工作,补充了一些 bean 定义,例如@Bean、@ComponentScan
⑦ 激活使 Bean 后处理器工作,针对 bean 的生命周期的各个阶段提供扩展, 例如 @Autowired @Resource …
… preInstantiateSingleton 使单例立刻创建(提前准备好所有单例)
注:
a.手动激活的时候,应该进行排序操作。有的后置处理器必须最先干活,比如扫描所有 @Autowired
注解、处理依赖注入;有的后置处理器必须最后再执行,比如 AOP 自动代理,需要等所有依赖都准备好了才给 Bean 织入切面。
b. beanFactory 不会做的事
1. 不会主动调用 BeanFactory 后处理器
2. 不会主动添加 Bean 后处理器
3. 不会主动初始化单例
4. 不会解析 beanFactory 还不会解析 ${ } 与 #{ }
c. bean 后处理器会有排序的逻辑
2.3 其他容器的实现
① ClassPathXmlApplicationContext
根据类路径读取 XML 的 Bean 配置信息
② FileSystemXmlApplicationContext
根据磁盘路径读取 XML 的 Bean 配置信息
① ② 的原理:
(1) 使用 XmlBeanDefinitionReader 设置 BeanDefinition 的读取方式,并生成读取对象
(2) 然后利用对象的 loadBeanDefinitions 方法,结合 类路径 或者 磁盘路径 读取 XML 文件
③ AnnotationConfigApplicationContext
根据 Java 配置类进行 Bean 的创建,AnnotationConfigApplicationContext 会将常用的后处理器加入到 BeanDefinition 中。XML 文件中可以通过标签开启:<context:annotation-config>
④ AnnotationConfigServletWebServerApplicationContext
根据 Java 配置类进行 Bean 的创建,AnnotationConfigServletWebServerApplicationContext 会将常用的后处理器加入到 BeanDefinition 中,用于 Web 环境
配置类中需要配置:
(1):ServletWebServerFactory(内嵌 TomCat 服务器)
(2):DispatcherServlet(前置处理器)
(3):DispatcherServletRegistrationBean (注册前置处理器并设置地址)
Web 环境
配置类中需要配置:
(1):ServletWebServerFactory(内嵌 TomCat 服务器)
(2):DispatcherServlet(前置处理器)
(3):DispatcherServletRegistrationBean (注册前置处理器并设置地址)
(4):Controller(控制器接口)