当前位置: 首页 > ops >正文

chapter06_应用上下文与门面模式

一、应用上下文

目前对Spring的使用,还是太复杂

  • 先要知道BeanFactory接口的最终实现类,DefaultListableBeanFactory
  • 还要创建XmlBeanDefinitionReader,读取BeanDefinition
@Test
public void testGetBeanFromXml() {// 1.初始化 BeanFactoryDefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();// 2. 读取配置文件&注册BeanXmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(beanFactory);reader.loadBeanDefinitions("classpath:spring.xml");// 3. 获取Bean对象调用方法Person person = (Person) beanFactory.getBean("person");System.out.println("person:" + person);
}

对外提供一个上下文,屏蔽掉DefaultListableBeanFactory与XmlBeanDefinitionReader,让外界使用只需要一行代码即可使用spring,这就是门面设计模式,对外提供一个统一接口,屏蔽掉内部实现细节

  • 门面内部会帮我们调用Spring各个子系统,完成具体的功能
  • 门面内部还可以给BeanFactory增加更多的功能,例如Bean的各种前置、后置处理器
  • 使用门面模式后,对用户而言,可以更加方便的使用BeanFactory

请添加图片描述

二、新建ApplicationContext

首先新建一个接口ListableBeanFactory,继承BeanFactory接口,扩展一个根据类型获取所有的Bean实例

public interface ListableBeanFactory extends BeanFactory{/*** 返回指定类型的所有实例** @param type* @param <T>* @return*/<T> Map<String, T> getBeansOfType(Class<T> type);
}

新建ApplicationContext接口,继承ListableBeanFactory,这样ApplicationContext就具备了getBean的能力

public interface ApplicationContext extends ListableBeanFactory {
}

新建ConfigurableApplicationContext接口,继承ApplicationContext接口

  • ApplicationContext本身是一个只读接口
  • 扩展后,允许彻底销毁并重新创建 BeanFactory,重新加载配置
  • refresh是Spring生命周期的关键方法
public interface ConfigurableApplicationContext extends ApplicationContext {void refresh();
}

新建AbstractApplicationContext,使用模板方法设计模式(类似于AbstractBeanFactory),实现refresh和三个getBean方法

  1. refreshBeanFactory,创建BeanFactory并加载BeanDefinition,交给子类实现
  2. getBeanFactory,交给子类实现
  3. 扩展点一,BeanFactoryPostProcessor,在所有的 BeanDefinition 加载完成后,实例化 Bean 对象之前,提供修改 BeanDefinition 属性的机制
  4. 扩展点二,BeanPostProcessor,提供初始化前和初始化后修改Bean的能力
  5. 实例化所有的Bean对象

定义两个抽象方法refreshBeanFactory,getBeanFactory,交给子类实现

public abstract class AbstractApplicationContext extends DefaultResourceLoader implements ConfigurableApplicationContext {@Overridepublic void refresh() {//创建BeanFactory,并扫描BeanDefinitionrefreshBeanFactory();ConfigurableListableBeanFactory beanFactory = getBeanFactory();//在bean实例化之前,执行BeanFactoryPostProcessorinvokeBeanFactoryPostProcessors(beanFactory);//BeanPostProcessor需要提前于其他bean实例化之前注册registerBeanPostProcessors(beanFactory);//提前实例化单例beanbeanFactory.preInstantiateSingletons();}/*** 创建BeanFactory,并加载BeanDefinition*/protected abstract void refreshBeanFactory();public abstract ConfigurableListableBeanFactory getBeanFactory();/*** 在bean实例化之前,执行BeanFactoryPostProcessor** @param beanFactory*/protected void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory) {Map<String, BeanFactoryPostProcessor> beanFactoryPostProcessorMap = beanFactory.getBeansOfType(BeanFactoryPostProcessor.class);for (BeanFactoryPostProcessor beanFactoryPostProcessor : beanFactoryPostProcessorMap.values()) {beanFactoryPostProcessor.postProcessBeanFactory(beanFactory);}}/*** 注册BeanPostProcessor** @param beanFactory*/protected void registerBeanPostProcessors(ConfigurableListableBeanFactory beanFactory) {Map<String, BeanPostProcessor> beanPostProcessorMap = beanFactory.getBeansOfType(BeanPostProcessor.class);for (BeanPostProcessor beanPostProcessor : beanPostProcessorMap.values()) {beanFactory.addBeanPostProcessor(beanPostProcessor);}}@Overridepublic Object getBean(String name, Object... args) {return getBeanFactory().getBean(name, args);}@Overridepublic <T> Map<String, T> getBeansOfType(Class<T> type) {return getBeanFactory().getBeansOfType(type);}public Object getBean(String name) {return getBeanFactory().getBean(name);}
}

BeanFactoryPostProcessor对BeanDefinition修改的原理

