Spring容器启动(中)

容器刷新

在构造方法的初始以及配置类的注册中,大多BeanPostProcessor都只是生成了BeanDefinition,还没有完成实例化,但在AbstractApplicationContext的refresh()方法中,会进行一系列的初始化,以及对这些BeanPostProcessor进行排序。除了进行初始化之外,还会去设置一些EL表达式解析器、类型转化注册器等。

1、 刷新前工作

在构造方法中,Spring容器里面只是设置了操作系统的环境变量和JVM的环境变量,对于Web类型的Spring容器,还必须要包括Servlet中设置的参数,而刷新前的工作,主要就是去加载AbstractApplicationContext子类的一些参数,比如GenericWebApplicationContext中,会去加载Servlet上下文的参数

protected void prepareRefresh() {
   // Switch to active.
   this.startupDate = System.currentTimeMillis();
    //设置容器运行状态
   this.closed.set(false);
   this.active.set(true);

   // Initialize any placeholder property sources in the context environment.
   // 比如子类可以把ServletContext中的参数对设置到Environment
   initPropertySources();

   // Validate that all properties marked as required are resolvable:
   // see ConfigurablePropertyResolver#setRequiredProperties
   getEnvironment().validateRequiredProperties();
   ……
}
2 、容器重复刷新

在Spring容器刷新时,会判断容器是否允许重复刷新,如果允许重复刷新,且当前容器已经有了BeanFactory对象,则需要销毁BeanFactory单例池中所有的Bean实例,然后重新生成一个新的DefaultListableBeanFactory对象作为beanFactory;如果不允许重复刷新,重复刷新将会抛异常。

只有实现了AbstractRefreshableWebApplicationContext类的Spring重启,才允许重复刷新容器

调用obtainFreshBeanFactory()返回已有的beanFactory或重新生成一个beanFactory

ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

AbstractRefreshableWebApplicationContext的refreshBeanFactory()会去销毁单例池中的Bean实例,然后生成新的BeanFactory并初始化,而

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

AbstractRefreshableWebApplicationContext类中方法:

protected final void refreshBeanFactory() throws BeansException {
   if (hasBeanFactory()) {
      destroyBeans();
      closeBeanFactory();
   }
   try {
      DefaultListableBeanFactory beanFactory = createBeanFactory();
      beanFactory.setSerializationId(getId());
      customizeBeanFactory(beanFactory);
      loadBeanDefinitions(beanFactory);
      this.beanFactory = beanFactory;
   }
}

GenericApplicationContext类中方法:

protected final void refreshBeanFactory() throws IllegalStateException {
   if (!this.refreshed.compareAndSet(false, true)) {
      throw new IllegalStateException(
            "GenericApplicationContext does not support multiple refresh attempts: just call 'refresh' once");
   }
   this.beanFactory.setSerializationId(getId());
}
3、 准备BeanFactory

在第三步会去设置一些BeanFactory的基本属性,包括类加载器、SpringEL表达式解析器以及类型转换注册器

beanFactory.setBeanClassLoader(getClassLoader());

// Spring5.3中新增的功能,可以选择是否开启Spel功能,shouldIgnoreSpel默认为false,表示开启
if (!shouldIgnoreSpel) {
    beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver(beanFactory.getBeanClassLoader()));
}

// 添加一个ResourceEditorRegistrar,注册一些级别的类型转化器
beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this, getEnvironment()));

添加三个BeanProcessor的实例对象,分别是ApplicationContextAwareProcessor、ApplicationListenerDetector和LoadTimeWeaverAwareProcessor

// Configure the bean factory with context callbacks.
// 组成一个BeanPostProcessor,用来处理EnvironmentAware、EmbeddedValueResolverAware等回调
beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));

// Register early post-processor for detecting inner beans as ApplicationListeners.
// ApplicationListenerDetector负责把ApplicantsListener类型的Bean注册到ApplicationContext中
beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(this));

// Detect a LoadTimeWeaver and prepare for weaving, if found.
// Aspectj本身是通过编译期进行代理的,在Spring中就跟LoadTimeWeaver有关
if (!NativeDetector.inNativeImage() && 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()));
}

