栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

Spring IOC(四):相关特性

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

Spring IOC(四):相关特性

参考书籍:《Spring技术内幕》

系列文章

Spring IOC(一):概述

Spring IOC(二):初始化

Spring IOC(三):依赖注入

Spring IOC(四):相关特性

5 容器其他相关特性的设计与实现

下面对容器的一些其他相关特性的设计原理也进行简要的分析。这些特性都是在使用loC容器的时候会经常遇到的。

5.1 ApplicationContext和Bean的初始化及销毁

对于BeanFactory, 特别是ApplicationContext, 容器自身也有一个初始化和销毁关闭的过程。下面详细看看在这两个过程中,应用上下文完成了什么,可以让我们更多地理解应用上下文的工作,容器初始化和关闭过程可以简要地通过下图来表现。

从图中可以看到,对ApplicationContext启动的过程是在AbstractApplicationcontext中实现的,在使用应用上下文时需要做一些准备工作,这些准备工作在prepareBeanFactory()方法中实现。在这个方法中,为容器配置了ClassLoader, PropertyEditor和BeanPostProcessor等,从而为容器的启动做好了必要的准备工作。

//这个方法在refresh()函数中在创建容器之后调用
 
 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逐个关闭,最后关闭容器自身。

@SuppressWarnings("deprecation")
 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 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);
     }
 }

以上是容器的初始化和销毁的设计与实现。

在应用开发中,常常需要执行一些特定的初始化工作,这些工作都是相对比较固定的,比如建立数据库连接,打开网络连接等,同时,在结束服务时,也有一些相对固定的销毁工作需要执行。为了便于这些工作的设计,Spring IoC容器提供了相关的功能,可以让应用定制Bean的初始化和销毁过程。

容器的实现是通过IoC管理Bean的生命周期来实现的。Spring IoC容器在对Bean的生命周期进行管理时提供了Bean生命周期各个时间点的回调,在分析Bean初始化和销毁过程的设计之前,介绍一下loC容器中的Bean生命周期。

  • Bean实例的创建
  • 为Bean实例设置属性
  • 初始化回调
  • 应用可以通过IOC容器使用Bean
  • 销毁回调

Bean的初始化方法调用是在doCreateBean()中调用的,具体初始化内容的逻辑实现是在initializeBean()方法中实现的:

//AbstractAutowireCapableBeanFactory类中: 在doCreateBean()方法中被调用,Bean实例创建后并且为Bean实例设置属性之后被调用
 protected Object initializeBean(String beanName, Object bean, @Nullable RootBeanDefinition mbd) {
     if (System.getSecurityManager() != null) {
         AccessController.doPrivileged((PrivilegedAction) () -> {
             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;
 }
 // 在调用初始化方法之前,调用一系列的aware接口实现,把相关的BeanName,BeanClassLoader,以及BeanFactoy注入到Bean中去。
 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);
         }
     }
 }
 

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

protected void invokeInitMethods(String beanName, Object bean, @Nullable RootBeanDefinition mbd)
     throws Throwable {
 
     boolean isInitializingBean = (bean instanceof InitializingBean);
     if (isInitializingBean && (mbd == null || !mbd.isExternallyManagedInitMethod("afterPropertiesSet"))) {
         if (logger.isTraceEnabled()) {
             logger.trace("Invoking afterPropertiesSet() on bean with name '" + beanName + "'");
         }
         if (System.getSecurityManager() != null) {
             try {
                 AccessController.doPrivileged((PrivilegedExceptionAction) () -> {
                     ((InitializingBean) bean).afterPropertiesSet();
                     return null;
                 }, getAccessControlContext());
             }
             catch (PrivilegedActionException pae) {
                 throw pae.getException();
             }
         }
         else {
             //afterPropertiesSet()可以在这个方法中写自定义的逻辑对Bean进行处理
             ((InitializingBean) bean).afterPropertiesSet();
         }
     }
 
     if (mbd != null && bean.getClass() != NullBean.class) {
         String initMethodName = mbd.getInitMethodName();
         if (StringUtils.hasLength(initMethodName) &&
             !(isInitializingBean && "afterPropertiesSet".equals(initMethodName)) &&
             !mbd.isExternallyManagedInitMethod(initMethodName)) {
             invokeCustomInitMethod(beanName, bean, mbd);
         }
     }
 }
 