  • 直接调用了invokeBeanFactoryPostProcessors,调用了getBeansOfType
protected void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory) {Map<String, BeanFactoryPostProcessor> beanFactoryPostProcessorMap = beanFactory.getBeansOfType(BeanFactoryPostProcessor.class);for (BeanFactoryPostProcessor beanFactoryPostProcessor : beanFactoryPostProcessorMap.values()) {beanFactoryPostProcessor.postProcessBeanFactory(beanFactory);}}
  • getBeansOfType,最终还是调用了getBean,提前将BeanFactoryPostProcessor类型的Bean创建了
@Override
public <T> Map<String, T> getBeansOfType(Class<T> type) {Map<String, T> result = new HashMap<>();beanDefinitionMap.forEach((beanName, beanDefinition) -> {Class beanClass = beanDefinition.getBeanClass();if (type.isAssignableFrom(beanClass)) {T bean = (T) getBean(beanName);result.put(beanName, bean);}});return result;
}

BeanFactoryProcessor对Bean修改的原理

  • 在refresh的时候,先将BeanFactoryProcessor类型的Bean实例化
/*** 注册BeanPostProcessor** @param beanFactory*/protected void registerBeanPostProcessors(ConfigurableListableBeanFactory beanFactory) {Map<String, BeanPostProcessor> beanPostProcessorMap = beanFactory.getBeansOfType(BeanPostProcessor.class);for (BeanPostProcessor beanPostProcessor : beanPostProcessorMap.values()) {beanFactory.addBeanPostProcessor(beanPostProcessor);}}

注册BeanPostProcessor,并在实例化Bean的时候,调用

@Override
public void addBeanPostProcessor(BeanPostProcessor beanPostProcessor) {//有则覆盖this.beanPostProcessors.remove(beanPostProcessor);this.beanPostProcessors.add(beanPostProcessor);
}

容易让人疑惑的地方,BeanFactoryPostProcessor和BeanPostProcessor自己也是Bean,自己getBeansOfType也要先实例化

  • BeanFactoryPostProcessor实例化的时候,BeanPostProcessor还没有注册,此时没有BeanPostProcessor,不会调用
  • BeanPostProcessor实例化的时候,可能已经有其它BeanPostProcessor注册了,所以会有BeanPostProcessor匹配上,所以BeanPostProcessor代码一定要写明确,对特定的类型进行初始化修改,避免引起歧义

新建AbstractRefreshableApplicationContext,实现上述两个抽象方法

  • 本类的任务就是完成Refresh功能
  • refreshBeanFactory的时候,会重新创建一个DefaultListableBeanFactory,调用loadBeanDefinitions抽象方法
  • getBeanFactory的时候,直接返回刚刚创建的BeanFactory
public abstract class AbstractRefreshableApplicationContext extends AbstractApplicationContext {private DefaultListableBeanFactory beanFactory;@Overrideprotected void refreshBeanFactory() {DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();loadBeanDefinitions(beanFactory);this.beanFactory = beanFactory;}/*** 加载BeanDefinition** @param beanFactory*/protected abstract void loadBeanDefinitions(DefaultListableBeanFactory beanFactory);@Overridepublic DefaultListableBeanFactory getBeanFactory() {return beanFactory;}
}

新建AbstractXmlApplicationContext,完成loadBeanDefinitions抽象方法

  • 真正干活的是XmlBeanDefinitionReader,由它读取XML中的Bean定义
  • 唯一不确定的是configLocations,继续将getConfigLocations交给子类实现
public abstract class AbstractXmlApplicationContext extends AbstractRefreshableApplicationContext {@Overrideprotected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) {XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory, this);String[] configLocations = getConfigLocations();if (configLocations != null) {beanDefinitionReader.loadBeanDefinitions(configLocations);}}protected abstract String[] getConfigLocations();
}

新建ClassPathXmlApplicationContext,继承AbstractXmlApplicationContext

  • 构造函数里面做了两件事情,保存xml文件的路径,调用refresh()方法
  • 实现父类的抽象方法getConfigLocations
public class ClassPathXmlApplicationContext extends AbstractXmlApplicationContext{private String[] configLocations;/*** 从xml文件加载BeanDefinition,并且自动刷新上下文** @param configLocation xml配置文件*/public ClassPathXmlApplicationContext(String configLocation) {this(new String[]{configLocation});}/*** 从xml文件加载BeanDefinition,并且自动刷新上下文** @param configLocations xml配置文件*/public ClassPathXmlApplicationContext(String[] configLocations) {this.configLocations = configLocations;refresh();}@Overrideprotected String[] getConfigLocations() {return this.configLocations;}
}

