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

简介: 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 + "]");
      }
    }

方法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() + "]");
      }
    }
  }

方法3:onRefresh

  protected void onRefresh() throws BeansException {
  }

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

方法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);
      }
    }
  }

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

事件源:

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);
  }
}

监听器:

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());
  }
}
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());
  }
}

xml文件配置监听器:

  <bean class="service.event.MyListener1" name="myListener1"></bean>
  <bean class="service.event.MyListener2" name="myListener2"></bean>

入口编写:

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

运行结果:

总结

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

目录
相关文章
|
10天前
|
缓存 Java 开发工具
Spring是如何解决循环依赖的?从底层源码入手,详细解读Spring框架的三级缓存
三级缓存是Spring框架里,一个经典的技术点,它很好地解决了循环依赖的问题,也是很多面试中会被问到的问题,本文从源码入手,详细剖析Spring三级缓存的来龙去脉。
Spring是如何解决循环依赖的?从底层源码入手,详细解读Spring框架的三级缓存
|
10天前
|
XML 缓存 Java
手写Spring源码(简化版)
Spring包下的类、手写@ComponentScan注解、@Component注解、@Autowired注解、@Scope注解、手写BeanDefinition、BeanNameAware、InitializingBean、BeanPostProcessor 、手写AnnotationConfigApplicationContext
手写Spring源码(简化版)
|
10天前
|
缓存 安全 Java
Spring框架中Bean是如何加载的?从底层源码入手,详细解读Bean的创建流程
从底层源码入手,通过代码示例,追踪AnnotationConfigApplicationContext加载配置类、启动Spring容器的整个流程,并对IOC、BeanDefinition、PostProcesser等相关概念进行解释
Spring框架中Bean是如何加载的?从底层源码入手,详细解读Bean的创建流程
|
10天前
|
XML Java 数据格式
Spring IOC—基于XML配置Bean的更多内容和细节(通俗易懂)
Spring 第二节内容补充 关于Bean配置的更多内容和细节 万字详解!
70 18
Spring IOC—基于XML配置Bean的更多内容和细节(通俗易懂)
|
11天前
|
Java 数据库连接 数据格式
【Java笔记+踩坑】Spring基础2——IOC,DI注解开发、整合Mybatis,Junit
IOC/DI配置管理DruidDataSource和properties、核心容器的创建、获取bean的方式、spring注解开发、注解开发管理第三方bean、Spring整合Mybatis和Junit
【Java笔记+踩坑】Spring基础2——IOC,DI注解开发、整合Mybatis,Junit
|
1月前
|
缓存 Java Maven
Java本地高性能缓存实践问题之SpringBoot中引入Caffeine作为缓存库的问题如何解决
Java本地高性能缓存实践问题之SpringBoot中引入Caffeine作为缓存库的问题如何解决
|
2月前
|
Java 测试技术 数据库
Spring Boot中的项目属性配置
本节课主要讲解了 Spring Boot 中如何在业务代码中读取相关配置,包括单一配置和多个配置项,在微服务中,这种情况非常常见,往往会有很多其他微服务需要调用,所以封装一个配置类来接收这些配置是个很好的处理方式。除此之外,例如数据库相关的连接参数等等,也可以放到一个配置类中,其他遇到类似的场景,都可以这么处理。最后介绍了开发环境和生产环境配置的快速切换方式,省去了项目部署时,诸多配置信息的修改。
|
2月前
|
Java 应用服务中间件 开发者
Java面试题:解释Spring Boot的优势及其自动配置原理
Java面试题:解释Spring Boot的优势及其自动配置原理
99 0
|
5天前
|
Java 应用服务中间件 开发者
深入探索并实践Spring Boot框架
深入探索并实践Spring Boot框架
20 2
|
26天前
|
缓存 Java 数据库连接
Spring Boot 资源文件属性配置,紧跟技术热点,为你的应用注入灵动活力!
【8月更文挑战第29天】在Spring Boot开发中,资源文件属性配置至关重要,它让开发者能灵活定制应用行为而不改动代码,极大提升了可维护性和扩展性。Spring Boot支持多种配置文件类型,如`application.properties`和`application.yml`,分别位于项目的resources目录下。`.properties`文件采用键值对形式,而`yml`文件则具有更清晰的层次结构,适合复杂配置。此外,Spring Boot还支持占位符引用和其他外部来源的属性值,便于不同环境下覆盖默认配置。通过合理配置,应用能快速适应各种环境与需求变化。
31 0