IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> Java知识库 -> Spring源码学习--06(打通Refresh方法的全链路) -> 正文阅读

[Java知识库]Spring源码学习--06(打通Refresh方法的全链路)

目录

1.后置处理器PostProcessor

2.Aware及其子接口

?3.事件监听器模式?

4.Spring容器 的刷新逻辑


1.后置处理器PostProcessor

? ? 后置处理器有三种

? ? ? BeanDefinitionRegistryPostProcessor: BeanDefinitionRegistry的后置处理器

? ? ??BeanFactoryPostProcessor :Bean 工厂后置处理器

? ? ??BeanPostProcessor :Bean 后置处理器

? 前两个是容器级别的后置处理器,最后一个属于Bean级别的后置处理器。BeanDefinitionRegistryPostProcessor在?Bean?实例化和BeanFactoryPostProcessor 检测开始之前,注册更多的BeanDefinition,除此之外,你还可以修改已注册的?BeanDefinition?信息。在注解的方式启动容器的时候,不管是从参数里面传进来的BeanDefinitionRegistryPostProcessor还是从容器里面获取到已经注册的BeanDefinitionRegistryPostProcessor,都会先于BeanFactoryPostProcessor去执行。用途呢可以在里面去搜索某些第三方的项目里面的Class,然后通过这种方式注入进容器,就可以在容器里面去使用他们了。

@Configuration
public class WXBeanDefinitionRegistryPostProcessor implements BeanDefinitionRegistryPostProcessor {

	@Override
	public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
		Class<User> userClass = User.class;
		BeanDefinitionBuilder beanDefinitionBuilder = BeanDefinitionBuilder.genericBeanDefinition(userClass);
		GenericBeanDefinition genericBeanDefinition = (GenericBeanDefinition) beanDefinitionBuilder.getRawBeanDefinition();
		registry.registerBeanDefinition("user", genericBeanDefinition);
	}

	@Override
	public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {

	}
}

BeanPostProcessor?是?Bean?后置处理器接口,里面包含两个方法:postProcessBeforeInitialization?和?postProcessAfterInitialization。前者在?Bean?实例化(不是BeanDefination实例化)前调用,后者则是在实例化后。比如生成一个?Bean?的代理类,就是其子类做的。

2.Aware及其子接口

?容器对bean的逻辑本身是无侵入的,因此Bean一般不需要了解容器的状态,但是在某些情况下在bean中需要对容器进行直接的操作。这个时候就需要在bean中设定对容器的感知,这便是Aware接口的作用。

Aware是一个空的接口,能发挥作用的是它的一些实现

例如ApplicationContextAware,在容器创建这个bean的时候将容器本身作为参数传入,获取容器相关的信息

?BeanFactoryAware,在容器创建这个bean的时候将BeanFactory本身作为参数传入,获取BeanFactory相关的信息

?使用他就是直接实现他的接口即可

?3.事件监听器模式?

? ? 什么是回调函数?简单来说就是调用一个组件的时候,按照组件的定义注册一个我们自己的方法,期待组件在特定的场景下去调用我们注册的方法。

? 事件源(Evnet Source)

? 事件监听器(Event Listener)事件监听器需要注册到事件源里面

? 事件对象(Event Object) 作为事件源与监听器之间得消息传递

Spring里面的事件驱动模型之容器事件

1.事件ApplicationEvent

?ContextStoppedEvent:容器停止后出发的事件

?ContextRefreshedEvent:容器初始化或者刷新完成后出发的事件

?ContextClosedEvent:容器关闭后触发的事件

?ContextStartedEvent:容器启动后触发的事件

在Spring4.2之前所有的事件都必须强制继承自ApplicationEvent,在4.2以后Spring提供了一个PayloadApplicationEvent的包装类,就不再强制事件必须继承自ApplicationEvent

?

2.事件监听器ApplicationListener

?SmartApplicationListener可以对监听器进行排序

想要实现事件监听器就需要实现ApplicationListener,或者使用@EventListener,就可以将这个Bean晋升为监听器,使用sayHello方法进行监听,返回值是任意的,如果返回值不是Void,此时的返回值会被当做一个新的事件再次进行发布。

?

3.事件发布器ApplicationEventPublisher和ApplicationEventMulticaster