最后,还会看到判断Bean是否配置有initMethod,如果有,那么通过invokeCustomInitMethod方法来直接调用,最终完成Bean的初始化。

protected void invokeCustomInitMethod(String beanName, Object bean, RootBeanDefinition mbd)
     throws Throwable {
 
     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);
 
     if (System.getSecurityManager() != null) {
         AccessController.doPrivileged((PrivilegedAction) () -> {
             ReflectionUtils.makeAccessible(methodToInvoke);
             return null;
         });
         try {
             AccessController.doPrivileged((PrivilegedExceptionAction)
                                           () -> 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();
         }
     }
 }
 

在这个对initMethod的调用中,可以看到首先需要得到Bean定义的initMethod,然后通过JDK的反射机制得到Method对象,直接调用在Bean定义中声明的初始化方法。

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

//AbstractApplicationContext类中:关闭容器的方法
 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.
         //销毁上下文的BeanFactory中所有缓存的单例对象。
         destroyBeans();
 
         // Close the state of this context itself.
         closeBeanFactory();
 
         // Let subclasses do some final clean-up if they wish...
         onClose();
 
         // 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);
     }
 }

其中的destroy方法,对Bean进行销毁处理。最终在DisposableBeanAdapter类中可以看到destroy方法的实现。

这里可以看到对Bean的销毁过程,首先对postProcessBeforeDestruction进行调用,然后调用Bean的destroy()方法,最后是对Bean的自定义销毁方法的调用,整个过程和前面的初始化过程很类似。

@Override
 public void destroy() {
     if (!CollectionUtils.isEmpty(this.beanPostProcessors)) {
         for (DestructionAwareBeanPostProcessor processor : this.beanPostProcessors) {
             //如果这个Bean有bean后置处理器,那么将后置处理器销毁
             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) () -> {
                     ((DisposableBean) this.bean).destroy();
                     return null;
                 }, this.acc);
             }
             else {
                 //执行bean实现DisposableBean接口实现的方法
                 ((DisposableBean) this.bean).destroy();
             }
         }
         catch (Throwable ex) {
             String msg = "Invocation of destroy method failed on bean with name '" + this.beanName + "'";
             if (logger.isDebugEnabled()) {
                 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) () -> {
                     ((AutoCloseable) this.bean).close();
                     return null;
                 }, this.acc);
             }
             else {
                 ((AutoCloseable) this.bean).close();
             }
         }
         catch (Throwable ex) {
             String msg = "Invocation of close method failed on bean with name '" + this.beanName + "'";
             if (logger.isDebugEnabled()) {
                 logger.warn(msg, ex);
             }
             else {
                 logger.warn(msg + ": " + ex);
             }
         }
     }
     else if (this.destroyMethod != null) {
         //调用Bean自定义的销毁方法
         invokeCustomDestroyMethod(this.destroyMethod);
     }
     else if (this.destroyMethodName != null) {
         Method methodToInvoke = determineDestroyMethod(this.destroyMethodName);
         if (methodToInvoke != null) {
             invokeCustomDestroyMethod(ClassUtils.getInterfaceMethodIfPossible(methodToInvoke));
         }
     }
 }
 
5.2 lazy-init属性和预实例化 

依赖注入发生在应用第一次向容器索要Bean时。向容器索要Bean是通过getBean的调用来完成的,该getBean是容器提供Bean服务的最基本的接口。在前面的分析中也提到,对于容器的初始化,也有一种例外情况,就是用户可以通过设置Bean的lazy-init属性来控制预实例化的过程。

在上下文的初始化过程,也就是refresh中的代码实现,可以看到预实例化是整个refresh初始化IoC容器的一个步骤。在AbstractApplicationContext中看一下refresh的实现。

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

