Spring原理【4】容器其他特性的设计与实现

99 阅读16分钟

ApplicationContext和Bean的初始化及销毁

对于BeanFactory,特别是ApplicationContext,容器自身也有一个初始化和销毁关闭的 过程。下面详细看看在这两个过程中,应用上下文完成了什么,可以让我们更多地理解应用 上下文的工作,容器初始化和关闭过程可以简要地通过下图来表现。 从图中可以看到,对ApplicationContext启动的过程是在AbstractApplicationContext中实现的。在使用应用上下文时需要做一些准备工作,这些准备工作prepareBeanFactory()方法中实现。在这个方法中,为容器配置了ClassLoader、PropertyEditor和BeanPostProcessor等,从而为容器的启动做好了必要的准备工作。

容器的初始化和关闭大致分为: (1)org.springframework.context.support.AbstractApplicationContext#prepareBeanFactory (2)org.springframework.beans.factory.config.ConfigurableListableBeanFactory.addPropertyEditorRegister (3)org.springframework.beans.factory.config.ConfigurableListableBeanFactory.addBeanPostProcessor (4)org.springframework.context.support.AbstractApplicationContext#doClose (5)org.springframework.context.support.AbstractApplicationContext#closeBeanFactory

org.springframework.context.support.AbstractApplicationContext#prepareBeanFactory的实现如下:

protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory) {
   // Tell the internal bean factory to use the context's class loader etc.
   beanFactory.setBeanClassLoader(getClassLoader());
   if (!shouldIgnoreSpel) {
      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);
   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 early post-processor for detecting inner beans as ApplicationListeners.
   beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(this));

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

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

同样,在容器要关闭时,也需要完成一系列的工作,这些工作在doClose()方法中完成。 在这个方法中,先发出容器关闭的信号,然后将Bean逐个关闭,最后关闭容器自身。

org.springframework.context.support.AbstractApplicationContext#doClose实现如下:

protected void doClose() {
   // Check whether an actual close attempt is necessary...
   if (this.active.get() && this.closed.compareAndSet(false, true)) {
      if (logger.isDebugEnabled()) {
         logger.debug("Closing " + this);
      }

      if (!NativeDetector.inNativeImage()) {
         LiveBeansView.unregisterApplicationContext(this);
      }

      try {
         // Publish shutdown event.
         publishEvent(new ContextClosedEvent(this));
      }
      catch (Throwable ex) {
         logger.warn("Exception thrown from ApplicationListener handling ContextClosedEvent", ex);
      }

      // Stop all Lifecycle beans, to avoid delays during individual destruction.
      if (this.lifecycleProcessor != null) {
         try {
            this.lifecycleProcessor.onClose();
         }
         catch (Throwable ex) {
            logger.warn("Exception thrown from LifecycleProcessor on context close", ex);
         }
      }

      // Destroy all cached singletons in the context's BeanFactory.
      destroyBeans();

      // Close the state of this context itself.
      closeBeanFactory();

      // Let subclasses do some final clean-up if they wish...
      onClose();

      // Reset common introspection caches to avoid class reference leaks.
      resetCommonCaches();

      // Reset local application listeners to pre-refresh state.
      if (this.earlyApplicationListeners != null) {
         this.applicationListeners.clear();
         this.applicationListeners.addAll(this.earlyApplicationListeners);
      }

      // Switch to inactive.
      this.active.set(false);
   }
}

容器的实现是通过IoC管理Bean的生命周期来实现的。SpringIoC容器在对Bean的生命 周期进行管理时提供了Bean生命周期各个时间点的回调。在分析Bean初始化和销毁过程的设计之前,简要介绍一下loC容器中的Bean生命周期。 (1)Bean实例的创建。 (2)为Bean实例设置属性。 (3)调用Bean的初始化方法。 (4)应用可以通过IoC容器使用Bean。 (5)当容器关闭时,调用Bean的销毁方法。 Bean的初始化方法调用是在以下的initializeBean方法中实现的:

org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#initializeBean(java.lang.String, java.lang.Object, org.springframework.beans.factory.support.RootBeanDefinition)的实现如下:

