• Spring IOC源码:实例化前的准备工作


    Spring源码系列:

    Spring IOC源码:简单易懂的Spring IOC 思路介绍
    Spring IOC源码:核心流程介绍
    Spring IOC源码:ApplicationContext刷新前准备工作
    Spring IOC源码:obtainFreshBeanFactory 详解(上)
    Spring IOC源码:obtainFreshBeanFactory 详解(中)
    Spring IOC源码:obtainFreshBeanFactory 详解(下)
    Spring IOC源码:<context:component-scan>源码详解
    Spring IOC源码:invokeBeanFactoryPostProcessors 后置处理器详解
    Spring IOC源码:registerBeanPostProcessors 详解
    Spring IOC源码:实例化前的准备工作
    Spring IOC源码:finishBeanFactoryInitialization详解
    Spring IoC源码:getBean 详解
    Spring IoC源码:createBean( 上)
    Spring IoC源码:createBean( 中)
    Spring IoC源码:createBean( 下)
    Spring IoC源码:finishRefresh 完成刷新详解

    前言

    上篇文章我们讲解了IOC比较重要的后置处理器注册方法,本篇文章讲解实例化前的准备工作,包括国际化、多播器创建、监听器注册等节点。

    正文

    进入refresh方法中,可以看到在正式实例化初始化方法前,还有4个方法:
    1、initMessageSource();
    这个方法主要作用就是使用国际化,定制不同的消息文本,比如定义了一个Person的Bean,它有name属性,我们需要在不同的国家展示对应国家所在语言名称,这时候就可以使用国际化了。

    2、initApplicationEventMulticaster();
    初始化应用事件广播器。这是观察者模式得典型应用。我们知道观察者模式由主题Subject和Observer组成。广播器相当于主题Subject,其包含多个监听器。当主题发生变化时会通知所有的监听器。

    3、onRefresh();
    onRefresh 是一个为使用者进行扩展的方法,如:springboot。

    4、registerListeners();
    将内部的、以及我们自定义的监听器添加到缓存中,以及添加事件源到缓存中,为后续逻辑处理做准备。

    方法1:initMessageSource

    ConfigurableListableBeanFactory beanFactory = getBeanFactory();
    		//判断工厂中是否存在MessageSource类型的定义信息
    		if (beanFactory.containsLocalBean(MESSAGE_SOURCE_BEAN_NAME)) {
    			//实例化
    			this.messageSource = beanFactory.getBean(MESSAGE_SOURCE_BEAN_NAME, MessageSource.class);
    			// 设置父类消息解析对象
    			if (this.parent != null && this.messageSource instanceof HierarchicalMessageSource) {
    				HierarchicalMessageSource hms = (HierarchicalMessageSource) this.messageSource;
    				if (hms.getParentMessageSource() == null) {
    					// Only set parent context as parent MessageSource if no parent MessageSource
    					// registered already.
    					hms.setParentMessageSource(getInternalParentMessageSource());
    				}
    			}
    			if (logger.isTraceEnabled()) {
    				logger.trace("Using MessageSource [" + this.messageSource + "]");
    			}
    		}
    		else {
    			// 实例化一个空的DelegatingMessageSource 对象
    			DelegatingMessageSource dms = new DelegatingMessageSource();
    			//设置父类消息解析对象
    			dms.setParentMessageSource(getInternalParentMessageSource());
    			this.messageSource = dms;
    			//注册添加到一级缓存中
    			beanFactory.registerSingleton(MESSAGE_SOURCE_BEAN_NAME, this.messageSource);
    			if (logger.isTraceEnabled()) {
    				logger.trace("No '" + MESSAGE_SOURCE_BEAN_NAME + "' bean, using [" + this.messageSource + "]");
    			}
    		}
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30

    方法2:initApplicationEventMulticaster

    protected void initApplicationEventMulticaster() {
    		//获取工厂对象
    		ConfigurableListableBeanFactory beanFactory = getBeanFactory();
    		//判断工厂中是否有ApplicationEventMulticaster的定义信息
    		if (beanFactory.containsLocalBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME)) {
    		//实例化,为后续实例化环节做准备
    			this.applicationEventMulticaster =
    					beanFactory.getBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, ApplicationEventMulticaster.class);
    			if (logger.isTraceEnabled()) {
    				logger.trace("Using ApplicationEventMulticaster [" + this.applicationEventMulticaster + "]");
    			}
    		}
    		else {
    			//创建一个多播器
    			this.applicationEventMulticaster = new SimpleApplicationEventMulticaster(beanFactory);
    			//添加到一级缓存中
    			beanFactory.registerSingleton(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, this.applicationEventMulticaster);
    			if (logger.isTraceEnabled()) {
    				logger.trace("No '" + APPLICATION_EVENT_MULTICASTER_BEAN_NAME + "' bean, using " +
    						"[" + this.applicationEventMulticaster.getClass().getSimpleName() + "]");
    			}
    		}
    	}
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23

    方法3:onRefresh

    	protected void onRefresh() throws BeansException {
    		
    	}
    
    • 1
    • 2
    • 3

    该方法为拓展接口,供子类实现。

    方法4:registerListeners

    	protected void registerListeners() {
    		// 将上下文中的监听器集合注册到多播器集合中
    		for (ApplicationListener<?> listener : getApplicationListeners()) {
    			getApplicationEventMulticaster().addApplicationListener(listener);
    		}
    
    		// Do not initialize FactoryBeans here: We need to leave all regular beans
    		// uninitialized to let post-processors apply to them!
    		String[] listenerBeanNames = getBeanNamesForType(ApplicationListener.class, true, false);
    		for (String listenerBeanName : listenerBeanNames) {
    			getApplicationEventMulticaster().addApplicationListenerBean(listenerBeanName);
    		}
    
    		// Publish early application events now that we finally have a multicaster...
    		Set<ApplicationEvent> earlyEventsToProcess = this.earlyApplicationEvents;
    		this.earlyApplicationEvents = null;
    		if (earlyEventsToProcess != null) {
    			for (ApplicationEvent earlyEvent : earlyEventsToProcess) {
    				getApplicationEventMulticaster().multicastEvent(earlyEvent);
    			}
    		}
    	}
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22

    自定义监听器以及事件源:

    事件源:

    package service.event;
    
    import org.springframework.context.ApplicationEvent;
    
    public class MyEvent extends ApplicationEvent  {
    	private static final long serialVersionUID = 2611556444074013268L;
    	/**
    	 * Create a new {@code ApplicationEvent}.
    	 *
    	 * @param source the object on which the event initially occurred or with
    	 *               which the event is associated (never {@code null})
    	 */
    	public MyEvent(Object source) {
    		super(source);
    	}
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    监听器:

    package service.event;
    
    import org.springframework.context.ApplicationEvent;
    import org.springframework.context.ApplicationListener;
    
    public class MyListener1 implements ApplicationListener<MyEvent> {
    
    	@Override
    	public void onApplicationEvent(MyEvent event) {
    		System.out.println("MyListener"+event.toString());
    	}
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    package service.event;
    
    import org.springframework.context.ApplicationEvent;
    import org.springframework.context.ApplicationListener;
    
    public class MyListener2 implements ApplicationListener<MyEvent> {
    
    	@Override
    	public void onApplicationEvent(MyEvent event) {
    		System.out.println("MyListener"+event.toString());
    	}
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    xml文件配置监听器:

    	<bean class="service.event.MyListener1" name="myListener1">bean>
    	<bean class="service.event.MyListener2" name="myListener2">bean>
    
    • 1
    • 2

    入口编写:

    	public static void main(String[] args) {
    		MyClassPathApplicationContext applicationContext=new MyClassPathApplicationContext("application-scan.xml");
    		applicationContext.publishEvent(new MyEvent("猪大肠事件"));
    	}
    
    • 1
    • 2
    • 3
    • 4

    运行结果:
    在这里插入图片描述

    总结

    这篇文章内容比较简单,主要是实例化前的准备工作。国际化定制消息类型,初始化多播器,注册监听器,提交发布早期事件。

  • 相关阅读:
    POSIX信号量
    联想y7000p怎么开启高性能模式?
    React+fetch 发送post请求 处理请求头参数配置
    如何利用ChatGPT搞科研?论文检索、写作、基金润色、数据分析、科研绘图(全球地图、植被图、箱型图、雷达图、玫瑰图、气泡图、森林图等)
    Day68:49. 字母异位词分组、128. 最长连续序列
    【2023云栖】黄博远:阿里云人工智能平台PAI年度发布
    【深度学习】不同虚拟环境安装不同Pytorch版本
    Java自定义类加载器的详解与步骤
    Linux 报错:failed to run command ‘java’: No such file or directory
    Linux shell编程学习笔记4:修改命令行提示符格式(内容和颜色)
  • 原文地址:https://blog.csdn.net/weixin_45031612/article/details/127971203