@Override
 public void refresh() throws BeansException, IllegalStateException {
     synchronized (this.startupShutdownMonitor) {
         StartupStep contextRefresh = this.applicationStartup.start("spring.context.refresh");
         prepareRefresh();
         // 调用自己的方法,先让子类启动容器,然后返回容器
         ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
         prepareBeanFactory(beanFactory);
         try {
             // 设置BeanFactory的后置处理器
             postProcessBeanFactory(beanFactory);
             StartupStep beanPostProcess = this.applicationStartup.start("spring.context.beans.post-process");
             // Invoke factory processors registered as beans in the context.
             //调用BeanFactory的后处理器,这些后处理器是在Bean定义中向容器注册的
             invokeBeanFactoryPostProcessors(beanFactory);
             // Register bean processors that intercept bean creation.
             //注册Bean的后处理器,在Bean创建过程中调用
             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.
             //初始化其他的特殊Bean
             onRefresh();
             // Check for listener beans and register them.
             //检查监听Bean并且将这些Bean向容器注册
             registerListeners();
             // Instantiate all remaining (non-lazy-init) singletons.
             //实例化所有的(non-lazy-init)单例,是对lazy-init属性进行处理的地方
             finishBeanFactoryInitialization(beanFactory);
             finishRefresh();
         }
         catch (BeansException ex) {
             if (logger.isWarnEnabled()) {
                 logger.warn("Exception encountered during context initialization - " +
                             "cancelling refresh attempt: " + ex);
             }
             destroyBeans();
             cancelRefresh(ex);
             throw ex;
         }
         finally {
             resetCommonCaches();
             contextRefresh.end();
         }
     }
 }
 
 // 进行具体的处理
 protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {
     // 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.
     //这里调用的preInstantiateSingletons()方法由DefaultListableBeanFactory实现进行具体的依赖注入
     beanFactory.preInstantiateSingletons();
 }
 
 @Override
 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 beanNames = new ArrayList<>(this.beanDefinitionNames);
 
     // Trigger initialization of all non-lazy singleton beans...
     // 在这里开始getBean,也就是触发Bean的依赖注入,这个getBean和前面分析的触发依赖注入的过程是一样的,只是发生的地方不同,
     // 如果不设置lazy-init属性,那么这个依赖注入是发生在容器初始化过程中,会对beanDefinitionMap中所有的Bean进行依赖注入,
     // 这样在初始化过程结束以后,容器执行getBean(),得到的就是已经准备好的Bean,不需要进行依赖注入。
     for (String beanName : beanNames) {
         RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
         if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
             //判断这个要初始化的Bean是否是FactoryBean
             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) ((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...
     //触发所有适用bean的初始化后回调
     for (String beanName : beanNames) {
         Object singletonInstance = getSingleton(beanName);
         if (singletonInstance instanceof SmartInitializingSingleton) {
             StartupStep smartInitialize = this.getApplicationStartup().start("spring.beans.smart-initialize")
                 .tag("beanName", beanName);
             SmartInitializingSingleton smartSingleton = (SmartInitializingSingleton) singletonInstance;
             if (System.getSecurityManager() != null) {
                 AccessController.doPrivileged((PrivilegedAction) () -> {
                     smartSingleton.afterSingletonsInstantiated();
                     return null;
                 }, getAccessControlContext());
             }
             else {
                 smartSingleton.afterSingletonsInstantiated();
             }
             smartInitialize.end();
         }
     }
 }
 

可以通过lazy-init属性来对整个IoC容器的初始化和依赖注入过程进行一些简单的控制。这些控制是可以由容器的使用者来决定的,具体来说,可以通过在BeanDefinition中设置lazy-init属性来进行控制。

设置了lazy-init属性为true,那么这个Bean就在使用到的时候getBean()实例化,如果没有这个属性或者这个属性为false,那么这个Bean就在容器初始化过程中进行实例化,具体的实例化还是执行getBean()。

5.3 FactoryBean的实现

什么是FactoryBean

先看一下FactoryBean接口的定义:

public interface FactoryBean {
    String OBJECT_TYPE_ATTRIBUTE = "factoryBeanObjectType";
  
    @Nullable
    T getObject() throws Exception;

    @Nullable
    Class getObjectType();
  
    default boolean isSingleton() {
        return true;
    }
}

下面来介绍常见的FactoryBean是怎样实现的。这些FactoryBean为应用生成需要的对象。

这些对象往往是经过特殊处理的,如ProxyFactoryBeo这样的特殊Bean。FactoryBean的生产特性是在getBean()中起作用的,在getBean()中创建一个Bean之后总会调用这个方法,看下面的调用:

//AbstractBeanFactory
// 这里的getObjectForBeanInstance()完成的是FactoryBean的相关处理,以取得FactoryBean的生产结果
beanInstance = getObjectForBeanInstance(sharedInstance, name, beanName, null);

看一下FactoryBean的实现:

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());
        // 从FactoryBean中得到bean
        object = getObjectFromFactoryBean(factory, beanName, !synthetic);
    }
    return object;
}