三、重构BeanFactory

给AbstractBeanFactory类,新增管理BeanPostProcessors的功能

新建HierarchicalBeanFactory接口,继承BeanFactory接口

  • 让BeanFactory支持“父子容器”层次结构
public interface HierarchicalBeanFactory extends BeanFactory{
}

新建ConfigurableBeanFactory接口,继承HierarchicalBeanFactory接口,让BeanFactory可配置化

  • 本章节,扩展管理BeanPostProcessor的能力
  • 后续章节,扩展销毁Bean的能力
public interface ConfigurableBeanFactory extends HierarchicalBeanFactory {/*** @param beanPostProcessor*/void addBeanPostProcessor(BeanPostProcessor beanPostProcessor);
}

让AbstractBeanFactory类,实现ConfigurableBeanFactory接口

  • 新增一个属性,保存beanPostProcessors,提供相应的get,set方法
public abstract class AbstractBeanFactory extends DefaultSingletonBeanRegistry implements ConfigurableBeanFactory {private final List<BeanPostProcessor> beanPostProcessors = new ArrayList<>();······@Overridepublic void addBeanPostProcessor(BeanPostProcessor beanPostProcessor) {//有则覆盖this.beanPostProcessors.remove(beanPostProcessor);this.beanPostProcessors.add(beanPostProcessor);}public List<BeanPostProcessor> getBeanPostProcessors() {return beanPostProcessors;}
}

修改AbstractAutowireCapableBeanFactory,在Bean创建时完成前置、后置处理器的调用