protected Object initializeBean(String beanName, Object bean, @Nullable RootBeanDefinition mbd) {
   if (System.getSecurityManager() != null) {
      AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
         invokeAwareMethods(beanName, bean);
         return null;
      }, getAccessControlContext());
   }
   else {
      invokeAwareMethods(beanName, bean);
   }

   Object wrappedBean = bean;
   if (mbd == null || !mbd.isSynthetic()) {
      wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
   }

   try {
      invokeInitMethods(beanName, wrappedBean, mbd);
   }
   catch (Throwable ex) {
      throw new BeanCreationException(
            (mbd != null ? mbd.getResourceDescription() : null),
            beanName, "Invocation of init method failed", ex);
   }
   if (mbd == null || !mbd.isSynthetic()) {
      wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
   }

   return wrappedBean;
}

在调用Bean的初始化方法之前,会调用一系列的aware接口实现,把相关的BeanName、BeanClassLoader,以及BeanFactoy注入到Bean中去。接着会看到对invokeInitMethods的调用,这时还会看到启动afterPropertiesSet的过程,当然,这需要Bean实现InitializingBean的接口,对应的初始化处理可以在InitializingBean接口的afterPropertiesSet方法中实现,这里同样是对Bean的一个回调。

org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#invokeAwareMethods的实现如下:

private void invokeAwareMethods(String beanName, Object bean) {
   if (bean instanceof Aware) {
      if (bean instanceof BeanNameAware) {
         ((BeanNameAware) bean).setBeanName(beanName);
      }
      if (bean instanceof BeanClassLoaderAware) {
         ClassLoader bcl = getBeanClassLoader();
         if (bcl != null) {
            ((BeanClassLoaderAware) bean).setBeanClassLoader(bcl);
         }
      }
      if (bean instanceof BeanFactoryAware) {
         ((BeanFactoryAware) bean).setBeanFactory(AbstractAutowireCapableBeanFactory.this);
      }
   }
}

org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#applyBeanPostProcessorsBeforeInitialization的实现如下:

public Object applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName)
      throws BeansException {

   Object result = existingBean;
   for (BeanPostProcessor processor : getBeanPostProcessors()) {
      Object current = processor.postProcessBeforeInitialization(result, beanName);
      if (current == null) {
         return result;
      }
      result = current;
   }
   return result;
}

org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#invokeInitMethods实现如下:

protected void invokeInitMethods(String beanName, Object bean, @Nullable RootBeanDefinition mbd)
      throws Throwable {

   boolean isInitializingBean = (bean instanceof InitializingBean);
   if (isInitializingBean && (mbd == null || !mbd.hasAnyExternallyManagedInitMethod("afterPropertiesSet"))) {
      if (logger.isTraceEnabled()) {
         logger.trace("Invoking afterPropertiesSet() on bean with name '" + beanName + "'");
      }
      if (System.getSecurityManager() != null) {
         try {
            AccessController.doPrivileged((PrivilegedExceptionAction<Object>) () -> {
               ((InitializingBean) bean).afterPropertiesSet();
               return null;
            }, getAccessControlContext());
         }
         catch (PrivilegedActionException pae) {
            throw pae.getException();
         }
      }
      else {
         ((InitializingBean) bean).afterPropertiesSet();
      }
   }

   if (mbd != null && bean.getClass() != NullBean.class) {
      String initMethodName = mbd.getInitMethodName();
      if (StringUtils.hasLength(initMethodName) &&
            !(isInitializingBean && "afterPropertiesSet".equals(initMethodName)) &&
            !mbd.hasAnyExternallyManagedInitMethod(initMethodName)) {
         // 执行自定义的初始化方法
         invokeCustomInitMethod(beanName, bean, mbd);
      }
   }
}