protected Object getObjectFromFactoryBean(FactoryBean factory, String beanName, boolean shouldPostProcess) {
    // FactoryBean中Bean是一个单例的
    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) factory::getObject, acc);
            }
            catch (PrivilegedActionException pae) {
                throw pae.getException();
            }
        }
        else {
            //获取FactoryBean中的对象
            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容器整合的,就是在上面分析的内容。

5.4 BeanPostProcessor的实现

BeanPostProcessor是使用IoC容器时经常会遇到的一个特性,这个Bean的后置处理器是一个监听器,它可以监听容器触发的事件。将它向IoC容器注册后,容器中管理的Bean具备了接收IoC容器事件回调的能力。

BeanPostProcessor的使用非常简单,只需要实现接口类BeanPostProcessor,然后设置到XML的Bean配置文件中。

这个BeanPostProcessor是一个接口类,它有两个接口方法,一个是postProcessBeforeInitialization(), 在Bean的初始化前提供回调入口:一个是postProcessAfterlnitialization(), 在Bean的初始化后提供回调入口,这两个回调的触发都是和容器管理Bean的生命周期相关的。这两个回调方法的参数都是一样的,分別是Bean的实例化对象和Bean的名字。

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

}

postProcessBeforeInitialization() 和postProcessAfterInitialization()是在 populateBean() 完成之后 initializeBean()方法中调用的。

在前面对IoC的依赖注人进行分析时,对这个populateBean()有过分析,这个方法实际上完成了Bean的依赖注
入 。 在 容 器 中 建 立 B e a n 的 依 赖 关 系 , 是 容 器 功 能 实 现 的 一 个 很 重 要 的 部 分 。 节选
doCreateBean() 中的代码:

Object exposedObject = bean;
try {
    // 属性注入
    populateBean(beanName, mbd, instanceWrapper);
    //在完成对Bean的生成和依赖注入以后,开始对Bean初始化这个初始化过程包含了对后置处理器中的两个方法的回调
    exposedObject = initializeBean(beanName, exposedObject, mbd);
}

具体的初始化过程也是loC容器完成依赖注人的一个重要部分、在initializeBean方法中,需要使用Bean的名字,完成依赖注人以后的Bean对象,以及这个Bean对应的BeanDefinition。

在这些输入的帮助下,完成Bean的初始化工作,这些工作包括为类型是BeanNameAware的Bean设置Bean的名字,类型是BeanClassLoaderAware的Bean设置类装载器,类型是BeanFactoryAware的Bean设置自身所在的IoC容器以供回调使用,还有对postProcessBeforelnitialization()/postProccss AfterInitialization() 的回调和初始化属性 init-method 的处理等。经过这一系列的初始化处理之后,得到的结果就是可以正常使用的由IoC容器托管的Bean具体的实现过程如代码:

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

    Object wrappedBean = bean;
    if (mbd == null || !mbd.isSynthetic()) {
        //BeanPostProcessors后置处理器,postProcessorsBeforeInitialization执行
        wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
    }

    try {
        //调用Bean的初始化方法,这个初始化方法是在BeanDefinition中通过定义init-method属性指定的
        //同时,如果Bean实现了 InitializingBean接口,那么这个Bean的afterPropertiesSet实现也会被调用
        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()) {
        //BeanPostProcessors后置处理器,postProcessorsAfterInitialization执行
        wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
    }

    return wrappedBean;
}

@Override
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;
}