? ApplicationContext继承了ApplicationEventPublisher,说明ApplicationContext具有事件发布的能力,同时还存在与ApplicationEventPublisher相关的Aware接口ApplicationEventPublisherAware

?这个Aware接口上面说过是让Bean可以感知到容器的存在,我们可以在Bean里面通过Aware来获取到ApplicationEventPublisher这个实例(ApplicationContext),然后就可以向容器里面发布自定义的事件,给容器里面注册的自定义的EvnetListener去处理。

ApplicationEventMulticaster:不仅仅具有发布事件的能理,还有添加和删除事件的方法。

?SimpleApplicationEventMulticaster里面如果设置了Executor,就支持多线程去发布事件

为什么有两个事件发布的接口?为什么不使用SimpleApplicationEventMulticaster来替换掉ApplicationEventPublisher?

因为想Bean和容器他们就只想发布事件,并不想维护事件,所以Spring对事件源进行了进一步的切割

4.Spring容器 的刷新逻辑

public void refresh() throws BeansException, IllegalStateException {
		synchronized (this.startupShutdownMonitor) {
			StartupStep contextRefresh = this.applicationStartup.start("spring.context.refresh");

			// 刷新容器前的准备工作
			prepareRefresh();
			// 对于XML来讲特别重要,涉及到BeanDefinition的注册,对于注册来讲仅仅是调用了子类的refreshBeanFactory
			//获取到DefaultListableBeanFactory的实例
			ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

			// 为容器注册必要的系统级别的Bean,例如classLoader beanFactoryPostProcessor
			prepareBeanFactory(beanFactory);

			try {
				// Allows post-processing of the bean factory in context subclasses.
				//允许容器的子类去注册postProcessor
				postProcessBeanFactory(beanFactory);

				StartupStep beanPostProcess = this.applicationStartup.start("spring.context.beans.post-process");
				// Invoke factory processors registered as beans in the context.
				//执行容器级别的后置处理器
				invokeBeanFactoryPostProcessors(beanFactory);

				// Register bean processors that intercept bean creation.
				//向容器注册Bean级别的后置处理器
				registerBeanPostProcessors(beanFactory);
				beanPostProcess.end();

				// Initialize message source for this context.
				//初始化国际化配置
				initMessageSource();

				// Initialize event multicaster for this context.
				//初始化事件发布者组件
				initApplicationEventMulticaster();

				// Initialize other special beans in specific context subclasses.
				// 单例Bean初始化之前,预留给子类初始化预留给子类初始化其他特殊bean的口子
				onRefresh();

				// Check for listener beans and register them.
				//向前面时间发布者组件注册监听器
				registerListeners();

				// Instantiate all remaining (non-lazy-init) singletons.
				//设置一些系统级别的服务,实例化所有非懒加载的单例
				finishBeanFactoryInitialization(beanFactory);

				// Last step: publish corresponding event.
				//触发初始化完成的回调方法,并发布容器刷新完成的事件给监听者
				finishRefresh();
			}

			catch (BeansException ex) {
				if (logger.isWarnEnabled()) {
					logger.warn("Exception encountered during context initialization - " +
							"cancelling refresh attempt: " + ex);
				}

				// Destroy already created singletons to avoid dangling resources.
				destroyBeans();

				// Reset 'active' flag.
				cancelRefresh(ex);

				// Propagate exception to caller.
				throw ex;
			}

			finally {
				// Reset common introspection caches in Spring's core, since we
				// might not ever need metadata for singleton beans anymore...
				//重置Spring中的内核共用缓存
				resetCommonCaches();
				contextRefresh.end();
			}
		}
	}

?

?

  Java知识库 最新文章
计算距离春节还有多长时间
系统开发系列 之WebService(spring框架+ma
springBoot+Cache(自定义有效时间配置)
SpringBoot整合mybatis实现增删改查、分页查
spring教程
SpringBoot+Vue实现美食交流网站的设计与实
虚拟机内存结构以及虚拟机中销毁和新建对象
SpringMVC---原理
小李同学: Java如何按多个字段分组
打印票据--java
上一篇文章      下一篇文章      查看所有文章
加:2021-12-15 18:08:21  更:2021-12-15 18:09:59 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/24 5:29:20-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码