protected void invokeCustomInitMethod(String beanName, Object bean, RootBeanDefinition mbd)
      throws Throwable {
   // 获取xml等形式配置的init初始化方法
   String initMethodName = mbd.getInitMethodName();
   Assert.state(initMethodName != null, "No init method set");
   Method initMethod = (mbd.isNonPublicAccessAllowed() ?
         BeanUtils.findMethod(bean.getClass(), initMethodName) :
         ClassUtils.getMethodIfAvailable(bean.getClass(), initMethodName));

   if (initMethod == null) {
      if (mbd.isEnforceInitMethod()) {
         throw new BeanDefinitionValidationException("Could not find an init method named '" +
               initMethodName + "' on bean with name '" + beanName + "'");
      }
      else {
         if (logger.isTraceEnabled()) {
            logger.trace("No default init method named '" + initMethodName +
                  "' found on bean with name '" + beanName + "'");
         }
         // Ignore non-existent default lifecycle methods.
         return;
      }
   }

   if (logger.isTraceEnabled()) {
      logger.trace("Invoking init method  '" + initMethodName + "' on bean with name '" + beanName + "'");
   }
   Method methodToInvoke = ClassUtils.getInterfaceMethodIfPossible(initMethod, bean.getClass());

   if (System.getSecurityManager() != null) {
      AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
         ReflectionUtils.makeAccessible(methodToInvoke);
         return null;
      });
      try {
         AccessController.doPrivileged((PrivilegedExceptionAction<Object>)
               () -> methodToInvoke.invoke(bean), getAccessControlContext());
      }
      catch (PrivilegedActionException pae) {
         InvocationTargetException ex = (InvocationTargetException) pae.getException();
         throw ex.getTargetException();
      }
   }
   else {
      try {
         ReflectionUtils.makeAccessible(methodToInvoke);
         methodToInvoke.invoke(bean);
      }
      catch (InvocationTargetException ex) {
         throw ex.getTargetException();
      }
   }
}

org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#applyBeanPostProcessorsAfterInitialization的实现如下:

public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName)
      throws BeansException {

   Object result = existingBean;
   for (BeanPostProcessor processor : getBeanPostProcessors()) {
      Object current = processor.postProcessAfterInitialization(result, beanName);
      if (current == null) {
         return result;
      }
      result = current;
   }
   return result;
}

与Bean初始化类似,当容器关闭时,可以看到对Bean销毁方法的调用。Bean销毁过程是这样的:

org.springframework.context.support.AbstractApplicationContext#doClose的实现如下:

protected void doClose() {
   // Check whether an actual close attempt is necessary...
   if (this.active.get() && this.closed.compareAndSet(false, true)) {
      if (logger.isDebugEnabled()) {
         logger.debug("Closing " + this);
      }

      if (!NativeDetector.inNativeImage()) {
         LiveBeansView.unregisterApplicationContext(this);
      }

      try {
         // Publish shutdown event.
         publishEvent(new ContextClosedEvent(this));
      }
      catch (Throwable ex) {
         logger.warn("Exception thrown from ApplicationListener handling ContextClosedEvent", ex);
      }

      // Stop all Lifecycle beans, to avoid delays during individual destruction.
      if (this.lifecycleProcessor != null) {
         try {
            this.lifecycleProcessor.onClose();
         }
         catch (Throwable ex) {
            logger.warn("Exception thrown from LifecycleProcessor on context close", ex);
         }
      }

      // Destroy all cached singletons in the context's BeanFactory.
      destroyBeans();

      // Close the state of this context itself.
      closeBeanFactory();

      // Let subclasses do some final clean-up if they wish...
      onClose();

      // Reset common introspection caches to avoid class reference leaks.
      resetCommonCaches();

      // Reset local application listeners to pre-refresh state.
      if (this.earlyApplicationListeners != null) {
         this.applicationListeners.clear();
         this.applicationListeners.addAll(this.earlyApplicationListeners);
      }

      // Switch to inactive.
      this.active.set(false);
   }
}

对Bean进行销毁处理的方法为org.springframework.beans.factory.support.DisposableBeanAdapter#destroy,实现如下:

public void destroy() {
    if (!CollectionUtils.isEmpty(this.beanPostProcessors)) {
       // 执行DestructionAwareBeanPostProcessor接口的方法
       for (DestructionAwareBeanPostProcessor processor : this.beanPostProcessors) {
          processor.postProcessBeforeDestruction(this.bean, this.beanName);
       }
    }

    if (this.invokeDisposableBean) {
       if (logger.isTraceEnabled()) {
          logger.trace("Invoking destroy() on bean with name '" + this.beanName + "'");
       }
       try {
          if (System.getSecurityManager() != null) {
             AccessController.doPrivileged((PrivilegedExceptionAction<Object>) () -> {
                ((DisposableBean) this.bean).destroy();
                return null;
             }, this.acc);
          }
          else {
             ((DisposableBean) this.bean).destroy();
          }
       }
       catch (Throwable ex) {
          if (logger.isWarnEnabled()) {
             String msg = "Invocation of destroy method failed on bean with name '" + this.beanName + "'";
             if (logger.isDebugEnabled()) {
                // Log at warn level like below but add the exception stacktrace only with debug level
                logger.warn(msg, ex);
             }
             else {
                logger.warn(msg + ": " + ex);
             }
          }
       }
    }

    if (this.invokeAutoCloseable) {
       if (logger.isTraceEnabled()) {
          logger.trace("Invoking close() on bean with name '" + this.beanName + "'");
       }
       try {
          if (System.getSecurityManager() != null) {
             AccessController.doPrivileged((PrivilegedExceptionAction<Object>) () -> {
                ((AutoCloseable) this.bean).close();
                return null;
             }, this.acc);
          }
          else {
             ((AutoCloseable) this.bean).close();
          }
       }
       catch (Throwable ex) {
          if (logger.isWarnEnabled()) {
             String msg = "Invocation of close method failed on bean with name '" + this.beanName + "'";
             if (logger.isDebugEnabled()) {
                // Log at warn level like below but add the exception stacktrace only with debug level
                logger.warn(msg, ex);
             }
             else {
                logger.warn(msg + ": " + ex);
             }
          }
       }
    }
    // 执行自定义的destry方法
    else if (this.destroyMethod != null) {
       invokeCustomDestroyMethod(this.destroyMethod);
    }
    else if (this.destroyMethodName != null) {
       Method destroyMethod = determineDestroyMethod(this.destroyMethodName);
       if (destroyMethod != null) {
          invokeCustomDestroyMethod(ClassUtils.getInterfaceMethodIfPossible(destroyMethod, this.bean.getClass()));
       }
    }
}

调用到close的调用堆栈如下:

destroy:195, DisposableBeanAdapter (org.springframework.beans.factory.support)
destroyBean:587, DefaultSingletonBeanRegistry (org.springframework.beans.factory.support)
destroySingleton:559, DefaultSingletonBeanRegistry (org.springframework.beans.factory.support)
destroySingleton:1163, DefaultListableBeanFactory (org.springframework.beans.factory.support)
destroySingletons:520, DefaultSingletonBeanRegistry (org.springframework.beans.factory.support)
destroySingletons:1156, DefaultListableBeanFactory (org.springframework.beans.factory.support)
destroyBeans:1109, AbstractApplicationContext (org.springframework.context.support)
doClose:1078, AbstractApplicationContext (org.springframework.context.support)
close:1024, AbstractApplicationContext (org.springframework.context.support)

lazy-init属性和预实例化

正如前面所述,在IoC容器的初始化过程中,主要的工作是对BeanDefinition的定位、载入、解析和注册。此时依赖注入并没有发生,依赖注入发生在应用第一次向容器索要Bean时。向容器索要Bean是通过getBean的调用来完成的,该getBean是容器提供Bean服务的最基本的接口。在前面的分析中也提到,对于容器的初始化,也有一种例外情况,就是用户可以通过设置Bean的lazy-init属性来控制预实例化的过程。这个预实例化在初始化容器时完成Bean的依赖注入。毫无疑问,这种容器的便用方式会对容器初始化的性能有一些影响,但却能够提高应用第一次取得Bean的性能。因为应用在第一次取得Bean时,依赖注入已经结束了,应用可以取得已有的Bean。

下面将从lazy-init属性配置实现的角度进行分析。对这个属性的处理也是容器refresh的一部分。在finishBeanFactoryInitialization的方法中,封装了对lazy-init属性的处理,实际的处理是在DefaultListableBeanFactory这个基本容器的preInstantiateSingletons方法中完成的。 该方法对单件Bean完成预实例化,这个预实例化的完成巧妙地委托给容器来实现。如果需要预实例化,那么就直接在这里采用getBean去触发依赖注入,与正常依赖注入的触发相比,只有触发的时间和场合不同。在这里,依赖注入发生在容器执行refresh的过程中,也就是发生在IoC容器初始化的过程中,而不像一般的依赖注入一样发生在IoC容器初始化完成以后,第一次向容器执行getBean时。