同时设置回调接口的方法不进行自动注入,并注册当前容器的依赖关系到ResolvableDependency,最后注册三个与环境变量相关的bean以及一个应用启动的实例到单例池中

// 如果一个属性对应的set方法在ignoredDependencyInterfaces接口中被定义了,则该属性不会进行自动注入(是Spring中的自动注入,不是@Autowired)
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.ignoreDependencyInterface(ApplicationStartupAware.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 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());
}
if (!beanFactory.containsLocalBean(APPLICATION_STARTUP_BEAN_NAME)) {
    beanFactory.registerSingleton(APPLICATION_STARTUP_BEAN_NAME, getApplicationStartup());
}
4、 子类设置BeanFactory

上一步,主要设置了BeanFactory公有的一些属性,但对于AbstractApplicationContext其子类来说,可能还需要一些特有的属性,以GenericWebApplicationContext为例,还要设置一些与servletContext相关的属性

// 子类来设置一下BeanFactory
postProcessBeanFactory(beanFactory);
protected void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) {
   if (this.servletContext != null) {
      beanFactory.addBeanPostProcessor(new ServletContextAwareProcessor(this.servletContext));
      beanFactory.ignoreDependencyInterface(ServletContextAware.class);
   }
   WebApplicationContextUtils.registerWebApplicationScopes(beanFactory, this.servletContext);
   WebApplicationContextUtils.registerEnvironmentBeans(beanFactory, this.servletContext);
}
5、 执行BeanFactoryPostProcessor方法

BeanFactory准备好了之后,执行BeanFactoryPostProcessor,开始对BeanFactory进行处理,默认情况下,此时beanFactory的BeanDefinitionMap中有6个BeanDefinition,其中5个都是在前面构造创建时添加进来的,还有一个注册配置类时添加的配置类AppConfig的BeanDefinition,而这6个中只有一个BeanFactoryPostProcessor:ConfigurationClassPostProcessor

这里会执行ConfigurationClassPostProcessor进行@Component的扫描,扫描得到BeanDefinition,并注册到beanFactory中

// 注意:扫描的过程中可能又会扫描出其他的BeanFactoryPostProcessor,那么这些BeanFactoryPostProcessor也得在这一步执行
invokeBeanFactoryPostProcessors(beanFactory);  // scanner.scan()
protected void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory) {

   // 正真调用BeanFactoryPostProcessor的方法
   PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, getBeanFactoryPostProcessors());

   // Detect a LoadTimeWeaver and prepare for weaving, if found in the meantime
   // (e.g. through an @Bean method registered by ConfigurationClassPostProcessor)
   // 关于LoadTimeWeaver看这篇文章了解即可,https://www.cnblogs.com/wade-luffy/p/6073702.html
   if (!NativeDetector.inNativeImage() && beanFactory.getTempClassLoader() == null && beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {
      beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));
      beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));
   }
}
6、 实例化BeanPostProcessors

在上一步执行BeanFactoryPostProcessor的方法进行扫描,会将扫描到的所有实现了BeanPostProcessor的类生成BeanDefinition,而这些BeanPostProcessor的实例在创建Bean实例时都会用到,所以,这一步主要是将所有的BeanPostProcessor进行实例化,并排序,然后添加到BeanFactory的beanPostProcessors属性中去

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

注:关于invokeBeanFactoryPostProcessors()和registerBeanPostProcessors()的介绍,将会在后面下一篇文章着重介绍

7、 初始化MessageSource

设置ApplicationContext的MessageSource,要么是用户设置的,要么是DelegatingMessageSource,主要用于处理国际化资源

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

如果当前beanFactory还没有MessageSource,则生成一个DelegatingMessageSource对象,并设置父messageSource,最后将MessageSource实例添加到beanFactory的单例池中

protected void initMessageSource() {
   ConfigurableListableBeanFactory beanFactory = getBeanFactory();
   if (beanFactory.containsLocalBean(MESSAGE_SOURCE_BEAN_NAME)) {
      this.messageSource = beanFactory.getBean(MESSAGE_SOURCE_BEAN_NAME, MessageSource.class);
      // Make MessageSource aware of parent MessageSource.
      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.
            // 拿父ApplicationContext的messageSource作为this.messageSource的父messageSource
            hms.setParentMessageSource(getInternalParentMessageSource());
         }
      }
   }
   else {
      // Use empty MessageSource to be able to accept getMessage calls.
      DelegatingMessageSource dms = new DelegatingMessageSource();
      dms.setParentMessageSource(getInternalParentMessageSource());
      this.messageSource = dms;
      beanFactory.registerSingleton(MESSAGE_SOURCE_BEAN_NAME, this.messageSource);
   }
}
8、 初始化事件广播器

