容器接口
- BeanFactory 接口,典型功能有:
- getBean
- ApplicationContext 接口,是 BeanFactory 的子接口。它扩展了 BeanFactory 接口的功能,如:
- 国际化
- 通配符方式获取一组 Resource 资源
- 整合 Environment 环境(能通过它获取各种来源的配置信息)
- 事件发布与监听,实现组件之间的解耦
BeanFactory与Application的区别
- 到底什么是 BeanFactory
- 它是 ApplicationContext 的父接口
- 它才是 Spring 的核心容器, 主要的 ApplicationContext 实现都【组合】了它的功能,【组合】是指 ApplicationContext 的一个重要成员变量就是 BeanFactory
- BeanFactory 能干点啥
- 表面上只有 getBean
- 实际上控制反转、基本的依赖注入、直至 Bean 的生命周期的各种功能,都由它的实现类提供
- 通过反射查看了它的成员变量 singletonObjects,内部包含了所有的单例 bean
- ApplicationContext 比 BeanFactory 多点啥
- ApplicationContext 组合并扩展了 BeanFactory 的功能
- 国际化、通配符方式获取一组 Resource 资源、整合 Environment 环境、事件发布与监听
容器实现
具体实现类:
- DefaultListableBeanFactory,是 BeanFactory 最重要的实现,像控制反转和依赖注入功能,都是它来实现
- ClassPathXmlApplicationContext,从类路径查找 XML 配置文件,创建容器(旧)
- FileSystemXmlApplicationContext,从磁盘路径查找 XML 配置文件,创建容器(旧)
- XmlWebApplicationContext,传统 SSM 整合时,基于 XML 配置文件的容器(旧)
- AnnotationConfigWebApplicationContext,传统 SSM 整合时,基于 java 配置类的容器(旧)
- AnnotationConfigApplicationContext,Spring boot 中非 web 环境容器(新)
- AnnotationConfigServletWebServerApplicationContext,Spring boot 中 servlet web 环境容器(新)
- AnnotationConfigReactiveWebServerApplicationContext,Spring boot 中 reactive web 环境容器*(新)
带有 ApplicationContext 的类都是 ApplicationContext 接口的实现,但它们是组合了 DefaultListableBeanFactory 的功能,并非继承而来。
DefaultListableBeanFactory
- beanFactory 可以通过 registerBeanDefinition 注册一个 bean definition 对象
- 我们平时使用的配置类、xml、组件扫描等方式都是生成 bean definition 对象注册到 beanFactory 当中
- bean definition 描述了这个 bean 的创建蓝图:scope 是什么、用构造还是工厂创建、初始化销毁方法是什么,等等
- beanFactory 需要手动调用 beanFactory 后处理器对它做增强
- 例如通过解析 @Bean、@ComponentScan 等注解,来补充一些 bean definition
- beanFactory 需要手动添加 bean 后处理器,以便对后续 bean 的创建过程提供增强
- 例如 @Autowired,@Resource 等注解的解析都是 bean 后处理器完成的
- bean 后处理的添加顺序会对解析结果有影响
- beanFactory 需要手动调用方法来初始化单例
- beanFactory 需要额外设置才能解析 ${} 与 #{}
ApplicationContext实现类
// ⬇️较为经典的容器, 基于 classpath 下 xml 格式的配置文件来创建 private static void testClassPathXmlApplicationContext() { ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("a02.xml"); for (String name : context.getBeanDefinitionNames()) { System.out.println(name); } System.out.println(context.getBean(Bean2.class).getBean1()); } // ⬇️基于磁盘路径下 xml 格式的配置文件来创建 private static void testFileSystemXmlApplicationContext() { FileSystemXmlApplicationContext context = new FileSystemXmlApplicationContext( "src\\main\\resources\\a02.xml"); for (String name : context.getBeanDefinitionNames()) { System.out.println(name); } System.out.println(context.getBean(Bean2.class).getBean1()); } // ⬇️较为经典的容器, 基于 java 配置类来创建 private static void testAnnotationConfigApplicationContext() { AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(Config.class); for (String name : context.getBeanDefinitionNames()) { System.out.println(name); } System.out.println(context.getBean(Bean2.class).getBean1()); } // ⬇️较为经典的容器, 基于 java 配置类来创建, 用于 web 环境 private static void testAnnotationConfigServletWebServerApplicationContext() { AnnotationConfigServletWebServerApplicationContext context = new AnnotationConfigServletWebServerApplicationContext(WebConfig.class); for (String name : context.getBeanDefinitionNames()) { System.out.println(name); } } @Configuration static class WebConfig { @Bean public ServletWebServerFactory servletWebServerFactory(){ return new TomcatServletWebServerFactory(); } @Bean public DispatcherServlet dispatcherServlet() { return new DispatcherServlet(); } @Bean public DispatcherServletRegistrationBean registrationBean(DispatcherServlet dispatcherServlet) { return new DispatcherServletRegistrationBean(dispatcherServlet, "/"); } @Bean("/hello") public Controller controller1() { return (request, response) -> { response.getWriter().print("hello"); return null; }; } } @Configuration static class Config { @Bean public Bean1 bean1() { return new Bean1(); } @Bean public Bean2 bean2(Bean1 bean1) { Bean2 bean2 = new Bean2(); bean2.setBean1(bean1); return bean2; } } static class Bean1 { } static class Bean2 { private Bean1 bean1; public void setBean1(Bean1 bean1) { this.bean1 = bean1; } public Bean1 getBean1() { return bean1; } } }
Bean 的生命周期
一个受 Spring 管理的 bean,生命周期主要阶段有
- 创建:根据 bean 的构造方法或者工厂方法来创建 bean 实例对象
- 依赖注入:根据 @Autowired,@Value 或其它一些手段,为 bean 的成员变量填充值、建立关系
- 初始化:回调各种 Aware 接口,调用对象的各种初始化方法
- 销毁:在容器关闭时,会销毁所有单例对象(即调用它们的销毁方法)
- prototype 对象也能够销毁,不过需要容器这边主动调用
生命周期中还有一类 bean 后置处理器,会在上述生命周期的前后,提供一些扩展逻辑。
bean后置处理器
注意:以下都是方法
创建前后的增强
- postProcessBeforeInstantiation (Instantiation:实例化)
- 这里返回的对象若不为 null 会替换掉原本的 bean,并且仅会走 postProcessAfterInitialization 流程
- postProcessAfterInstantiation
- 这里如果返回 false 会跳过依赖注入阶段
依赖注入前的增强
- postProcessProperties
- 如 @Autowired、@Value、@Resource
初始化前后的增强
- postProcessBeforeInitialization (Initialization:初始化)
- 这里返回的对象会替换掉原本的 bean
- 如 @PostConstruct、@ConfigurationProperties
- postProcessAfterInitialization
- 这里返回的对象会替换掉原本的 bean
- 如代理增强
销毁之前的增强
- postProcessBeforeDestruction
- 如 @PreDestroy
模板方法模式
Bean的生命周期中通过bean的后置处理器作扩展,使用的是模板方法模式
代码演示:
public class TestMethodTemplate { public static void main(String[] args) { MyBeanFactory beanFactory = new MyBeanFactory(); //定义不同的子类 beanFactory.addBeanPostProcessor(bean -> System.out.println("解析 @Autowired")); beanFactory.addBeanPostProcessor(bean -> System.out.println("解析 @Resource")); beanFactory.getBean(); } // 模板方法 Template Method Pattern static class MyBeanFactory { public Object getBean() { Object bean = new Object(); System.out.println("构造 " + bean); System.out.println("依赖注入 " + bean); // @Autowired, @Resource for (BeanPostProcessor processor : processors) { processor.inject(bean); } System.out.println("初始化 " + bean); return bean; } private List<BeanPostProcessor> processors = new ArrayList<>(); public void addBeanPostProcessor(BeanPostProcessor processor) { processors.add(processor); } } static interface BeanPostProcessor { public void inject(Object bean); // 对依赖注入阶段的扩展 } }
bean 后处理器排序
对于各种后处理器的执行顺序,有这样的规则:
- 实现了 PriorityOrdered 接口的优先级最高
- 实现了 Ordered 接口与加了 @Order 注解的平级, 按数字升序
- 其它的排在最后
代码演示:
/* bean 后处理的的排序 */ public class TestProcessOrder { public static void main(String[] args) { DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory(); AnnotationConfigUtils.registerAnnotationConfigProcessors(beanFactory); List<BeanPostProcessor> list = new ArrayList<>(List.of(new P1(), new P2(), new P3(), new P4(), new P5())); list.sort(beanFactory.getDependencyComparator()); list.forEach(processor->{ processor.postProcessBeforeInitialization(new Object(), ""); }); /* 学到了什么 1. 实现了 PriorityOrdered 接口的优先级最高 2. 实现了 Ordered 接口与加了 @Order 注解的平级, 按数字升序 3. 其它的排在最后 */ } @Order(1) static class P1 implements BeanPostProcessor { private static final Logger log = LoggerFactory.getLogger(P1.class); @Override public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException { log.debug("postProcessBeforeInitialization @Order(1)"); return bean; } } @Order(2) static class P2 implements BeanPostProcessor { private static final Logger log = LoggerFactory.getLogger(P2.class); @Override public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException { log.debug("postProcessBeforeInitialization @Order(2)"); return bean; } } static class P3 implements BeanPostProcessor, PriorityOrdered { private static final Logger log = LoggerFactory.getLogger(P3.class); @Override public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException { log.debug("postProcessBeforeInitialization PriorityOrdered"); return bean; } @Override public int getOrder() { return 100; } } static class P4 implements BeanPostProcessor, Ordered { private static final Logger log = LoggerFactory.getLogger(P4.class); @Override public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException { log.debug("postProcessBeforeInitialization Ordered"); return bean; } @Override public int getOrder() { return 0; } } static class P5 implements BeanPostProcessor { private static final Logger log = LoggerFactory.getLogger(P5.class); @Override public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException { log.debug("postProcessBeforeInitialization"); return bean; } } }
控制台输出样例:
[DEBUG] 22:13:30.104 [main] com.itheima.a03.TestProcessOrder$P3 - postProcessBeforeInitialization PriorityOrdered [DEBUG] 22:13:30.108 [main] com.itheima.a03.TestProcessOrder$P4 - postProcessBeforeInitialization Ordered [DEBUG] 22:13:30.108 [main] com.itheima.a03.TestProcessOrder$P1 - postProcessBeforeInitialization @Order(1) [DEBUG] 22:13:30.108 [main] com.itheima.a03.TestProcessOrder$P2 - postProcessBeforeInitialization @Order(2) [DEBUG] 22:13:30.108 [main] com.itheima.a03.TestProcessOrder$P5 - postProcessBeforeInitialization
Bean 后处理器
后处理器作用
- @Autowired 等注解的解析属于 bean 生命周期阶段(依赖注入, 初始化)的扩展功能,这些扩展功能由 bean 后处理器来完成
- 每个后处理器各自增强什么功能
- AutowiredAnnotationBeanPostProcessor 解析 @Autowired 与 @Value
- CommonAnnotationBeanPostProcessor 解析 @Resource、@PostConstruct、@PreDestroy
- ConfigurationPropertiesBindingPostProcessor 解析 @ConfigurationProperties
- 另外 ContextAnnotationAutowireCandidateResolver 负责获取 @Value 的值,解析 @Qualifier、泛型、@Lazy 等
@Autowired bean 后处理器运行分析
- AutowiredAnnotationBeanPostProcessor.findAutowiringMetadata 用来获取某个 bean 上加了 @Value @Autowired 的成员变量,方法参数的信息,表示为 InjectionMetadata
- InjectionMetadata 可以完成依赖注入
- InjectionMetadata 内部根据成员变量,方法参数封装为 DependencyDescriptor 类型
- 有了 DependencyDescriptor,就可以利用 beanFactory.doResolveDependency 方法进行基于类型的查找