@Override
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定义的init-method方法调用,与IoC容器对Bean的管理有机结合起来了、对这个特性的理解,离不开对loC容器基本实现原理的理解。

下面再分析一T容器的autowiring特性是怎样实现的。

5.5 autowiring自动装配的实现

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

从autowiring使用上可以知道,这个autowiring属性在对Bean属性进行依赖注入时起作用。

对Bean属性依赖注人的实现原理,在前面已经做过分析。回顾那部分内容,不难发现,对autowirng属性进行处理,从而完成对Bean属性的自动依赖装配,是在popuateBean()中实现的。

查看AbstractAutowireCapableBeanFactory 的 populateBean() 方法中与 autowiring 实现相关的部分代码,可以清楚地看到这个特性在容器中实现的人口,也就是说,对属性autowiring的处理是populateBean()处理过程的一个部分。在populateBean()的实现中,在处理一般的Bean之前,先对autowiring厲性进行处理。如果当前的Bean配置了autowire_by_name和autowire_by_type属性,那么调用相应的autowireByName()方法和autowireByType()方法。这两个方法很巧妙地应用了IoC容器的特性。例如,对于autowire_by_name,它首先通过反射机制从当前Bean中得到需要注入的属性名,然后使用这个属性名向容器申请与之同名的Bean,这样实际又触发了另一个Bean的生成和依赖注入的过程。实现过程如代码:

//在AbstractAutoWireCableBeanFactory类中的populateBean()方法中:
//开始进行依赖注入过程,先处理Autowire的注入,可以根据Bean的名字或者类型
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的属性中去,这样就完成了通过这个依赖属性名自动完成依赖注入的过程。

autowireByType的实现和autowireByName的实现过程是非常类似的。autowiring的实现如代码:

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

    String[] propertyNames = unsatisfiedNonSimpleProperties(mbd, bw);
    for (String propertyName : propertyNames) {
        if (containsBean(propertyName)) {
            //使用取得的当前Bean的属性名作为Bean的名字,向loC容器索取Bean,然后把从容器得到的Bean设置到当前Bean的属性中去
            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");
            }
        }
    }
}
5.6 Bean的依赖检查

在使用Spring的时候,如果应用设计比较复杂,那么在这个应用中,IoC管理的Bean的个数可能非常多,这些Bean之间的相互依赖关系也会非常复杂。在一般情况下,Bean的依赖注入是在应用第一次向容器索取Bean的时候发生,在这个时候,不能保证注入一定能够成功,如果需要重新检査这些依赖关系的有效性,会是一件很繁琐的事情。

为了解决这样的问题,在Spring IoC容器中,设计了一个依赖检査特性,通过它,Spring可以帮助应用检查是否所
有的属性都已经被正确设置。在具体使用的时候,应用只需要在Bean定义中设置dependency-check属性来指定依赖检査模式即可,这里可以将属性设置为none, simple、object, all四种模式,默认的模式是none。

如果对检査模式进行了设置,通过下面的分析,可以更好地理解这个特性的便用。具体的实现代码是在AbstractAutowireCapableBeanFactory实现createBean()的过程中完成的,在这个过程中,会对Bean的Dependencies属性进行检査,如果发现不满足要求,就会抛出异常通知应用。

//在AbstractAutowireCapableBeanFactory类中的populate()方法中
if (needsDepCheck) {
    if (filteredPds == null) {
        filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
    }
    checkDependencies(beanName, mbd, filteredPds, pvs);
}
//检查依赖
protected void checkDependencies(
    String beanName, AbstractBeanDefinition mbd, PropertyDescriptor[] pds, @Nullable PropertyValues pvs)
    throws UnsatisfiedDependencyException {

    int dependencyCheck = mbd.getDependencyCheck();
    for (PropertyDescriptor pd : pds) {
        if (pd.getWriteMethod() != null && (pvs == null || !pvs.contains(pd.getName()))) {
            boolean isSimple = BeanUtils.isSimpleProperty(pd.getPropertyType());
            boolean unsatisfied = (dependencyCheck == AbstractBeanDefinition.DEPENDENCY_CHECK_ALL) ||
                (isSimple && dependencyCheck == AbstractBeanDefinition.DEPENDENCY_CHECK_SIMPLE) ||
                (!isSimple && dependencyCheck == AbstractBeanDefinition.DEPENDENCY_CHECK_OBJECTS);
            if (unsatisfied) {
                throw new UnsatisfiedDependencyException(mbd.getResourceDescription(), beanName, pd.getName(),
                                                         "Set this property value or disable dependency checking for this bean.");
            }
        }
    }
}
5.7 Bean对loC容器的感知