public void refresh() throws BeansException, IllegalStateException {
    synchronized (this.startupShutdownMonitor) {
       StartupStep contextRefresh = this.applicationStartup.start("spring.context.refresh");

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

          StartupStep beanPostProcess = this.applicationStartup.start("spring.context.beans.post-process");
          // Invoke factory processors registered as beans in the context.
          invokeBeanFactoryPostProcessors(beanFactory);

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

          // 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.对lazy-init属性进行处理的地方
          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();
          contextRefresh.end();
       }
    }
}

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 BeanFactoryPostProcessor
    // (such as a PropertySourcesPlaceholderConfigurer 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();
}

org.springframework.beans.factory.support.DefaultListableBeanFactory#preInstantiateSingletons的实现如下:

public void preInstantiateSingletons() throws BeansException {
    if (logger.isTraceEnabled()) {
       logger.trace("Pre-instantiating singletons in " + this);
    }

    // Iterate over a copy to allow for init methods which in turn register new bean definitions.
    // While this may not be part of the regular factory bootstrap, it does otherwise work fine.
    List<String> beanNames = new ArrayList<>(this.beanDefinitionNames);

    // Trigger initialization of all non-lazy singleton beans...
    // 在这里就开始getBean,也就是去触发Bean的依赖注入
    // 这个getBean和前面分析的触发依赖注入的过程是一样的,只是发生的地方不同。如果设置
lazy-init属性,那么这个依赖注入是发生在容器初始化结束以后,第一次向容器发出getBean时,
如果不设置1azy-init属性,那么依赖注入发生在容器初始化的过程中,会对beanDefinitionMap中所有的Bean进行依赖注入,这样在初始化过程结束以后,容器执行getBean得到的就是已经准备好的Bean,不需要进行依始注入
    for (String beanName : beanNames) {
       RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
       if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
          if (isFactoryBean(beanName)) {
             Object bean = getBean(FACTORY_BEAN_PREFIX + beanName);
             if (bean instanceof FactoryBean) {
                FactoryBean<?> factory = (FactoryBean<?>) bean;
                boolean isEagerInit;
                if (System.getSecurityManager() != null && factory instanceof SmartFactoryBean) {
                   isEagerInit = AccessController.doPrivileged(
                         (PrivilegedAction<Boolean>) ((SmartFactoryBean<?>) factory)::isEagerInit,
                         getAccessControlContext());
                }
                else {
                   isEagerInit = (factory instanceof SmartFactoryBean &&
                         ((SmartFactoryBean<?>) factory).isEagerInit());
                }
                if (isEagerInit) {
                   getBean(beanName);
                }
             }
          }
          else {
             getBean(beanName);
          }
       }
    }

    // Trigger post-initialization callback for all applicable beans...
    for (String beanName : beanNames) {
       Object singletonInstance = getSingleton(beanName);
       if (singletonInstance instanceof SmartInitializingSingleton) {
          StartupStep smartInitialize = getApplicationStartup().start("spring.beans.smart-initialize")
                .tag("beanName", beanName);
          SmartInitializingSingleton smartSingleton = (SmartInitializingSingleton) singletonInstance;
          if (System.getSecurityManager() != null) {
             AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
                smartSingleton.afterSingletonsInstantiated();
                return null;
             }, getAccessControlContext());
          }
          else {
             smartSingleton.afterSingletonsInstantiated();
          }
          smartInitialize.end();
       }
    }
}

FactoryBean的实现

getObjectForBeanInstance做了哪些处理?在getObjectForBeanInstance的实现方法中可以看到在FactoryBean中常见的getObject方法的接口,详细的实现过程如下所示。

org.springframework.beans.factory.support.AbstractBeanFactory#getObjectForBeanInstance实现如下:

protected Object getObjectForBeanInstance(
       Object beanInstance, String name, String beanName, @Nullable RootBeanDefinition mbd) {

    // Don't let calling code try to dereference the factory if the bean isn't a factory.
    // 如果这里不是对FactoryBean的调用,那么结束处理
    if (BeanFactoryUtils.isFactoryDereference(name)) {
       if (beanInstance instanceof NullBean) {
          return beanInstance;
       }
       if (!(beanInstance instanceof FactoryBean)) {
          throw new BeanIsNotAFactoryException(beanName, beanInstance.getClass());
       }
       if (mbd != null) {
          mbd.isFactoryBean = true;
       }
       return beanInstance;
    }

    // Now we have the bean instance, which may be a normal bean or a FactoryBean.
    // If it's a FactoryBean, we use it to create a bean instance, unless the
    // caller actually wants a reference to the factory.
    if (!(beanInstance instanceof FactoryBean)) {
       return beanInstance;
    }

    Object object = null;
    if (mbd != null) {
       mbd.isFactoryBean = true;
    }
    else {
       object = getCachedObjectForFactoryBean(beanName);
    }
    if (object == null) {
       // Return bean instance from factory.
       FactoryBean<?> factory = (FactoryBean<?>) beanInstance;
       // Caches object obtained from FactoryBean if it is a singleton.
       if (mbd == null && containsBeanDefinition(beanName)) {
          mbd = getMergedLocalBeanDefinition(beanName);
       }
       boolean synthetic = (mbd != null && mbd.isSynthetic());
       object = getObjectFromFactoryBean(factory, beanName, !synthetic);
    }
    return object;
}

// 从FactoryBean中得到bean
protected Object getObjectFromFactoryBean(FactoryBean<?> factory, String beanName, boolean shouldPostProcess) {
    if (factory.isSingleton() && containsSingleton(beanName)) {
       synchronized (getSingletonMutex()) {
          Object object = this.factoryBeanObjectCache.get(beanName);
          if (object == null) {
             object = doGetObjectFromFactoryBean(factory, beanName);
             // Only post-process and store if not put there already during getObject() call above
             // (e.g. because of circular reference processing triggered by custom getBean calls)
             Object alreadyThere = this.factoryBeanObjectCache.get(beanName);
             if (alreadyThere != null) {
                object = alreadyThere;
             }
             else {
                if (shouldPostProcess) {
                   if (isSingletonCurrentlyInCreation(beanName)) {
                      // Temporarily return non-post-processed object, not storing it yet..
                      return object;
                   }
                   beforeSingletonCreation(beanName);
                   try {
                      object = postProcessObjectFromFactoryBean(object, beanName);
                   }
                   catch (Throwable ex) {
                      throw new BeanCreationException(beanName,
                            "Post-processing of FactoryBean's singleton object failed", ex);
                   }
                   finally {
                      afterSingletonCreation(beanName);
                   }
                }
                if (containsSingleton(beanName)) {
                   this.factoryBeanObjectCache.put(beanName, object);
                }
             }
          }
          return object;
       }
    }
    else {
       Object object = doGetObjectFromFactoryBean(factory, beanName);
       if (shouldPostProcess) {
          try {
             object = postProcessObjectFromFactoryBean(object, beanName);
          }
          catch (Throwable ex) {
             throw new BeanCreationException(beanName, "Post-processing of FactoryBean's object failed", ex);
          }
       }
       return object;
    }
}

private Object doGetObjectFromFactoryBean(FactoryBean<?> factory, String beanName) throws BeanCreationException {
    Object object;
    try {
       if (System.getSecurityManager() != null) {
          AccessControlContext acc = getAccessControlContext();
          try {
             object = AccessController.doPrivileged((PrivilegedExceptionAction<Object>) factory::getObject, acc);
          }
          catch (PrivilegedActionException pae) {
             throw pae.getException();
          }
       }
       else {
          // 这里调用factory的getObject方法从FactoryBean中得到Bean
          object = factory.getObject();
       }
    }
    catch (FactoryBeanNotInitializedException ex) {
       throw new BeanCurrentlyInCreationException(beanName, ex.toString());
    }
    catch (Throwable ex) {
       throw new BeanCreationException(beanName, "FactoryBean threw exception on object creation", ex);
    }

    // Do not accept a null value for a FactoryBean that's not fully
    // initialized yet: Many FactoryBeans just return null then.
    if (object == null) {
       if (isSingletonCurrentlyInCreation(beanName)) {
          throw new BeanCurrentlyInCreationException(
                beanName, "FactoryBean which is currently in creation returned null from getObject");
       }
       object = new NullBean();
    }
    return object;
}

