Spring源码分析-IOC源码分析(一)

436 阅读3分钟

这是我参与8月更文挑战的第23天,活动详情查看:8月更文挑战

前言

前面两篇文章介绍了一下Spring IOC的概念和一些核心组件,这两天又重新看了下《Spring源码深度解析》,《Spring实战》和《Spring揭秘》三本书,说到Spring大家可能很熟悉,作为后端研发基本都是用的Spring框架。说到Spring源码我们一般都想到什么呢?IOC, Spring bean生命周期,aop, Spring 生命周期中各种扩展点。Spring使用门槛不高,但是入门的门槛是极高的,不了解源码,面对各种中间件,开源代码里面的问题就很难入手了。

对于源码不太了解的新手建议可以看看《Spring揭秘》这本书。

image.png

Spring的IoC容器在实现控制反转和依赖注入的过程中,可以划分为两个阶段,

  • 容器启动阶段
  • Bean实例化阶段

Spring 源码分析系列

1. 容器启动过程分析

例子

// 定义接口
public interface MessageService {
   
   String send();
}

// 定义实现类
public class MessageServiceImpl implements MessageService {
   @Override
   public String send() {
      return "say hi";
   }
}

定义MessageBean.xml文件

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">

   <bean id="messageService" class="com.br.spring.demo.impl.MessageServiceImpl"/>
</beans>

APP应用

public class App {

   public static void main(String[] args) {
      ApplicationContext context = new ClassPathXmlApplicationContext("classpath:MessageBean.xml");

      System.out.println("context start success");

      // 从 context 中取出我们的 Bean,控制反转将创建对象操作交给Spring 不需要自己在new对象
      MessageService messageService = context.getBean(MessageService.class);
      // 这句将输出: say hi
      System.out.println(messageService.send());

   }
}

输出结果

image.png

1.1 入口ClassPathXmlApplicationContext构造函数

public ClassPathXmlApplicationContext(
      String[] configLocations, boolean refresh, @Nullable ApplicationContext parent)
      throws BeansException {

   super(parent);
   // 根据提供的路径,处理成配置文件
   setConfigLocations(configLocations);
   if (refresh) {
      // 核心方法
      refresh();
   }
}

1.2 获取资源加载器 (AbstractApplicationContext)

public abstract class AbstractApplicationContext extends DefaultResourceLoader
      implements ConfigurableApplicationContext {
      
    static {
       // Eagerly load the ContextClosedEvent class to avoid weird classloader issues
       // on application shutdown in WebLogic 8.1. (Reported by Dustin Woods.)
       ContextClosedEvent.class.getName();
    }

    public AbstractApplicationContext(@Nullable ApplicationContext parent) {
       this();
       setParent(parent);
    }

    public AbstractApplicationContext() {
       // 获取一个Spring reource的加载器
       this.resourcePatternResolver = getResourcePatternResolver();
    } 
     // ....
}

Spring资源加载器 AbstractApplicationContext#getResourcePatternResolver

protected ResourcePatternResolver getResourcePatternResolver() {
   return new PathMatchingResourcePatternResolver(this);
}

public PathMatchingResourcePatternResolver(ResourceLoader resourceLoader) {
   Assert.notNull(resourceLoader, "ResourceLoader must not be null");
   this.resourceLoader = resourceLoader;
}

1.3 解析配置路径 AbstractRefreshableConfigApplicationContext

获取到资源加载器后, 再调用父类 AbstractRefreshableConfigApplicationContext 的 setConfigLocations() 方法设定位配置文件的路径信息。

// 处理单个资源文件
public void setConfigLocation(String location) {
   setConfigLocations(StringUtils.tokenizeToStringArray(location, CONFIG_LOCATION_DELIMITERS));
}

// 处理多个资源文件
public void setConfigLocations(@Nullable String... locations) {
   if (locations != null) {
      Assert.noNullElements(locations, "Config locations must not be null");
      this.configLocations = new String[locations.length];
      for (int i = 0; i < locations.length; i++) {
         this.configLocations[i] = resolvePath(locations[i]).trim();
      }
   }
   else {
      this.configLocations = null;
   }
}

1.4 开始启动流程 AbstractApplicationContext#refresh()