容器管理的Bean-殷不需要了解容器的状态和直接使用容器,但在某些情况了,是需要在Bean中直接対loC容器进行操作的,这时候,就需要在Bean中设定对容器的感知。Spring loC容器也提供了该功能,它是通过特定的aware接口来完成的。aware接口有以下这些:

  • BeanNameAware,可以在Bean中得到它在IoC容器中的Bean实例名称。
  • BeanFactoryAware, 4以在Bean中得到Bean所在的IoC容器,从而直接在Bean中使用loC容器的服务。
  • ApplicationContextAware,可以在Bean屮得到Bean所在的应用上下文,从而直接在Bean中使用应用上下文的服务。
  • MessageSourceAware,在Bean中可以得到消息源。
  • ApplicationEventPublisherAware,在Bean中可以得到应用上下文的事件发布器,从而可以在Bean中发布应用上下文的事件。
  • ResourceLoaderAware,在Bean中可以得到ResourceLoader,从而在Bean中使用ResourceLoader加载外部对应的Resource资源。

在设置Bean的属性之后,调用初始化回调方法之前,Spring会调用aware接口中的setter方法。

一个ApplicationContextAwareProcessor作为BeanPostProcessor的实现,对一系列的aware回调进行
了调用。比如对ResourceLoaderAware接口的调用,对ApplicationEventPublisherAware接口的调用,以及对MessageSourceAware和AppIicationContextAware的接口调用等。

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) () -> {
                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接口的相关注人。

ApplicationContextAwareProcessor是什么时候添加到容器中的呢?

执行refresh方法中,会执行容器的初始化方法prepareBeanFactory方法,在这个方法中会添加一些Bean到容器中,其中就包括ApplicationContextAwareProcessor这个Bean。

protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory) {
    // 设置 BeanFactory 的类加载器,我们知道 BeanFactory 需要加载类,也就需要类加载器,
    // 这里设置为加载当前 ApplicationContext 类的类加载器
    beanFactory.setBeanClassLoader(getClassLoader());

    // 设置 BeanexpressionResolver
    beanFactory.setBeanexpressionResolver(new StandardBeanexpressionResolver(beanFactory.getBeanClassLoader()));
    // 
    beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this, getEnvironment()));

    // 添加一个 BeanPostProcessor,这个 processor 比较简单:
    // 实现了 Aware 接口的 beans 在初始化的时候,这个 processor 负责回调,
    // 这个我们很常用,如我们会为了获取 ApplicationContext 而 implement ApplicationContextAware
    // 注意:它不仅仅回调 ApplicationContextAware,
    //   还会负责回调 EnvironmentAware、ResourceLoaderAware 等,看下源码就清楚了
    beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));

    // 下面几行的意思就是,如果某个 bean 依赖于以下几个接口的实现类,在自动装配的时候忽略它们,
    // Spring 会通过其他方式来处理这些依赖。
    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.registerResolvableDependency(BeanFactory.class, beanFactory);
    beanFactory.registerResolvableDependency(ResourceLoader.class, this);
    beanFactory.registerResolvableDependency(ApplicationEventPublisher.class, this);
    beanFactory.registerResolvableDependency(ApplicationContext.class, this);

    // 这个 BeanPostProcessor 也很简单,在 bean 实例化后,如果是 ApplicationListener 的子类,
    // 那么将其添加到 listener 列表中,可以理解成:注册 事件监听器
    beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(this));

    // 这里涉及到特殊的 bean,名为:loadTimeWeaver,这不是我们的重点,忽略它
    // tips: ltw 是 AspectJ 的概念,指的是在运行期进行织入,这个和 Spring AOP 不一样,
    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()));
    }

    

    // 如果没有定义 "environment" 这个 bean,那么 Spring 会 "手动" 注册一个
    if (!beanFactory.containsLocalBean(ENVIRONMENT_BEAN_NAME)) {
        beanFactory.registerSingleton(ENVIRONMENT_BEAN_NAME, getEnvironment());
    }
    // 如果没有定义 "systemProperties" 这个 bean,那么 Spring 会 "手动" 注册一个
    if (!beanFactory.containsLocalBean(SYSTEM_PROPERTIES_BEAN_NAME)) {
        beanFactory.registerSingleton(SYSTEM_PROPERTIES_BEAN_NAME, getEnvironment().getSystemProperties());
    }
    // 如果没有定义 "systemEnvironment" 这个 bean,那么 Spring 会 "手动" 注册一个
    if (!beanFactory.containsLocalBean(SYSTEM_ENVIRONMENT_BEAN_NAME)) {
        beanFactory.registerSingleton(SYSTEM_ENVIRONMENT_BEAN_NAME, getEnvironment().getSystemEnvironment());
    }
}
6 总结