  • 修改createBean方法的业务流程,新增初始化initializeBean方法调用
  • initializeBean方法是定义业务流程,包括初始化前和后的扩展
  • 真正的初始化方法是invokeInitMethods
/*** 负责创建Bean** @Author 孤风雪影* @Email gitee.com/efairy520* @Date 2025/1/1 1:01* @Version 1.0*/
public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFactory implements AutowireCapableBeanFactory {private final InstantiationStrategy instantiationStrategy = new SimpleInstantiationStrategy();/*** 实现父类未实现的createBean方法* @param beanName* @param beanDefinition* @return*/@Overrideprotected Object createBean(String beanName, BeanDefinition beanDefinition, Object[] args) {Object bean = doCreateBean(beanName, beanDefinition, args);populateBean(beanName, bean, beanDefinition);bean = initializeBean(beanName, bean, beanDefinition);addSingleton(beanName, bean);return bean;}protected Object initializeBean(String beanName, Object bean, BeanDefinition beanDefinition) {//执行BeanPostProcessor的前置处理Object wrappedBean = applyBeanPostProcessorsBeforeInitialization(bean, beanName);//TODO 后面会在此处执行bean的初始化方法invokeInitMethods(beanName, wrappedBean, beanDefinition);//执行BeanPostProcessor的后置处理wrappedBean = applyBeanPostProcessorsAfterInitialization(bean, beanName);return wrappedBean;}/*** 执行bean的初始化方法** @param beanName* @param bean* @param beanDefinition* @throws Throwable*/protected void invokeInitMethods(String beanName, Object bean, BeanDefinition beanDefinition) {//TODO 后面会实现}·······@Overridepublic Object applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName) {Object result = existingBean;for (BeanPostProcessor processor : getBeanPostProcessors()) {Object current = processor.postProcessBeforeInitialization(result, beanName);if (current == null) {return result;}result = current;}return result;}@Overridepublic Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName) {Object result = existingBean;for (BeanPostProcessor processor : getBeanPostProcessors()) {Object current = processor.postProcessAfterInitialization(result, beanName);if (current == null) {return result;}result = current;}return result;}
}

四、测试类

新建MyBeanFactoryPostProcessor类

public class MyBeanFactoryPostProcessor implements BeanFactoryPostProcessor {@Overridepublic void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) {System.out.println("MyBeanFactoryPostProcessor#postProcessBeanFactory");//此后置处理器,修改person的名称BeanDefinition personBeanDefiniton = beanFactory.getBeanDefinition("person");PropertyValues propertyValues = personBeanDefiniton.getPropertyValues();//将person的name属性改为updatedpropertyValues.addPropertyValue(new PropertyValue("name", "MyBeanFactoryPostProcessor改为:Steven Curry"));}
}

新建MyBeanPostProcessor类

public class MyBeanPostProcessor implements BeanPostProcessor {@Overridepublic Object postProcessBeforeInitialization(Object bean, String beanName) {if ("cat".equals(beanName)) {Cat cat = (Cat) bean;cat.setName("Bean后置初始化前改为:汤姆猫");}return bean;}@Overridepublic Object postProcessAfterInitialization(Object bean, String beanName) {return null;}
}

新建springPostProcessor.xml文件

<?xml version="1.0" encoding="UTF-8"?>
<beans><bean id="cat" class="cn.shopifymall.springframework.test.bean.Cat"><property name="name" value="tomcat"/><property name="weight" value="2000"/></bean><bean id="person" class="cn.shopifymall.springframework.test.bean.Person"><property name="name" value="LeBron James"/><property name="age" value="18"/><property name="cat" ref="cat"/></bean><bean class="cn.shopifymall.springframework.test.common.MyBeanPostProcessor"/><bean class="cn.shopifymall.springframework.test.common.MyBeanFactoryPostProcessor"/></beans>

测试类

public class ApiTest {@Testpublic void test_xml() {// 1.初始化 BeanFactoryClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("classpath:springPostProcessor.xml");// 2. 获取Bean对象调用方法Person person = (Person) applicationContext.getBean("person");System.out.println("测试结果:" + person);}
}

控制台输出

  • 可以看出,两种类型的处理器都起作用了
MyBeanFactoryPostProcessor#postProcessBeanFactory
测试结果:Person(name=MyBeanFactoryPostProcessor改为:Steven Curry, age=18, cat=Cat(name=Bean后置初始化前改为:汤姆猫, weight=2000))

四、总结

整个Spring最重要的方法,refresh(),定义了Spring的生命周期

  1. 创建BeanFactory实现类
  2. 扫描BeanDefinition
  3. 扩展点一:调用BeanFactory后置处理器
  4. 扩展点二:注册Bean后置处理器
  5. 提前实例化所有的单例Bean
public void refresh() {//创建BeanFactory,并扫描BeanDefinitionrefreshBeanFactory();ConfigurableListableBeanFactory beanFactory = getBeanFactory();//在bean实例化之前,执行BeanFactoryPostProcessorinvokeBeanFactoryPostProcessors(beanFactory);//BeanPostProcessor需要提前于其他bean实例化之前注册registerBeanPostProcessors(beanFactory);//提前实例化单例beanbeanFactory.preInstantiateSingletons();
}

在Spring中,一切都是Bean,后置处理器本身也是Bean,也要注册到容器中

  • 没有配置id的时候,beanName就是简单类名的首字母小写

实现上下文后的骨架

  • 层1:缓存单例Bean
  • 层2:串联上下游,管理BeanPostProcessor
  • 层3:创建Bean
  • 层4:管理BeanDefinition

请添加图片描述

http://www.xdnf.cn/news/18546.html

相关文章:

  • 每日算法题【链表】:链表的中间节点、返回倒数第k个节点、合并两个有序链表
  • MySQL优化器追踪(Optimizer Trace)详解
  • APIs基础one
  • docker的数据管理
  • Java试题-选择题(16)
  • 论文阅读:arxiv 2025 Can You Trick the Grader? Adversarial Persuasion of LLM Judges
  • selenium采集数据怎么应对反爬机制?
  • Python爬虫实战:研究WSL技术,构建跨平台数据采集和分析系统
  • 从人工巡检到智能监测:工业设备管理的颠覆性变革
  • Selenium
  • 系统思考:突破复杂困境
  • 随机森林2——集成学习的发展
  • EPWpy 安装教程
  • 如何解决 pyqt5 程序“长时间运行失效” 问题?
  • 爬小红书图片软件:根据搜索关键词,采集笔记图片、正文、评论等
  • 在云服务器中使用tmux实现程序24小时运行
  • daily notes[4]
  • Sqlserver存储过程
  • Python入门:从零开始的编程之旅
  • git实战问题(6)git push 时发现分支已被更新,push失败了怎么办
  • GaussDB 数据库架构师修炼(十八) SQL引擎-解析器
  • 学习游戏制作记录(合并更多的技能与技能树)8.23
  • [e3nn] 模型部署 | TorchScript JIT | `@compile_mode`装饰器 | Cython
  • 老年常见疾病及健康管理建议
  • 精斗云智能开单解决方案:高效移动办公新体验
  • Qt/C++开发监控GB28181系统/录像文件回放/自动播放下一个录像文件/倍速回放/录像文件下载
  • openharmony之一多开发:产品形态配置讲解
  • 使用自制的NTC测量模块测试Plecs的热仿真效果
  • 分布式蜜罐系统的部署安装
  • 微服务统一入口——Gateway