这里返回的已经是作为工厂的FactoryBean生产的产品,而不是FactoryBean本身。这种FactoryBean的机制可以为我们提供一个很好的封装机制,比如封装Proxy、RMI、JNDI等。通过对FactoryBean实现过程的原理进行分析,相信读者会对getObject方法有很深刻的印象,这个方法就是主要的FactoryBean的接口,需要实现特定的工厂的生产过程,至于这个生产过程是怎样和IoC容器整合的,就是在上面分析的内容。

对比两者的实现,可以看到FactoryBean类似于AbstractFactory抽象工厂getObjectForBeanInstance()方法类似于createProductA()这样的生产接口,而具体的FactoryBean实现,如TransactionProxyFactoryBean,就是具体的工厂实现,其生成出的 TransactionProxy就是抽象工厂模式中对应的ConcreteProduct。有了抽象工厂设计模式 的参考和对比,对FactoryBean的设计和实现就更容易理解一些了。

BeanPostProcessor的实现

BeanPostProcessor是使用IoC容器时经常会遇到的一个特性,这个Bean的后置处理器是一个监听器,它可以监听容器触发的事件。将它向IoC容器注册后,容器中管理的Bean具备了接收IoC容器事件回调的能力。BeanPostProcessor的使用非常简单,只需要通过设计一个具体的后置处理器来实现。同时,这个具体的后置处理器需要实现接口类BeanPostProcessor,然后设置到XML的Bean配置文件中。这个BeanPostProcessor是一个接口类,它有两个接口方法,一个是postProcessBeforeInitialization,在Bean的初始化前提供回调人口;一个是postProcessAfterInitialization,在Bean的初始化后提供回调入口,这两个回调的触发都是和容器管理Bean的生命周期相关的。这两个回调方法的参数都是一样的,分别是Bean的实例化对象和 Bean的名字。BeanPostProcessor为具体的处理提供基本的回调输入,如下代码所示。

public interface BeanPostProcessor {
    @Nullable
    default Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
       return bean;
    }

    @Nullable
    default Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
       return bean;
    }
}

autowiring的实现

在前面对IoC容器实现原理的分析中,一直是通过BeanDefinition的属性值和构造函数以显式的方式对Bean的依赖关系进行管理的。在Spring中,相对这种显式的依赖管理方式:IoC容器还提供了自动依赖装配的方式,为应用使用容器提供更大的方便。在自动装配中,不需要对Bean属性做显式的依赖关系声明,只需要配置好autowiring属性,IoC容器会根据这个属性的配置,使用反射自动查找属性的类型或者名字,然后基于属性的类型或名字来自动匹配loC容器中的Bean,从而自动地完成依赖注入。

org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#populateBean中的实现如下:

int resolvedAutowireMode = mbd.getResolvedAutowireMode();
if (resolvedAutowireMode == AUTOWIRE_BY_NAME || resolvedAutowireMode == AUTOWIRE_BY_TYPE) {
    MutablePropertyValues newPvs = new MutablePropertyValues(pvs);
    // Add property values based on autowire by name if applicable.
    if (resolvedAutowireMode == AUTOWIRE_BY_NAME) {
       autowireByName(beanName, mbd, bw, newPvs);
    }
    // Add property values based on autowire by type if applicable.
    if (resolvedAutowireMode == AUTOWIRE_BY_TYPE) {
       autowireByType(beanName, mbd, bw, newPvs);
    }
    pvs = newPvs;
}

在对autowiring类型做了一些简单的逻辑判断以后,通过调用autowireByName和autowireByType来完成自动依赖装配。以autowireByName为例子来看看容器的自动依赖装配功能是怎样实现的。对autowireByName来说,它首先需要得到当前Bean的属性名,这些属性名已经在BeanWrapper和BeanDefinition中封装好了,然后是对这一系列属性名进行匹配的过程。在匹配的过程中,因为已经有了属性的名字,所以可以直接使用属性名作为Bean名字向容器索取Bean,这个getBean会触发当前Bean的依赖Bean的依赖注入,从而得到属性对应的依赖Bean。在执行完这个getBean后,把这个依赖Bean注入到当前Bean的属性中去,这样就完成了通过这个依赖属性名自动完成依赖注入的过程。

org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#autowireByName的实现如下:

protected void autowireByName(
       String beanName, AbstractBeanDefinition mbd, BeanWrapper bw, MutablePropertyValues pvs) {

    String[] propertyNames = unsatisfiedNonSimpleProperties(mbd, bw);
    for (String propertyName : propertyNames) {
       if (containsBean(propertyName)) {
          Object bean = getBean(propertyName);
          pvs.add(propertyName, bean);
          registerDependentBean(propertyName, beanName);
          if (logger.isTraceEnabled()) {
             logger.trace("Added autowiring by name from bean name '" + beanName +
                   "' via property '" + propertyName + "' to bean named '" + propertyName + "'");
          }
       }
       else {
          if (logger.isTraceEnabled()) {
             logger.trace("Not autowiring property '" + propertyName + "' of bean '" + beanName +
                   "' by name: no matching bean found");
          }
       }
    }
}

Bean对IOC容器的感知

容器管理的Bean一般不需要了解容器的状态和直接使用容器,但在某些情况下,是需要在Bean中直接对IoC容器进行操作的,这时候,就需要在Bean中设定对容器的感知。Spring IoC容器也提供了该功能,它是通过特定的aware接口来完成的。aware接口有以下这些: (1)BeanNameAware,可以在Bean中得到它在IoC容器中的Bean实例名称。 (2)BeanFactoryAware,可以在Bean中得到Bean所在的IoC容器,从而直接在Bean中使用 IoC容器的服务。 (3)ApplicationContextAware,可以在Bean中得到Bean所在的应用上下文,从而直接在 Bean中使用应用上下文的服务。 (4)MessageSourceAware,在Bean中可以得到消息源。 (5)ApplicationEventPublisherAware,在Bean中可以得到应用上下文的事件发布器,从而 可以在Bean中发布应用上下文的事件。 (6)ResourceLoaderAware,在Bean中可以得到ResourceLoader,从而在Bean中使用 ResourceLoader加载外部对应的Resource资源。

在设置Bean的属性之后,调用初始化回调方法之前,Spring会调用aware接口中的setter 方法。以ApplicationContextAware为例,分析对应的设计和实现。这个接口定义得很简单。

public interface ApplicationContextAware extends Aware {
    void setApplicationContext(ApplicationContext applicationContext) throws BeansException;

}

这个对setApplicationContext方法的回调是由容器自动完成的。可以看到,一个ApplicationContextAwareProcessor作为BeanPostProcessor的实现,对一系列的aware回调进行了调用,比如对ResourceLoaderAware接口的调用,对ApplicationEventPublisherAware接口的调用,以及对MessageSourceAware和ApplicationContextAware的接口调用等。

class ApplicationContextAwareProcessor implements BeanPostProcessor {

    private final ConfigurableApplicationContext applicationContext;

    private final StringValueResolver embeddedValueResolver;

    public ApplicationContextAwareProcessor(ConfigurableApplicationContext applicationContext) {
       this.applicationContext = applicationContext;
       this.embeddedValueResolver = new EmbeddedValueResolver(applicationContext.getBeanFactory());
    }

    @Override
    @Nullable
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
       if (!(bean instanceof EnvironmentAware || bean instanceof EmbeddedValueResolverAware ||
             bean instanceof ResourceLoaderAware || bean instanceof ApplicationEventPublisherAware ||
             bean instanceof MessageSourceAware || bean instanceof ApplicationContextAware ||
             bean instanceof ApplicationStartupAware)) {
          return bean;
       }

       AccessControlContext acc = null;

       if (System.getSecurityManager() != null) {
          acc = this.applicationContext.getBeanFactory().getAccessControlContext();
       }

       if (acc != null) {
          AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
             invokeAwareInterfaces(bean);
             return null;
          }, acc);
       }
       else {
          invokeAwareInterfaces(bean);
       }

       return bean;
    }

    private void invokeAwareInterfaces(Object bean) {
       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 ApplicationStartupAware) {
          ((ApplicationStartupAware) bean).setApplicationStartup(this.applicationContext.getApplicationStartup());
       }
       if (bean instanceof ApplicationContextAware) {
          ((ApplicationContextAware) bean).setApplicationContext(this.applicationContext);
       }
    }

}

而作为依赖注入的一部分,postProcessBeforelnitialization会在initializeBean的实现过程 中被调用,从而实现对aware接口的相关注入。