关于容器的基本工作原理,就先讲解这么多了,可以大致整理出以下几个方面:

  • BeanDefinition的定位。对IoC容器来说,它为管理POJO之间的依赖关系提供了帮助,但也要依据Spring的定义规则提供Bean定义信息。我们可以使用各种形式的Bean定义信息,其中比较熟悉和常用的是使用XML的文件格式。在Bean定义方面,Spring为用户提供了很大的灵活性。在初始化loC容器的过程中,首先需要定位到这些有效的Bean定义信息,这里Spring使用Resource接口来统一这些Bean定义信息,而这个定位由ResourceLoader来完成。如果使用上下文,ApplicationContext本身就为客户提供了定位的功能。因为上下文本身就是DefaultResourceLoader的子类。如果使用基本的BeanFactory作为IoC容器,需要做的额外工作就是为BeanFactory指定相应的Resource来完成Bean信息的定位。
  • 容器的初始化。在使用上下文时,需要一个对它进行初始化的过程,完成初始化以后,这个IoC容器才是可用的。这个过程的入口是在refresh中实现的,这个refresh相当于容器的初始化函数。在初始化过程中,比较重要的部分是对BeanDefinition信息的载入和注册工作。相当于在IoC容器中需要建立一个BeanDefinition定义的数据映像,Spring为了达到载入的灵活性,把载入的功能从IoC容器中分离出来,由**BeanDefinitionReader 来完成Bean定义信息的读取、解析和IoC容器内部BeanDefinition的建立**。在DefaultListableBeanFactory中,这些BeanDefinition被维护在一个ConcurrentHashmap中,以后的IoC容器对Bean的管理和操作就是通过这些BeanDefinition来完成的。

在容器初始化完成以后,IoC容器的使用就准备好了,但这时只是在IoC容器内部建立了BeanDefinition,具体的依赖关系还没有注入。在客户第一次向IoC容器请求Bean时,IoC容器对相关的Bean依赖关系进行注入。如果需要提前注入,客户可以通过lazy-init属性进行预实例化,这个预实例化是上下文初始化的一部分,起到提前完成依赖注入的控制作用D在依赖注入完成以后,IoC容器就会保持这些具备依赖关系的Bean供客户直接使用。这时可以通
过getBean来取得Bean,这些Bean不是简单的Java对象,而是已经包含了对象之间依赖关系的Bean,尽管这些依赖注入的过程对用户来说是不可见的。

在对IoC容器的分析中,重点讲解了 BeanFactory和ApplicationContext体系、ResourceLoader。refresh初始化、容器的loadBeanDefinition和注册、容器的依赖注入、预实例化和FactoryBean的工作原理,等等。通过对这些实现过程的深人分析,我们可以初步了解IoC容器的基本工作原理和它的基本特性的实现思路,了解了IoC容器的基本实现原理后,我们对容器的其他特性的实现原理也进行了分析。这些特性包括init-lazy预实例化、BeanFactory,Bean后置处理器以及autowiring特性的实现。这些特性对我们更灵活地使用IoC容器有很大的帮助。

转载请注明:文章转载自 www.mshxw.com
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号