Spring IOC容器对bean的装载是从refresh方法开始的,refresh()是一个模板方法,规定了IOC 容器的启动流程, 当然也定义了一些钩子函数,交给子类去实现。

refresh()方法主要为 IOC 容器 Bean 的生命周期管理提供条件,整个 refresh() 中 ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory() 这句以后代码的都是注册容器的信息源和生命周期事件,我们前面说的载入就是从这句代码开始启动。Spring IOC 容器载入 Bean 配置信息是从其子类容器的 refreshBeanFactory() 方法启动。

@Override
public void refresh() throws BeansException, IllegalStateException {
   synchronized (this.startupShutdownMonitor) {
      // Prepare this context for refreshing.
      // 1. 准备工作,记录容器启动时间,标记已启动状态
      prepareRefresh();

      // Tell the subclass to refresh the internal bean factory.
      // 2.告诉子类启动refreshBeanFactory()方法,Bean定义资源文件的载入从子类的refreshBeanFactory()方法启动
      ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

      // Prepare the bean factory for use in this context.
      // 3.为BeanFactory配置处理器,例如类加载器、事件处理器等
      prepareBeanFactory(beanFactory);

      try {
         // 4. 前置处理器
         postProcessBeanFactory(beanFactory);

         // Invoke factory processors registered as beans in the context.
         // 5.调用所有注册的BeanFactoryPostProcessor的Bean
         invokeBeanFactoryPostProcessors(beanFactory);

         // 6. 为BeanFactory注册BeanPost事件处理器, BeanPostProcessor是Bean后置处理器,用于监听容器触发的事件
         registerBeanPostProcessors(beanFactory);

         //7.初始化信息源,和国际化相关.
         initMessageSource();

         // Initialize event multicaster for this context.
         // 8.初始化容器事件传播器
         initApplicationEventMulticaster();

         // Initialize other special beans in specific context subclasses.
         // 9.调用子类的某些特殊Bean初始化方法
         onRefresh();

         // Check for listener beans and register them.
         // 10.为事件传播器注册事件监听器.
         registerListeners();

         // Instantiate all remaining (non-lazy-init) singletons.
         // 11.初始化所有剩余的单例Bean
         finishBeanFactoryInitialization(beanFactory);

         // Last step: publish corresponding event.
         // 12.初始化容器的生命周期事件处理器,并发布容器的生命周期事件
         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.
         // 13.销毁已创建的Bean
         destroyBeans();

         // Reset 'active' flag.
         // 14.取消refresh操作,重置容器的同步标识。
         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...
         // 15.重设公共缓存
         resetCommonCaches();
      }
   }
}

1.4.1 prepareRefresh

protected void prepareRefresh() {
   // Switch to active. 设置启动时间,启动标识
   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<>();
}

1.4.2. obtainFreshBeanFactory

protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
   refreshBeanFactory();
   return getBeanFactory();
}

AbstractRefreshableApplicationContext#refreshBeanFactory 创建容器

@Override
protected final void refreshBeanFactory() throws BeansException {
   // 如果已经有容器,销毁容器中的bean,关闭容器
   if (hasBeanFactory()) {
      destroyBeans();
      closeBeanFactory();
   }
   try {
      // 创建IOC容器
      DefaultListableBeanFactory beanFactory = createBeanFactory();
      beanFactory.setSerializationId(getId());
      // 自定义IOC容器,如设置启动参数,开启注解的自动装配等
      customizeBeanFactory(beanFactory);
      // 装载Bean的定义
      // 委派模式,在当前类中只定义了抽象的loadBeanDefinitions方法,具体的实现调用子类容器 loadBeanDefinitions(beanFactory);
      loadBeanDefinitions(beanFactory);
      this.beanFactory = beanFactory;
   }
   catch (IOException ex) {
      throw new ApplicationContextException("I/O error parsing bean definition source for " + getDisplayName(), ex);
   }
}

AbstractXmlApplicationContext#loadBeanDefinitions(beanFactory)

@Override
protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) throws BeansException, IOException {
   // 创建XmlBeanDefinitionReader
   XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory);

   // 为Bean读取器设置Spring资源加载器     
   beanDefinitionReader.setEnvironment(this.getEnvironment());
   beanDefinitionReader.setResourceLoader(this);
   beanDefinitionReader.setEntityResolver(new ResourceEntityResolver(this));

   // 当Bean读取器读取Bean定义的Xml资源文件时,启用Xml的校验机制
   initBeanDefinitionReader(beanDefinitionReader);
   // Bean读取器真正实现加载的方法
   loadBeanDefinitions(beanDefinitionReader);
}

