赞
踩
在陈旧系统中都是使用 SSM 架构进行搭建,Spring 源码是后续深入理解学习 SpringBoot、SpringCloud 组件所必须依赖的,只是不再采用 XML 方式来进行配置使用,在这里,主要是回顾下最初在使用 Spring 时的核心类「ClassPathXmlApplicationContext」实例过程以及配置文件加载的详细过程,因为后续的核心方法 refresh 内容讲解也得从此处开始讲起.
文章内容有点长,可以分目录节点进行阅读,比较想深入理解的方法可以点击文章目录入口.
新建 ApplicationContext 上下文对象整体流程如下
// 创建 Ant【表达式语言】 方式的路径匹配器
private PathMatcher pathMatcher = new AntPathMatcher();
setConfigLocations:设置应用程序上下文的配置路径
customizePropertySources:在创建标准化环境对象(StandardEnvironment)时 createEnvironment() 会执行父类【AbstractEnvironment】构造方法加载这两项值【systemProperties:系统属性值,systemEnvironment:系统环境值】
protected void customizePropertySources(MutablePropertySources propertySources) {
propertySources.addLast(new PropertiesPropertySource(SYSTEM_PROPERTIES_PROPERTY_SOURCE_NAME,getSystemProperties()));
propertySources.addLast(new SystemEnvironmentPropertySource(SYSTEM_ENVIRONMENT_PROPERTY_SOURCE_NAME,getSystemEnvironment()));
}
resolveRequiredPlaceholders:解析占位符信息
创建 PropertyPlaceholderHelper 处理类
doResolvePlaceholders 执行解析操作
在其内部递归调用 PropertyPlaceholderHelper#parseStringValue 方法从系统属性和系统环境中解析占用符拿到具体值,递归的原因是因为可能出现这种情况【spring-${username${nickname}}.xml】
容器刷新前的准备工作
protected void prepareRefresh() { // 设置容器启动的时间 this.startupDate = System.currentTimeMillis(); // 容器的关闭标志位 this.closed.set(false); // 容器的激活标志位 this.active.set(true); // 记录日志 if (logger.isDebugEnabled()) { if (logger.isTraceEnabled()) { logger.trace("Refreshing " + this); } else { logger.debug("Refreshing " + getDisplayName()); } } // Initialize any placeholder property sources in the context environment. // 留给子类覆盖扩展,初始化属性资源,钩子函数 initPropertySources(); // Validate that all properties marked as required are resolvable: // see ConfigurablePropertyResolver#setRequiredProperties // 创建并获取环境对象,验证需要的属性文件是否都已经放入环境中,如果没有放入就抛出异常 getEnvironment().validateRequiredProperties(); // Store pre-refresh ApplicationListeners... // 判断刷新前的应用程序监听器集合是否为空,如果为空,则将监听器添加到此集合中 if (this.earlyApplicationListeners == null) { this.earlyApplicationListeners = new LinkedHashSet<>(this.applicationListeners); } else { // Reset local application listeners to pre-refresh state. // 如果不等于空,则清空集合元素对象 this.applicationListeners.clear(); this.applicationListeners.addAll(this.earlyApplicationListeners); } // Allow for the collection of early ApplicationEvents, // to be published once the multicaster is available... // 创建刷新前的监听事件集合 this.earlyApplicationEvents = new LinkedHashSet<>(); }
设置容器的启动时间、设置活跃状态为 true、设置关闭状态为 false、获取 Environment 对象,并加载当前的系统属性值到 Environment 对象中、验证必需的属性是否在环境中存在,如果没有则抛出异常、准备监听器和监听事件的集合对象,默认为空的集合.
该方法流程里面有一个扩展点「初始化属性源交由子类去扩展,可以在其下自定义一些属性,要求其拥有其必须依赖的属性才能正常的运行」
public class MyClassPathXmlApplicationContext extends ClassPathXmlApplicationContext {
public MyClassPathXmlApplicationContext(String... configLocations){
super(configLocations);
}
@Override
protected void initPropertySources() {
System.out.println("扩展initPropertySource");
// 若系统属性中不存在 username,会抛出异常.
getEnvironment().setRequiredProperties("username");
}
}
创建容器对象【DefaultListableBeanFactory】加载 xml 配置文件的属性值到当前工厂中,最重要的就是 BeanDefinition
protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
// 初始化 BeanFactory,并进行 XML 文件读取,并将得到的 BeanFactory 记录在当前实体的属性中
refreshBeanFactory();
// 返回当前实体 beanFactory 属性
return getBeanFactory();
}
AbstractApplicationContext 子类 AbstractRefreshableApplicationContext 继承重写以下方法,XML 启动容器时是该入口来实现
因为 AbstractRefreshableApplicationContext 是 ClassPathXmlApplicationContext 的父类
@Override protected final void refreshBeanFactory() throws BeansException { // 如果存在beanFactory,则销毁beanFactory if (hasBeanFactory()) { destroyBeans(); closeBeanFactory(); } try { // 创建DefaultListableBeanFactory对象 DefaultListableBeanFactory beanFactory = createBeanFactory(); // 为了序列化指定id,可以从id反序列化到beanFactory对象 beanFactory.setSerializationId(getId()); // 定制beanFactory,设置相关属性,包括是否允许覆盖同名称的不同定义的对象以及循环依赖 customizeBeanFactory(beanFactory); // 初始化documentReader,并进行XML文件读取及解析,默认命名空间的解析,自定义标签的解析 loadBeanDefinitions(beanFactory); this.beanFactory = beanFactory; } catch (IOException ex) { throw new ApplicationContextException("I/O error parsing bean definition source for " + getDisplayName(), ex); } }
AbstractApplicationContext 子类 GenericApplicationContext 继承重写以下方法,SpringBoot 是该入口来实现:
protected final void refreshBeanFactory() throws IllegalStateException {
if (!this.refreshed.compareAndSet(false, true)) {
throw new IllegalStateException(
"GenericApplicationContext does not support multiple refresh attempts: just call 'refresh' once");
}
this.beanFactory.setSerializationId(getId());
}
涉及到 Web 容器启动流程中在 createApplicationContext 方法中会根据类型创建一个上下文对象:AnnotationConfigServletWebServerApplicationContext
protected ConfigurableApplicationContext createApplicationContext() { Class<?> contextClass = this.applicationContextClass; if (contextClass == null) { try { switch(this.webApplicationType) { case SERVLET: contextClass = Class.forName("org.springframework.boot.web.servlet.context.AnnotationConfigServletWebServerApplicationContext"); break; case REACTIVE: contextClass = Class.forName("org.springframework.boot.web.reactive.context.AnnotationConfigReactiveWebServerApplicationContext"); break; default: contextClass = Class.forName("org.springframework.context.annotation.AnnotationConfigApplicationContext"); } } catch (ClassNotFoundException var3) { throw new IllegalStateException("Unable create a default ApplicationContext, please specify an ApplicationContextClass", var3); } } return (ConfigurableApplicationContext)BeanUtils.instantiateClass(contextClass); }
再查看它的类关系图就清楚了
接着继续分析 AbstractRefreshableApplicationContext#obtainFreshBeanFactory
方法的处理流程:
public AbstractAutowireCapableBeanFactory() {
super();
// 忽略要依赖的接口
ignoreDependencyInterface(BeanNameAware.class);
ignoreDependencyInterface(BeanFactoryAware.class);
ignoreDependencyInterface(BeanClassLoaderAware.class);
}
// 此方法可以交由子类去自由扩展实现
@Override
protected void customizeBeanFactory(DefaultListableBeanFactory beanFactory) {
super.setAllowBeanDefinitionOverriding(false);
super.setAllowCircularReferences(false);
super.customizeBeanFactory(beanFactory);
}
创建配置文件读取器:XmlBeanDefinitionReader
beanDefinitionReader#setEntityResolver(new ResourceEntityResolver(this))
:设置实体解析器,有 DTD(document type Definition)、XSD(XML Schema Definition) 这两种解析方式,目前大部分使用的是后者
this.dtdResolver = new BeansDtdResolver();
// 当完成这行代码的调用之后,大家神奇的发现一件事情,schemaResolver 对象的 schemaMappings 属性被完成了赋值操作,但是你遍历完成所有代码后依然没有看到显式调用
// 其实此时的原理是非常简单的,我们在进行 debug 的时候,因为在程序运行期间需要显示当前类的所有信息,所以 idea 会帮助我们调用 toString 方法,只不过此过程我们识别不到而已,idea 中可以设置关闭 Debug 模式下 toString 方法调用
// toString(){return "EntityResolver using schema mappings " + getSchemaMappings();}
// 会去加载 META-INF/spring.schemas 文件下所有键值对
this.schemaResolver = new PluggableSchemaResolver(classLoader);
initBeanDefinitionReader(beanDefinitionReader):初始化 beanDefinitionReader 对象,此处设置配置文件是否要进行验证
loadBeanDefinitions(beanDefinitionReader):开始完成对 BeanDefinition 的加载,详细流程图如下:
解析 spring 配置文件整体流程: 这个解析过程是由 documentLoader 完成的,从 String[]—>string—>Resource[]—>resource,最终开始将 resource 转换为 InputStream 流对象后读取成一个 document 文档,新建 BeanDefinitionDocumentReader 对象后对 XML 中 BeanDefinition 进行解析,根据文档的节点信息封装成一个个的 BeanDefinition 对象,将其包装为 BeanDefinitionHolder 对象,并把 BeanDefinition、BeanName、alias 相关信息存入【beanDefinitionMap、beanDefinitionNames】集合中.
BeanDefinitionHolder 介绍:BeanDefinition 对象持有者,封装了 BeanDefinition,bean 名字和别名,用它来完成向 IOC 容器注册,得到这个 BeanDefinitionHolder 意味着 beanDefinition 是通过 BeanDefinitionParserDelegate 对 XML 元素的信息按照 spring bean 规则进行解析得到的
通过子节点来划分整个加载 XML 配置文件的流程:
parseDefaultElement(ele, delegate)
处理,无须去加载文件中的命名空间 handler 类;非默认命名空间,则需要去获取对应的 handler 进行处理import 标签:会获取
resource
属性值,判定其是绝对还是相对的 URI【绝对 URI 直接将 resource 对象直接重新解析的一个流程,相对 URI 则匹配上前缀路径后再走这样的一个流程】
alias:给指定的 BeanName 注册 1~N 个别名,会对所有的
alias->name
关系进行校验,如果不满足就会抛出异常结束「beanName 与 alias 相同不记录 alias、alias 已存在集合中,判定是否允许覆盖:不允许抛出异常、检查别名关系中是否出现嵌套异常,如 A->B 可以但 B->A 就不可以了、将 alias->name 键值对存入集合中」
bean 标签:获取 id、name 属性,id 作为 BeanName,name 作为 alias,如果没有指定 BeanName 名称时,那么 Spring 会根据命名规则为当前 Bean 生成 BeanName 值
checkNameUniqueness(beanName, aliases, ele):会去校验 BeanName 的唯一性,如果存在了会抛出异常
parseBeanDefinitionElement(ele, beanName, containingBean):对 bean 元素进行详细解析
1、根据 class 属性获取全路径类名,反射获取其类实例
2、解析 bean 标签内的属性:depends-on、init-method、destroy-method
3、解析 bean 标签下子标签及其属性:lookup-method【执行新的逻辑需要新加 bean】、replaced-method【将之前方法执行的逻辑替换为新的】、property、构造函数参数
4、property 标签有以下约束:property 标签上不能同时有 value 和 ref 属性、 在有 value 或 ref 属性的同时不能再有子节点、property 标签上 value 和 ref 两个属性都没有也会报错
以上流程处理完调用 BeanDefinitionReaderUtils.registerBeanDefinition(definition, registry)
注册 Bean 信息放入到 【beanDefinitionMap、beanDefinitionNames】 集合中
BeanFactory 准备工作,对 BeanFactory 各种属性进行填充
protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory) { // 设置 beanFactory 的 classloader 为当前 context 的 classloader beanFactory.setBeanClassLoader(getClassLoader()); // 设置 BeanFactory 表达式语言处理器 beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver(beanFactory.getBeanClassLoader())); // 为 beanFactory 增加一个默认的 propertyEditor,这个主要是对 bean 属性等设置管理的一个工具类 beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this, getEnvironment())); // Configure the bean factory with context callbacks. // 添加 beanPostProcessor,ApplicationContextAwareProcessor 此类用来完成某些Aware对象的注入 // postProcessBeforeInitialization 方法执行某些 Aware 对象的属性注入,实例化之后-初始化之前调用 beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this)); // 设置要忽略自动装配的接口,为什么此处要对这些接口进行忽略,原因非常简单,这些接口的实现是由容器通过set 方法进行注入的, // 所以在使用 autowire 进行注入的时候需要将这些接口进行忽略 beanFactory.ignoreDependencyInterface(EnvironmentAware.class); beanFactory.ignoreDependencyInterface(EmbeddedValueResolverAware.class); beanFactory.ignoreDependencyInterface(ResourceLoaderAware.class); beanFactory.ignoreDependencyInterface(ApplicationEventPublisherAware.class); beanFactory.ignoreDependencyInterface(MessageSourceAware.class); beanFactory.ignoreDependencyInterface(ApplicationContextAware.class); // BeanFactory interface not registered as resolvable type in a plain factory. // MessageSource registered (and found for autowiring) as a bean. // 设置几个自动装配的特殊规则,当在进行ioc初始化的如果有多个实现,那么就使用指定的对象进行注入 beanFactory.registerResolvableDependency(BeanFactory.class, beanFactory); beanFactory.registerResolvableDependency(ResourceLoader.class, this); beanFactory.registerResolvableDependency(ApplicationEventPublisher.class, this); beanFactory.registerResolvableDependency(ApplicationContext.class, this); // Register early post-processor for detecting inner beans as ApplicationListeners. // 注册BPP beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(this)); // 增加对AspectJ的支持,在java中织入分为三种方式,分为编译器织入,类加载器织入,运行期织入, // 编译器织入:指在java编译器,采用特殊的编译器,将切面织入到java类中, // 类加载期织入:指通过特殊的类加载器,在类字节码加载到JVM时,织入切面, // 运行期织入:采用cglib和jdk进行切面的织入 // aspectj 提供了两种织入方式, // 第一种是通过特殊编译器,在编译器,将aspectj语言编写的切面类织入到java类中, // 第二种是类加载期织入,就是下面的 load time weaving,此处后续讲 if (beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) { beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory)); // Set a temporary ClassLoader for type matching. beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader())); } // 注册默认的系统环境bean到一级缓存中 if (!beanFactory.containsLocalBean(ENVIRONMENT_BEAN_NAME)) { beanFactory.registerSingleton(ENVIRONMENT_BEAN_NAME, getEnvironment()); } if (!beanFactory.containsLocalBean(SYSTEM_PROPERTIES_BEAN_NAME)) { beanFactory.registerSingleton(SYSTEM_PROPERTIES_BEAN_NAME, getEnvironment().getSystemProperties()); } if (!beanFactory.containsLocalBean(SYSTEM_ENVIRONMENT_BEAN_NAME)) { beanFactory.registerSingleton(SYSTEM_ENVIRONMENT_BEAN_NAME, getEnvironment().getSystemEnvironment()); } }
StandardBeanExpressionResolver
postProcessBeforeInitialization
方法中执行某些 Aware 属性的注入,在实例化之后、执行初始化方法之前进行调用EnvironmentAware、EmbeddedValueResolverAware、ResourceLoaderAware、ApplicationEventPublisherAware、MessageSourceAware、ApplicationContextAware
还有一些 aware 接口是在执行初始化时也就是调用 invokeAwareMethods 方法时【BeanNameAware、BeanClassLoaderAware、BeanFactoryAware】进行注入.
Aware 相关的在 invokeAwareMethods 方法中只会执行 BeanNameAware、BeanClassLoaderAware、BeanFactoryAware,其他定义的 Aware 接口会在 ApplicationContextAwareProcessor.postProcessBeforeInitialization 中执行
扩展 BeanPostProcessor「简称:BPP」,其实就是实现 BPP 接口,在实现的方法编写自己需要扩展的逻辑
public class MyBeanPostProcessor implements BeanPostProcessor { @Override public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException { System.out.println("postProcessBeforeInitialization---MyBeanPostProcessor"); return bean; } @Override public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { System.out.println("postProcessAfterInitialization---MyBeanPostProcessor"); if (bean instanceof Person) { Person person = (Person) bean; person.setName("哈哈哈"); System.out.println("postProcessAfterInitialization#person:" + person.getName()); return person; } else { return bean; } } }
在 SpringMVC 中通过 XML 文件配置使其能够被 Spring 所读取
<bean class="com.mashibing.MyBeanPostProcessor"/>
在 SpringBoot 中通过注解 @Configuration 或 @Import 导入该类型即可.
此方法交由子类去实现做额外的处理,此处我们一般不做任何扩展工作,但是在 Web 中的代码,是由具体的实现的.
protected void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) {
super.postProcessBeanFactory(beanFactory);
// scanner=ClassPathBeanDefinitionScanner
if (this.basePackages != null && this.basePackages.length > 0) {
this.scanner.scan(this.basePackages);
}
// reader=AnnotatedBeanDefinitionReader
if (!this.annotatedClasses.isEmpty()) {
this.reader.register(ClassUtils.toClassArray(this.annotatedClasses));
}
}
AnnotatedBeanDefinitionReader 类作用:直接将指定的某个没有使用 spring 提供的 @Bean 、@Component 等注解的类解析成 BeanDefinition 对象并保存到容器中,如果被解析的类上有 spring 其他注解,也会被解析,保存到 BeanDefinition 以后,后面会经过 Spring Bean 整个生命周期进行 Bean 实例构建.
ClassPathBeanDefinitionScanner 类作用:扫描指定包路径下的 @Component 注解,将有这个注解的类解析成 BeanDefinition 对象并放入容器中
此方法是执行 BeanFactoryPostProcessor「BFPP」 方法的入口,调用各种 BeanFactory 处理器,会在这里面完成属性的 ${}
的解析工作
protected void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory) {
// 获取到当前应用程序上下文的 beanFactoryPostProcessors 集合的值,并且实例化调用执行所有已经注册的 beanFactoryPostProcessor
PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, getBeanFactoryPostProcessors());
// Detect a LoadTimeWeaver and prepare for weaving, if found in the meantime
// (e.g. through an @Bean method registered by ConfigurationClassPostProcessor)
if (beanFactory.getTempClassLoader() == null && beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {
beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));
beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));
}
}
默认情况下,通过 getBeanFactoryPostProcessors 方法来获取已经注册的 BFPP,但是默认是空的,那么问题来了,如果你想扩展,怎么进行扩展工作?
public class MyBeanFactoryPostProcessor implements BeanFactoryPostProcessor {
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
System.out.println("扩展 BeanFactoryPostProcessor");
}
}
<bean class="com.mashibing.MyBeanFactoryPostProcessor"/>
ClassPathXmlApplicationContext ac = new ClassPathXmlApplicationContext("test.xml");
ac.addBeanFactoryPostProcessor(new MyBeanFactoryPostProcessor());
ac.refresh();
将 XML 配置的类去除即可.
实现 BFPP(BeanFactoryPostProcessor)比较重要的有这个类:ConfigurationClassPostProcessor【1、解析加了 @Configuration 的配置类;2、解析 @ComponentScan 扫描的包;3、解析 @ComponentScans 扫描的包;4、解析 @Import 注解】该类是用于 SpringBoot 自动装配过程中的核心类
ConfigurationClassPostProceesor 核心类流程详解:Spring 核心类 ConfigurationClassPostProcessor 流程讲解及源码全面分析
在学习分析该方法核心流程之前,我们先要区分两个类的作用,BeanFactoryPostProcessor 与 BeanDefinitionRegistryPostProcessor 区别
public static void invokeBeanFactoryPostProcessors( ConfigurableListableBeanFactory beanFactory, List<BeanFactoryPostProcessor> beanFactoryPostProcessors) { // 无论是什么情况,优先执行 BeanDefinitionRegistryPostProcessors // 将已经执行过的BFPP存储在 processedBeans 中,防止重复执行 Set<String> processedBeans = new HashSet<>(); // 此处是 DefaultListableBeanFactory,实现了 BeanDefinitionRegistry 接口,所以为 true if (beanFactory instanceof BeanDefinitionRegistry) { // 类型转换 BeanDefinitionRegistry registry = (BeanDefinitionRegistry) beanFactory; // 存放 BeanFactoryPostProcessor 的集合 List<BeanFactoryPostProcessor> regularPostProcessors = new ArrayList<>(); // 存放 BeanDefinitionRegistryPostProcessor 的集合 List<BeanDefinitionRegistryPostProcessor> registryProcessors = new ArrayList<>(); // 首先处理入参中的 beanFactoryPostProcessors,遍历所有的 beanFactoryPostProcessors,将BeanDefinitionRegistryPostProcessor 和 BeanFactoryPostProcessor 区分开 for (BeanFactoryPostProcessor postProcessor : beanFactoryPostProcessors) { // 如果是 BeanDefinitionRegistryPostProcessor if (postProcessor instanceof BeanDefinitionRegistryPostProcessor) { BeanDefinitionRegistryPostProcessor registryProcessor = (BeanDefinitionRegistryPostProcessor) postProcessor; // 直接执行 BeanDefinitionRegistryPostProcessor 接口中的postProcessBeanDefinitionRegistry 方法 registryProcessor.postProcessBeanDefinitionRegistry(registry); // 添加到 registryProcessors,用于后续执行 postProcessBeanFactory 方法 registryProcessors.add(registryProcessor); } else { // 否则,只是普通的BeanFactoryPostProcessor,添加到regularPostProcessors,用于后续执行postProcessBeanFactory方法 regularPostProcessors.add(postProcessor); } } // 用于保存本次要执行的 BeanDefinitionRegistryPostProcessor List<BeanDefinitionRegistryPostProcessor> currentRegistryProcessors = new ArrayList<>(); // 调用所有实现PriorityOrdered接口的BeanDefinitionRegistryPostProcessor实现类 // 找到所有实现BeanDefinitionRegistryPostProcessor接口bean的beanName String[] postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false); // 遍历处理所有符合规则的postProcessorNames for (String ppName : postProcessorNames) { // 检测是否实现了 PriorityOrdered 接口 if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) { // 获取名字对应的bean实例,添加到currentRegistryProcessors中 currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class)); // 将要被执行的BFPP名称添加到processedBeans,避免后续重复执行 processedBeans.add(ppName); } } // 按照优先级进行排序操作 sortPostProcessors(currentRegistryProcessors, beanFactory); // 添加到registryProcessors中,用于最后执行postProcessBeanFactory方法 registryProcessors.addAll(currentRegistryProcessors); // 遍历currentRegistryProcessors,执行postProcessBeanDefinitionRegistry方法 invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry); // 执行完毕之后,清空currentRegistryProcessors currentRegistryProcessors.clear(); // 找到所有实现BeanDefinitionRegistryPostProcessor接口bean的beanName,此处需要重复查找的原因在于上面的执行过程中可能会新增其他的 BeanDefinitionRegistryPostProcessor // 在 MyBeanDefinitionRegistryPostProcessor 类实现新增 postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false); for (String ppName : postProcessorNames) { // 检测是否实现了Ordered接口,并且还未执行过 if (!processedBeans.contains(ppName) && beanFactory.isTypeMatch(ppName, Ordered.class)) { // 获取名字对应的bean实例,添加到currentRegistryProcessors中 currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class)); // 将要被执行的BFPP名称添加到processedBeans,避免后续重复执行 processedBeans.add(ppName); } } // 按照优先级进行排序操作 sortPostProcessors(currentRegistryProcessors, beanFactory); // 添加到registryProcessors中,用于最后执行postProcessBeanFactory方法 registryProcessors.addAll(currentRegistryProcessors); // 遍历currentRegistryProcessors,执行postProcessBeanDefinitionRegistry方法 invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry); // 执行完毕之后,清空currentRegistryProcessors currentRegistryProcessors.clear(); // 最后,调用所有剩下的BeanDefinitionRegistryPostProcessors boolean reiterate = true; while (reiterate) { reiterate = false; // 找出所有实现BeanDefinitionRegistryPostProcessor接口的类 postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false); // 遍历执行 for (String ppName : postProcessorNames) { // 跳过已经执行过的BeanDefinitionRegistryPostProcessor if (!processedBeans.contains(ppName)) { // 获取名字对应的bean实例,添加到currentRegistryProcessors中 currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class)); // 将要被执行的BFPP名称添加到processedBeans,避免后续重复执行 processedBeans.add(ppName); reiterate = true; } } // 按照优先级进行排序操作 sortPostProcessors(currentRegistryProcessors, beanFactory); // 添加到registryProcessors中,用于最后执行postProcessBeanFactory方法 registryProcessors.addAll(currentRegistryProcessors); // 遍历currentRegistryProcessors,执行postProcessBeanDefinitionRegistry方法 invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry); // 执行完毕之后,清空currentRegistryProcessors currentRegistryProcessors.clear(); } // 调用所有BeanDefinitionRegistryPostProcessor的postProcessBeanFactory方法 invokeBeanFactoryPostProcessors(registryProcessors, beanFactory); // 最后,调用入参beanFactoryPostProcessors中的普通BeanFactoryPostProcessor的postProcessBeanFactory方法 invokeBeanFactoryPostProcessors(regularPostProcessors, beanFactory); } else { // Invoke factory processors registered with the context instance. // 如果beanFactory不归属于BeanDefinitionRegistry类型,那么直接执行postProcessBeanFactory方法 invokeBeanFactoryPostProcessors(beanFactoryPostProcessors, beanFactory); } // 到这里为止,入参 beanFactoryPostProcessors 和容器中的所有BeanDefinitionRegistryPostProcessor 已经全部处理完毕,下面开始处理容器中所有的 BeanFactoryPostProcessor // 可能会包含一些实现类,只实现了 BeanFactoryPostProcessor,并没有实现 BeanDefinitionRegistryPostProcessor 接口 // 找到所有实现BeanFactoryPostProcessor接口的类 // 自身 new 出来的 BFPP 无法匹配到,只会匹配到交由 Bean 容器管理的对象 String[] postProcessorNames = beanFactory.getBeanNamesForType(BeanFactoryPostProcessor.class, true, false); // 用于存放实现了PriorityOrdered接口的BeanFactoryPostProcessor List<BeanFactoryPostProcessor> priorityOrderedPostProcessors = new ArrayList<>(); // 用于存放实现了Ordered接口的BeanFactoryPostProcessor的beanName // List<String> orderedPostProcessorNames = new ArrayList<>(); List<BeanFactoryPostProcessor> orderedPostProcessor = new ArrayList<>(); // 用于存放普通BeanFactoryPostProcessor的beanName // List<String> nonOrderedPostProcessorNames = new ArrayList<>(); List<BeanFactoryPostProcessor> nonOrderedPostProcessorNames = new ArrayList<>(); // 遍历 postProcessorNames,将 BeanFactoryPostProcessor 按实现 PriorityOrdered、实现Ordered 接口、普通三种区分开 for (String ppName : postProcessorNames) { // 跳过已经执行过的BeanFactoryPostProcessor if (processedBeans.contains(ppName)) { // skip - already processed in first phase above } // 添加实现了PriorityOrdered接口的BeanFactoryPostProcessor到priorityOrderedPostProcessors else if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) { priorityOrderedPostProcessors.add(beanFactory.getBean(ppName, BeanFactoryPostProcessor.class)); } // 添加实现了Ordered接口的BeanFactoryPostProcessor的beanName到orderedPostProcessorNames else if (beanFactory.isTypeMatch(ppName, Ordered.class)) { // orderedPostProcessorNames.add(ppName); orderedPostProcessor.add(beanFactory.getBean(ppName, BeanFactoryPostProcessor.class)); } else { // 添加剩下的普通BeanFactoryPostProcessor的beanName到nonOrderedPostProcessorNames // nonOrderedPostProcessorNames.add(ppName); nonOrderedPostProcessorNames.add(beanFactory.getBean(ppName, BeanFactoryPostProcessor.class)); } } // 对实现了PriorityOrdered接口的BeanFactoryPostProcessor进行排序 sortPostProcessors(priorityOrderedPostProcessors, beanFactory); // 遍历实现了 PriorityOrdered 接口的 BeanFactoryPostProcessor,执行 postProcessBeanFactory 方法 invokeBeanFactoryPostProcessors(priorityOrderedPostProcessors, beanFactory); // 创建存放实现了Ordered接口的BeanFactoryPostProcessor集合 // List<BeanFactoryPostProcessor> orderedPostProcessors = new ArrayList<>(orderedPostProcessorNames.size()); // 遍历存放实现了Ordered接口的BeanFactoryPostProcessor名字的集合 // for (String postProcessorName : orderedPostProcessorNames) { // 将实现了Ordered接口的BeanFactoryPostProcessor添加到集合中 // orderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class)); // } // 对实现了Ordered接口的BeanFactoryPostProcessor进行排序操作 sortPostProcessors(orderedPostProcessor, beanFactory); // 遍历实现了Ordered接口的BeanFactoryPostProcessor,执行postProcessBeanFactory方法 // invokeBeanFactoryPostProcessors(orderedPostProcessors, beanFactory); invokeBeanFactoryPostProcessors(orderedPostProcessor, beanFactory); // Finally, invoke all other BeanFactoryPostProcessors. // 最后,创建存放普通的BeanFactoryPostProcessor的集合 // List<BeanFactoryPostProcessor> nonOrderedPostProcessors = new ArrayList<>(nonOrderedPostProcessorNames.size()); // 遍历存放实现了普通BeanFactoryPostProcessor名字的集合 // for (String postProcessorName : nonOrderedPostProcessorNames) { // 将普通的BeanFactoryPostProcessor添加到集合中 // nonOrderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class)); // } // 遍历普通的BeanFactoryPostProcessor,执行postProcessBeanFactory方法 // invokeBeanFactoryPostProcessors(nonOrderedPostProcessors, beanFactory); invokeBeanFactoryPostProcessors(nonOrderedPostProcessorNames, beanFactory); // 清除元数据缓存(mergeBeanDefinitions、allBeanNamesByType、singletonBeanNameByType) // 因为后置处理器可能已经修改了原始元数据,例如,替换值中的占位符 beanFactory.clearMetadataCache(); }
源码中 PriorityOrdered、Ordered、nonOrdered 的 BFPP 对象,都分别用不同的循环进行遍历 getBean,此处调整了源码,将这三种类型的对象放在一个循环里面进行处理,增加多重 if 判别存入到不同的集合中
以下对源码中的流程进行流程图的解析,以及详细的文档说明
创建一个空的集合,用来存储已经执行过的 BFPP 或 BDRPP
判断当前 BeanFactory 是否是 BeanDefinitionRegistry 类型,此处是 DefaultListableBeanFactory,实现了 BeanDefinitionRegistry 接口,所以为 true
创建两个集合用于存放不同的接口,分别是存储 BFPP(BeanFactoryPostProcessor)接口的 regularPostProcessors,另外一个是 存储 BDRPP(BeanDefinitionRegistryPostProcessor)接口的 registryProcessors;存储到这两个集合中的类只是为了方便执行 BFPP 下的 postProcessBeanFactory 方法
先处理用户自定义的 BFPP 集合,遍历每一个元素,先判定其是否为 BDRPP 类型:如果是就执行 postProcessBeanDefinitionRegistry 方法并将其添加进 registryProcessors 集合中;如果不是就将其添加进 regularPostProcessors 即可
单独创建一个集合对象,用于存放当前需要执行的 BDRPP 对象:currentRegistryProcessors
获取当前容器中实现了 BDRPP 接口的 beanName
1、判定是否存在实现了 PriorityOrdered
接口的 beanName:如果有就通过 beanName 进行 getBean 操作【getBean->doGetBean->createBean->doCreateBean】,将其添加进 currentRegistryProcessors 集合中,再添加到 processedBeans 集合中【避免后续重复执行】
2、判断是否存在实现了 Ordered
接口的 beanName:如果有就通过 beanName 进行 getBean 操作【getBean->doGetBean->createBean->doCreateBean】,将其添加进 currentRegistryProcessors 集合中,再添加到 processedBeans 集合中【避免后续重复执行】
3、找出剩下所有实现 BDRPP 接口的类,直至所有的方法所被找到并且执行完毕
4、1-2-3 步骤取出对应的接口出来以后,都要经过如下的流程去处理
5、调用所有 BeanDefinitionRegistryPostProcessor#postProcessBeanFactory 方法
6、最后,调用入参 beanFactoryPostProcessors 中的普通 BeanFactoryPostProcessor#postProcessBeanFactory 方法
7、到这里为止,入参中所有的 BFPP 和容器中所有的 BDRPP 都已经全部处理完毕
以下的流程是处理容器中的 BFPP 接口
处理容器中的 BFPP【自身 new 出来的入参时会携带进来,下面的都是被容器所管理的 BFPP】
PriorityOrdered
接口的 beanName,如果是将其放入 priorityOrderedPostProcessors 集合中Ordered
接口的 beanName,如果是将其放入 Ordered 对应的集合中实现 BDRPP 接口的类可以调用 registry.registerBeanDefinition
来新增 BeanDefinition 信息,配置它的同时新增的类也可以被 Spring 被所识别
// 该类需要在 XML 配置,使其能够让 Spring 识别 public class MyBeanDefinitionRegistryPostProcessor implements BeanDefinitionRegistryPostProcessor, PriorityOrdered { @Override public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException { System.out.println("执行postProcessBeanDefinitionRegistry---MyBeanDefinitionRegistryPostProcessor"); // 引入了一个新的 BDRPP 实现类 BeanDefinitionBuilder builder = BeanDefinitionBuilder.rootBeanDefinition(MySelfBeanDefinitionRegistryPostProcessor.class); builder.addPropertyValue("name","zhangsan"); registry.registerBeanDefinition("vnjohn",builder.getBeanDefinition()); } @Override public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException { System.out.println("执行postProcessBeanFåactory---MyBeanDefinitionRegistryPostProcessor"); BeanDefinition msb = beanFactory.getBeanDefinition("vnjohn"); msb.getPropertyValues().getPropertyValue("name").setConvertedValue("lisi"); System.out.println("==============="); } @Override public int getOrder() { return 0; } }
// 该类不需要进行配置,会在循环查找 BDRPP 时被找到 public class MySelfBeanDefinitionRegistryPostProcessor implements BeanDefinitionRegistryPostProcessor, PriorityOrdered { private String name; public String getName() { return name; } public void setName(String name) { this.name = name; } @Override public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException { System.out.println("调用执行postProcessBeanDefinitionRegistry--MySelfBeanDefinitionRegistryPostProcessor"); // 这里可以继续进行扩展新增 BDRPP 实现类 // BeanDefinitionBuilder builder = BeanDefinitionBuilder.rootBeanDefinition(MySelfTwoBeanDefinitionRegistryPostProcessor.class); // builder.addPropertyValue("nickName","vnjohn"); // registry.registerBeanDefinition("mySelfTwo",builder.getBeanDefinition()); } @Override public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException { System.out.println("调用执行postProcessBeanFactory--MySelfBeanDefinitionRegistryPostProcessor"); } @Override public int getOrder() { return 0; } }
<bean class="com.mashibing.selfbdrpp.MyBeanDefinitionRegistryPostProcessor"/>
由于 refresh 涉及到了 13 个方法,在一篇文章里进行分解内容会过长,分为两个章节,剩下的 registerBeanPostProcessors、initMessageSource、initApplicationEventMulticaster、onRefresh、registerListeners、finishBeanFactoryInitialization、finishRefresh 方法在章节二进行剖析
记录个人在学习 Spring 源码时整理出来的详细笔记,整理文章不易,喜欢的可以点个关注和赞
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。