事件广播器主要是当发布事件时,获取所有的事件监听器,来串行或并行处理发布的事件

// Initialize event multicaster for this context.
// 设置ApplicationContext的applicationEventMulticaster,么是用户设置的,要么是SimpleApplicationEventMulticaster
initApplicationEventMulticaster();

如果存在名字为“applicationEventMulticaster”的BeanDefinition,则直接根据BeanDefinition生成一个ApplicationEventMulticaster实例;如果没有BeanDefinition,则直接生成一个SimpleApplicationEventMulticaster对象,并添加到单例池

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);
   }
   else {
      this.applicationEventMulticaster = new SimpleApplicationEventMulticaster(beanFactory);
      beanFactory.registerSingleton(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, this.applicationEventMulticaster);
   }
}
9、 注册事件监听器
// Check for listener beans and register them.
// 把定义的ApplicationListener的Bean对象,设置到ApplicationContext中去,并执行在此之前所发布的事件
registerListeners();

将所有的ApplicationListener实例添加到当前容器的事件广播器ApplicationEventMulticaster,同时找到所有ApplicationListener实现类的BeanName也添加到事件广播器中,主要为了应对懒加载的事件监听器

最后去处理事件广播器初始化之前发布的事件

protected void registerListeners() {
   // Register statically specified listeners first.
   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...
   // 添加了事件监听器后,判断是否有earlyApplicationEvents,如果有就使用事件广播器发布earlyApplicationEvents
   // earlyApplicationEvents表示在事件广播器还没生成好之前ApplicationContext所发布的事件
   Set<ApplicationEvent> earlyEventsToProcess = this.earlyApplicationEvents;
   this.earlyApplicationEvents = null;
   if (!CollectionUtils.isEmpty(earlyEventsToProcess)) {
      for (ApplicationEvent earlyEvent : earlyEventsToProcess) {
         getApplicationEventMulticaster().multicastEvent(earlyEvent);
      }
   }
}

发布-监听事件的大概流程:容器调用publishEvent()来发布事件,然后该容器的事件广播器将遍历它的事件监听器,并行或串行来执行事件监听器方法

10、 完成BeanFactory初始化

这一步其中最重要的就是实例化非懒加载的单例Bean,但是也还有一些其他的操作,比如:设置类型转换器、默认的占位符解析器

// Instantiate all remaining (non-lazy-init) singletons.
finishBeanFactoryInitialization(beanFactory);
protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {
   // Initialize conversion service for this context.
   // 如果BeanFactory中存在名字叫conversionService的Bean,则设置为BeanFactory的conversionService属性
   // ConversionService是用来进行类型转化的
   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 BeanFactoryPostProcessor
   // (such as a PropertySourcesPlaceholderConfigurer bean) registered any before:
   // at this point, primarily for resolution in annotation attribute values.
   // 设置默认的占位符解析器  ${xxx}  ---key
   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);
   }

   // Instantiate all remaining (non-lazy-init) singletons.
   // 实例化非懒加载的单例Bean
   beanFactory.preInstantiateSingletons();
}
11、 完成刷新,发布事件
// Last step: publish corresponding event.
finishRefresh();

在最后完成刷新这一步,会去设置lifecycleProcessor,并调用onRefresh()去更新容器的状态,后面容器状态的改变都会调用lifecycleProcessor的内部方法类更新状态,最后发布一个容器启动完成的事件

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

   // Initialize lifecycle processor for this context.
   // 设置lifecycleProcessor,默认为DefaultLifecycleProcessor
   initLifecycleProcessor();

   // Propagate refresh to lifecycle processor first.
   // 调用LifecycleBean的start()
   getLifecycleProcessor().onRefresh();

   // Publish the final event.
   publishEvent(new ContextRefreshedEvent(this));
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值