解读ApplicationContext接口以AbstractApplicationContext的refresh方法为起点

首先我们看其的接口关系,了解其整体结构:

 

1、我们可以看到,其关于Bean获取的接口接口是HierarchicalBeanFactory(获取父Bean容器)、ListableBeanFactory(可列表的Bean容器-如根据Bean类型、或获取Bean的数量等)

要注意的是、这里与我们前面讲的DefaultListableBeanFactory的区别。我们前面说的DefaultListableBeanFactory,就是一个纯粹的生产Bean的容器,而我们现在讲的ApplicationContext接口其等于是一个管理者,其控制DefaultListableBeanFactory这个生产Bean的将其去生产,并对这个Bean过程生产Bean对象的过程进行进行管控。其实ApplicationContext接口的getBean方法就是再去调用其的成员变量去获取Bean对象的。

 

2、然后是EnvironmentCapable接口,即决定启动ApplicationContext管理者的环境、如要满足那些条件才能启动、以及要获取哪些Bean、不获取哪些Bean,这个在下面源码中会讲到。

3、然后是ApplicationEventPublisher接口,其主要是进行Event发布,然后对应监视其的Lister进行对应处理。就是一种监视器模式的机制,可以看下这篇文章:https://cloud.tencent.com/developer/article/1449255

4、ResourcePatternResolver,决定怎样去解析资源,例如怎样确定资源的读取路径。

5、MessageSource,资源的国际化,可以看下这一篇:https://www.cnblogs.com/wade-luffy/p/6073391.html

6、ApplicationContext,接口,这些看其名字,就知道这些方法是干什么的:

7、ConfigurableApplicationContext接口

通过这些方法名我们可以知道,即将前面那些接口要处理的对象通过这个Bean工厂的管理者设置到对应接口的成员变量中。例如添加BeanFactoryPostProcessor、ApplicationListener、ConfigurableEnvironment,这些之后通过源码进行解读。

8、LifeCycle、Closeable,即这个Bean管理者的启动、关闭方法,就是一个容器的生命周期方法,这个在Tomcat容器也是有对应方法。

 

然后分析其源码:

public void refresh() throws BeansException, IllegalStateException {
   synchronized (this.startupShutdownMonitor) {
      // Prepare this context for refreshing.
      prepareRefresh();

      // Tell the subclass to refresh the internal bean factory.
      ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

      // Prepare the bean factory for use in this context.
      prepareBeanFactory(beanFactory);

      try {
         // Allows post-processing of the bean factory in context subclasses.
         postProcessBeanFactory(beanFactory);

         // Invoke factory processors registered as beans in the context.
         invokeBeanFactoryPostProcessors(beanFactory);

         // Register bean processors that intercept bean creation.
         registerBeanPostProcessors(beanFactory);

         // Initialize message source for this context.
         initMessageSource();

         // Initialize event multicaster for this context.
         initApplicationEventMulticaster();

         // Initialize other special beans in specific context subclasses.
         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...
         resetCommonCaches();
      }
   }
}

 

首先是:prepareRefresh();

   这个主要是初始化ApplicationContext的启动准备,主要是初始化Envirement接口:

// Initialize any placeholder property sources in the context environment
initPropertySources();

// Validate that all properties marked as required are resolvable
// see ConfigurablePropertyResolver#setRequiredProperties
getEnvironment().validateRequiredProperties();

// Allow for the collection of early ApplicationEvents,
// to be published once the multicaster is available...
this.earlyApplicationEvents = new LinkedHashSet<>();

其中initPropertySources()是将servletContext,servletConfig设置到envirement中:

protected void initPropertySources() {
   ConfigurableEnvironment env = getEnvironment();
   if (env instanceof ConfigurableWebEnvironment) {
      ((ConfigurableWebEnvironment) env).initPropertySources(this.servletContext, this.servletConfig);
   }
}
而getEnvironment().validateRequiredProperties()是进行启动的参数校验,如果缺少必要的参数,则抛出异常,停止启动。
this.earlyApplicationEvents = new LinkedHashSet<>()由名字就可以知道,提前初始化的ApplicationEvent。具体用处到使用再分析。

第二个是:

// Tell the subclass to refresh the internal bean factory.
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

// Prepare the bean factory for use in this context.
prepareBeanFactory(beanFactory);

1、首先是获取前面提到的DefaultListBeanFactory,即Bean工厂。

protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
   refreshBeanFactory();
   ConfigurableListableBeanFactory beanFactory = getBeanFactory();
   if (logger.isDebugEnabled()) {
      logger.debug("Bean factory for " + getDisplayName() + ": " + beanFactory);
   }
   return beanFactory;
}
protected final void refreshBeanFactory() throws BeansException {
   if (hasBeanFactory()) {
      destroyBeans();
      closeBeanFactory();
   }
   try {
      DefaultListableBeanFactory beanFactory = createBeanFactory();
      beanFactory.setSerializationId(getId());
      customizeBeanFactory(beanFactory);
      //这个就是从资源中加载BeanDefiniion
      loadBeanDefinitions(beanFactory);
      synchronized (this.beanFactoryMonitor) {
         this.beanFactory = beanFactory;
      }
   }
   catch (IOException ex) {
      throw new ApplicationContextException("I/O error parsing bean definition source for " + getDisplayName(), ex);
   }
}
protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) throws BeansException, IOException {
   // Create a new XmlBeanDefinitionReader for the given BeanFactory.
   XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory);
              ..............
   loadBeanDefinitions(beanDefinitionReader);
}
2、之后是准备这个工厂,直接看prepareBeanFactory()方法的实现:
protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory) {
   // Tell the internal bean factory to use the context's class loader etc.
   //设置这个工厂的类加载器
   beanFactory.setBeanClassLoader(getClassLoader());
   //这个是设置SPEL表达式解析器,与主线关系不是很大,就不详细展开
   beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver(beanFactory.getBeanClassLoader()));
   //而关于PropertyEditorRegistrar,可以看我的这一篇博文:https://blog.csdn.net/qq_25179481/article/details/97620204
   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);

   // BeanFactory interface not registered as resolvable type in a plain factory.
   // MessageSource registered (and found for autowiring) as a bean.
   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.
   beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(this));

   // Detect a LoadTimeWeaver and prepare for weaving, if found.
   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()));
   }

   // Register default environment beans.
   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());
   }
}

然后在这个准备BeanFactory的过程中,添加了一个BeanPostProcessor(关于BeanPostProcessor的源码执行时机可以看我的这篇博文:https://blog.csdn.net/qq_25179481/article/details/89204826

beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));

这里分析下ApplicationContextAwareProcessor的源码。

在postProcessBeforeInitialization的的方法中主要是方法invokeAwareInterfaces(bean);

private void invokeAwareInterfaces(Object bean) {
   if (bean instanceof Aware) {
      if (bean instanceof EnvironmentAware) {
         ((EnvironmentAware) bean).setEnvironment(this.applicationContext.getEnvironment());
      }
      if (bean instanceof EmbeddedValueResolverAware) {
         ((EmbeddedValueResolverAware) bean).setEmbeddedValueResolver(this.embeddedValueResolver);
      }
      if (bean instanceof ResourceLoaderAware) {
         ((ResourceLoaderAware) bean).setResourceLoader(this.applicationContext);
      }
      if (bean instanceof ApplicationEventPublisherAware) {
         ((ApplicationEventPublisherAware) bean).setApplicationEventPublisher(this.applicationContext);
      }
      if (bean instanceof MessageSourceAware) {
         ((MessageSourceAware) bean).setMessageSource(this.applicationContext);
      }
      if (bean instanceof ApplicationContextAware) {
         ((ApplicationContextAware) bean).setApplicationContext(this.applicationContext);
      }
   }
}

这里就与下面的Aware接口对应了。

将这些被忽略的值重新设置上。

   第三个是:registerResolvableDependency():

beanFactory.registerResolvableDependency(BeanFactory.class, beanFactory);
beanFactory.registerResolvableDependency(ResourceLoader.class, this);
beanFactory.registerResolvableDependency(ApplicationEventPublisher.class, this);
beanFactory.registerResolvableDependency(ApplicationContext.class, this);

这个主要是将这些ApplicationEventPublisher设置到BeanFactory容器中。this也就是指当前这个ApplicationContext,即Spring容器的管理者。要注意Spring容器中的两大类,第一个就是Spring自己的类,这是通过spring自己new出来的,还有一个是交给Sring管理的,就是Bean工厂产生的。归根结底,spring只是在java的基础上对对象做一层封装。它要管理,首先其自己就需要一些对象来形成这个管理者,因为没有谁再去封装spring容器了,而这个对象在java范围内肯定需要new一个对象(当然也可以用反射),所以spring它自己new出这个管理者后(即ApplicationEventPublisher、BeanFactory等),再通过这个管理者去做这个new对象的事,然后spring这个管理者对使用其的人来说,好像是没有new对象一样。

    就拿在最前面的environment来说:

public ConfigurableEnvironment getEnvironment() {
   if (this.environment == null) {
      this.environment = createEnvironment();
   }
   return this.environment;
}
protected ConfigurableEnvironment createEnvironment() {
   return new StandardEnvironment();
}

第三个是:ApplicationListenerDetector,这个直接看源码就知道是什么意思了:

public Object postProcessAfterInitialization(Object bean, String beanName) {
   if (bean instanceof ApplicationListener) {
      // potentially not detected as a listener by getBeanNamesForType retrieval
      Boolean flag = this.singletonNames.get(beanName);
      if (Boolean.TRUE.equals(flag)) {
         // singleton bean (top-level or inner): register on the fly
         this.applicationContext.addApplicationListener((ApplicationListener<?>) bean);
      }
      else if (Boolean.FALSE.equals(flag)) {
         if (logger.isWarnEnabled() && !this.applicationContext.containsBean(beanName)) {
            // inner bean with other scope - can't reliably process events
            logger.warn("Inner bean '" + beanName + "' implements ApplicationListener interface " +
                  "but is not reachable for event multicasting by its containing ApplicationContext " +
                  "because it does not have singleton scope. Only top-level listener beans are allowed " +
                  "to be of non-singleton scope.");
         }
         this.singletonNames.remove(beanName);
      }
   }
   return bean;
}

就是判断这个bean是不是ApplicationListener,如果是,并且已经在单例对象集合中,就将其加到applicationContext的Lister集合中。

4、postProcessBeanFactory(beanFactory)这个是个模板方法,我们看其的其中一个子类:

@Override
protected void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) {
   beanFactory.addBeanPostProcessor(new ServletContextAwareProcessor(this.servletContext, this.servletConfig));
   beanFactory.ignoreDependencyInterface(ServletContextAware.class);
   beanFactory.ignoreDependencyInterface(ServletConfigAware.class);

   WebApplicationContextUtils.registerWebApplicationScopes(beanFactory, this.servletContext);
   WebApplicationContextUtils.registerEnvironmentBeans(beanFactory, this.servletContext, this.servletConfig);
}

一个是添加一个PostProcessor接口ServletContextAwareProcessor,这个接口就是给实现了ServletConfigAware