initBeanDefinitionReader

protected void initBeanDefinitionReader(XmlBeanDefinitionReader reader) {
   reader.setValidating(this.validating);
}

loadBeanDefinitions

// Xml Bean读取器加载Bean定义资源
protected void loadBeanDefinitions(XmlBeanDefinitionReader reader) throws BeansException, IOException {
   // 获取Bean定义资源的定位
   Resource[] configResources = getConfigResources();
   if (configResources != null) {
      // Xml Bean读取器调用其父类AbstractBeanDefinitionReader读取定位的Bean定义资源
      reader.loadBeanDefinitions(configResources);
   }
   String[] configLocations = getConfigLocations();
   if (configLocations != null) {
       // Xml Bean读取器调用其父类AbstractBeanDefinitionReader读取定位的Bean定义资源
      reader.loadBeanDefinitions(configLocations);
   }
}

1.4.3 prepareBeanFactory(beanFactory)

这个方法不难理解,定了一堆处理器,比如类加载器,事件处理器等等。

protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory) {
   // Tell the internal bean factory to use the context's class loader etc.
   beanFactory.setBeanClassLoader(getClassLoader());
   beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver(beanFactory.getBeanClassLoader()));
   beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this, getEnvironment()));

   // Configure the bean factory with context callbacks.
   beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));
   beanFactory.ignoreDependencyInterface(EnvironmentAware.class);
   beanFactory.ignoreDependencyInterface(EmbeddedValueResolverAware.class);
   beanFactory.ignoreDependencyInterface(ResourceLoaderAware.class);
   beanFactory.ignoreDependencyInterface(ApplicationEventPublisherAware.class);
   beanFactory.ignoreDependencyInterface(MessageSourceAware.class);
   beanFactory.ignoreDependencyInterface(ApplicationContextAware.class);
   // ....
}

1.4.4 postProcessBeanFactory(beanFactory) 前置处理器

spring中并没有具体去实现postProcessBeanFactory方法,是提供给想要实现BeanPostProcessor的三方框架使用的。

protected void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) {
}

image.png

1.4.5 invokeBeanFactoryPostProcessors

为BeanFactory注册BeanPost事件处理器, BeanPostProcessor是Bean后置处理器,用于监听容器触发的事件,核心方法后面还会详细去介绍

protected void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory) {
   PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, getBeanFactoryPostProcessors());

   // Detect a LoadTimeWeaver and prepare for weaving, if found in the meantime
   if (beanFactory.getTempClassLoader() == null && beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {
      beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));
      beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));
   }
}

1.4.6 registerBeanPostProcessors(beanFactory)

为BeanFactory注册BeanPost事件处理器, BeanPostProcessor是Bean后置处理器,用于监听容器触发的事件.

protected void registerBeanPostProcessors(ConfigurableListableBeanFactory beanFactory) {
   PostProcessorRegistrationDelegate.registerBeanPostProcessors(beanFactory, this);
}

1.4.7 initMessageSource

初始化信息源,和国际化相关.

1.4.8 initApplicationEventMulticaster

初始化容器事件传播器.

protected void initApplicationEventMulticaster() {
   ConfigurableListableBeanFactory beanFactory = getBeanFactory();
   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.4.9 onRefresh()

调用子类的某些特殊Bean初始化方法, 主要和web相关

image.png

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

   // 先发布早期的监听器
   Set<ApplicationEvent> earlyEventsToProcess = this.earlyApplicationEvents;
   this.earlyApplicationEvents = null;
   if (!CollectionUtils.isEmpty(earlyEventsToProcess)) {
      for (ApplicationEvent earlyEvent : earlyEventsToProcess) {
         getApplicationEventMulticaster().multicastEvent(earlyEvent);
      }
   }
}

1.4.11 finishBeanFactoryInitialization

初始化所有剩余的单例Bean

1.4.12 finishRefresh

初始化容器的生命周期事件处理器,并发布容器的生命周期事件

2. Bean实例化阶段

参考

《Spring源码深度解析》
《Spring实战》
《Spring揭秘》