、ServletContextAware接口赋值servletContext与servletConfig,关于servletContext与servletConfig(http://c.biancheng.net/view/3998.html)。

5、invokeBeanFactoryPostProcessors(beanFactory)

这个方法从名字看是执行BeanFactoryPostProcessor接口,但其实里面会执行两个接口方法。一个是BeanFactoryPostProcessor,另一个是BeanDefinitionRegistryPostProcessor,同时这两个接口可以分别通过Order接口来决定执行的顺序。

其中看PostProcessor接口的作用,就是看其要执行的入参是什么,就知道它能干什么了。

BeanFactoryPostProcessor:

void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException;

入参是ConfigurableListableBeanFactory,它就能掉用ConfigurableListableBeanFactory里面的方法去做对应的操作。

BeanDefinitionRegistryPostProcessor:
void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException;

可以看到这个的入参仅仅是BeanDefinitionRegistry,所以其单单使用BeanDefinitionRegistry对应的方法。

6:、registerBeanPostProcessors(beanFactory);

这个通过名字可以知道其是注册BeanPostProcessor到ConfigurableListableBeanFactory,因为这些BeanPostProcessor现在都还是以BeanDefinition的方式存在在ConfigurableListableBeanFactory中,现在就提前出来,将他们放到List中。

同时在分离完后还会注册一个BeanPostProcessor接口的工厂中,ApplicationListenerDetector,这个就是与ApplicationLister相关的,想分离BeanPostProcessor接口一样,也将ApplicaationLister分离出来,以及将Lister移除。

7、initMessageSource();初始化MessageSource,即资源国际化的。

8、initApplicationEventMulticaster(),初始化ApplicationEventMulticaster,用于事件发布的(https://cloud.tencent.com/developer/article/1449255)。

在ApplicationEventMulticaster中运行时间就是这个,就是一ApplicationEvent为参数,调用Lister接口的onApplicationEvent方法

private void doInvokeListener(ApplicationListener listener, ApplicationEvent event) {
   try {
      listener.onApplicationEvent(event);
   }
   catch (ClassCastException ex) {
      String msg = ex.getMessage();
      if (msg == null || matchesClassCastMessage(msg, event.getClass().getName())) {
         // Possibly a lambda-defined listener which we could not resolve the generic event type for
         // -> let's suppress the exception and just log a debug message.
         Log logger = LogFactory.getLog(getClass());
         if (logger.isDebugEnabled()) {
            logger.debug("Non-matching event type for listener: " + listener, ex);
         }
      }
      else {
         throw ex;
      }
   }
}

9、onRefresh();就是刷新主题,一般没怎么用,没有收入研究。

10、registerListeners();

这个就是想将BeanPostProcessor、BeanDefinitionRegistryPostProcessor从beanDefinition转化出来一样,将ApplicationLister转化出来添加到ApplicationEventMulticast中。

11、finishBeanFactoryInitialization(beanFactory);结束Bean的初始化。

protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {
   // Initialize conversion service for this context.
   if (beanFactory.containsBean(CONVERSION_SERVICE_BEAN_NAME) &&
         beanFactory.isTypeMatch(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class)) {
      beanFactory.setConversionService(
            beanFactory.getBean(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class));
   }

   // Register a default embedded value resolver if no bean post-processor
   // (such as a PropertyPlaceholderConfigurer bean) registered any before:
   // at this point, primarily for resolution in annotation attribute values.
   if (!beanFactory.hasEmbeddedValueResolver()) {
      beanFactory.addEmbeddedValueResolver(strVal -> getEnvironment().resolvePlaceholders(strVal));
   }

   // Initialize LoadTimeWeaverAware beans early to allow for registering their transformers early.
   String[] weaverAwareNames = beanFactory.getBeanNamesForType(LoadTimeWeaverAware.class, false, false);
   for (String weaverAwareName : weaverAwareNames) {
      getBean(weaverAwareName);
   }

   // Stop using the temporary ClassLoader for type matching.
   beanFactory.setTempClassLoader(null);

   // Allow for caching all bean definition metadata, not expecting further changes.
   beanFactory.freezeConfiguration();

   // Instantiate all remaining (non-lazy-init) singletons.
   beanFactory.preInstantiateSingletons();
}

 

1、首先提取ConversionService接口设置到Bean工厂中。这个好像是跟PropertyEditor接口由于类型转换的,暂时还未具体研究。

2、beanFactory.freezeConfiguration();的作用表示停止BeanDefinition的注册

public void freezeConfiguration() {
   this.configurationFrozen = true;
   this.frozenBeanDefinitionNames = StringUtils.toStringArray(this.beanDefinitionNames);
}
public String[] getBeanDefinitionNames() {
   String[] frozenNames = this.frozenBeanDefinitionNames;
   if (frozenNames != null) {
      return frozenNames.clone();
   }
   else {
      return StringUtils.toStringArray(this.beanDefinitionNames);
   }
}
3、beanFactory.preInstantiateSingletons();这个就是bean的实例化,将所有bean变成对象的形式。

12、finishRefresh();即结束refresh

protected void finishRefresh() {
   // Clear context-level resource caches (such as ASM metadata from scanning).
   clearResourceCaches();

   // Initialize lifecycle processor for this context.
   initLifecycleProcessor();

   // Propagate refresh to lifecycle processor first.
   getLifecycleProcessor().onRefresh();

   // Publish the final event.
   publishEvent(new ContextRefreshedEvent(this));

   // Participate in LiveBeansView MBean, if active.
   LiveBeansView.registerApplicationContext(this);
}

1、其中initLifecycleProcessor,注册LifecycleProcessor接口到bean工厂中,注意这里它是根据名字去获取这个Bean的,所以只会获取到一个LifecycleProcessor。与生命周期相关

public interface LifecycleProcessor extends Lifecycle {

   /**
    * Notification of context refresh, e.g. for auto-starting components.
    */
   void onRefresh();

   /**
    * Notification of context close phase, e.g. for auto-stopping components.
    */
   void onClose();

}

2、getLifecycleProcessor().onRefresh();就是上面的LifecycleProcessor。然后还有onClose就是用于容器关闭时去进行对应的操作,例如释放一些资源等。

3、publishEvent(new ContextRefreshedEvent(this));发布这个事件。

   其内部还是通过获取ApplicationContext的ApplicationContextMulticaster去处理。

getApplicationEventMulticaster().multicastEvent(applicationEvent, eventType);
@Override
public void multicastEvent(final ApplicationEvent event, @Nullable ResolvableType eventType) {
   ResolvableType type = (eventType != null ? eventType : resolveDefaultEventType(event));
   for (final ApplicationListener<?> listener : getApplicationListeners(event, type)) {
      Executor executor = getTaskExecutor();
      if (executor != null) {
         executor.execute(() -> invokeListener(listener, event));
      }
      else {
         invokeListener(listener, event);
      }
   }
}

再下面就是上面提过的。

4、LiveBeansView.registerApplicationContext(this);这个还未研究。

自此,容器的初始化启动各种就完成了。

 

拿一个初学spring最常见的类ClassPathXmlApplicationContext,看其创建对象的构造方法,就知道到底在什么时候调用refresh初始化ApplicationContext了。

public ClassPathXmlApplicationContext(String configLocation) throws BeansException {
   this(new String[] {configLocation}, true, null);
}
public ClassPathXmlApplicationContext(
      String[] configLocations, boolean refresh, @Nullable ApplicationContext parent)
      throws BeansException {

   super(parent);
   setConfigLocations(configLocations);
   if (refresh) {
      refresh();
   }
}

完结

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值