zoukankan      html  css  js  c++  java
  • Spring IOC-基于XML配置的容器

    Spring IOC-基于XML配置的容器

    我们先分析一下AbstractXmlApplicationContext这个容器的加载过程。

    AbstractXmlApplicationContext的老爸是AbstractRefreshableApplicationContext

    它老爸是AbstractApplicationContext的两个儿子之一。

    1. 开始

    从一张关系图开始:

    demo中使用了ClassPathXmlApplicationContext,然后还有它旁边的兄弟FileSystemXmlApplicationContext,它们俩都是从xml配置文件加载配置的

    除了这两个之外还有一个AnnotationConfigApplicationContext

    2. 源码分析

    public class ClassPathXmlApplicationContext extends AbstractXmlApplicationContext {
      //配置文件数组
      private Resource[] configResources;
    
      // 指定ApplicationContext的父容器
      public ClassPathXmlApplicationContext(ApplicationContext parent) {
        super(parent);
      }
      
      public ClassPathXmlApplicationContext(String configLocation) throws BeansException {
      		this(new String[] {configLocation}, true, null);
      }
      
      public ClassPathXmlApplicationContext(String... configLocations) throws BeansException {
      		this(configLocations, true, null);
      }
      
      public ClassPathXmlApplicationContext(String[] configLocations, @Nullable ApplicationContext parent)
      			throws BeansException {
      
      		this(configLocations, true, parent);
      }
      
      public ClassPathXmlApplicationContext(String[] configLocations, boolean refresh, ApplicationContext parent)
          throws BeansException {
    
        super(parent);
        // 根据提供的路径,处理成配置文件数组(以分号、逗号、空格、tab、换行符分割)
        setConfigLocations(configLocations);
        
        if (refresh) {
          refresh();
        }
      }
    }
    

    可以看到,ClassPathXmlApplicationContext提供了一系列的构造方法,主要是为了指定配置文件的位置,以及设置一个父容器,还有就是调用了refresh()方法,
    setConfigLocations()这个很简单,看来主要的就是在refresh方法中了

    setConfigLocations()

    先看看setConfigLocations()方法中做了什么

    
    public void setConfigLocations(String... locations) {
        if (locations != null) {
            Assert.noNullElements(locations, "Config locations must not be null");
            this.configLocations = new String[locations.length];
            for (int i = 0; i < locations.length; i++) {
                //往下看
                this.configLocations[i] = resolvePath(locations[i]).trim();
            }
        }
        else {
            this.configLocations = null;
        }
    }
    
    protected String resolvePath(String path) {
        return getEnironment().resolveRequiredPlaceholders(path);
    }
    

    setConfigLocations()方法的主要工作有两个:创建环境对象ConfigurableEnvironment和处理构造ClassPathXmlApplicationContext时传入的字符串中的占位符,
    这里getEnvironment()就涉及到了创建环境变量相关的操作了

    getEnvironment()获取环境变量

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

    在上面的getEnvironment()方法的返回值中,我们看到一个ConfigurableEnvironment的类
    先看看这个类的结构:

    这个接口比较重要的就是两部分内容了,一个是设置Spring的环境就是我们经常用的spring.profile配置。另外就是系统资源Property

    接着看看getEnvironment()中的createEnvironment()方法,
    这个类创建了一个StandardEnvironment:

    public class StandardEnvironment extends AbstractEnvironment {
    
    	/** System environment property source name: {@value} 
    	    系统属性 eg:System.getProperty("java.home");
    	    
    	*/
    	public static final String SYSTEM_ENVIRONMENT_PROPERTY_SOURCE_NAME = "systemEnvironment";
    
    	/** JVM system properties property source name: {@value}
    	    JVM 属性  --name=ranger  OR  -Dname=ranger
    	 */
    	public static final String SYSTEM_PROPERTIES_PROPERTY_SOURCE_NAME = "systemProperties";
    
    
    	/**
    	 * Customize the set of property sources with those appropriate for any standard
    	 * Java environment:
    	 * 使用任何适合标准Java环境来定义资源集
    	 * <ul>
    	 * <li>{@value #SYSTEM_PROPERTIES_PROPERTY_SOURCE_NAME}
    	 * <li>{@value #SYSTEM_ENVIRONMENT_PROPERTY_SOURCE_NAME}
    	 * </ul>
    	 * JVM属性的优先级比系统属性高
    	 * <p>Properties present in {@value #SYSTEM_PROPERTIES_PROPERTY_SOURCE_NAME} will
    	 * take precedence over those in {@value #SYSTEM_ENVIRONMENT_PROPERTY_SOURCE_NAME}.
    	 * @see AbstractEnvironment#customizePropertySources(MutablePropertySources)
    	 * 根据父类中对于这个方法的解释:
    	        子类可以重写这个方法来添加自定义的PropertySource, 添加方式如下:
    	            public class Level1Environment extends AbstractEnvironment {
                        &#064;Override
                        protected void customizePropertySources(MutablePropertySources propertySources) {
                            super.customizePropertySources(propertySources); // no-op from base class
                            propertySources.addLast(new PropertySourceA(...));
                            propertySources.addLast(new PropertySourceB(...));
                        }
                    }
                在Level1Environment的子类中,还可以这样添加自定义的PropertySource,而且加入的这个是有优先级的,  比如上面的示例中, 子类添加的 > A > B    
    	 * @see #getSystemProperties()
    	 * @see #getSystemEnvironment()
    	 */
    	@Override
    	protected void customizePropertySources(MutablePropertySources propertySources) {
    		propertySources.addLast(new MapPropertySource(SYSTEM_PROPERTIES_PROPERTY_SOURCE_NAME, getSystemProperties()));
    		propertySources.addLast(new SystemEnvironmentPropertySource(SYSTEM_ENVIRONMENT_PROPERTY_SOURCE_NAME, getSystemEnvironment()));
    	}
    
    }
    

    而这个类中的customizePropertySources方法就会往资源列表中添加Java进程中的变量和系统的环境变量。
    可以看出一个Environment即是包含了一系列PropertySource的资源集合, 而PropertySource就是资源属性

    再次回到resolvePath()方法,一直跟踪这个方法,最后到了org.springframework.util.PropertyPlaceholderHelper.parseStringValue()方法,这个方法主要就是处理所有使用${}方式的占位符

    
    protected String parseStringValue(
             String value, PlaceholderResolver placeholderResolver, Set<String> visitedPlaceholders) {
    
          StringBuilder result = new StringBuilder(value);
          int startIndex = value.indexOf(this.placeholderPrefix);
          while (startIndex != -1) {
             int endIndex = findPlaceholderEndIndex(result, startIndex);
             if (endIndex != -1) {
                String placeholder = result.substring(startIndex + this.placeholderPrefix.length(), endIndex);
                String originalPlaceholder = placeholder;
                if (!visitedPlaceholders.add(originalPlaceholder)) {
                   throw new IllegalArgumentException(
                         "Circular placeholder reference '" + originalPlaceholder + "' in property definitions");
                }
                placeholder = parseStringValue(placeholder, placeholderResolver, visitedPlaceholders);
                // Now obtain the value for the fully resolved key...
                String propVal = placeholderResolver.resolvePlaceholder(placeholder);
                if (propVal == null && this.valueSeparator != null) {
                   int separatorIndex = placeholder.indexOf(this.valueSeparator);
                   if (separatorIndex != -1) {
                      String actualPlaceholder = placeholder.substring(0, separatorIndex);
                      String defaultValue = placeholder.substring(separatorIndex + this.valueSeparator.length());
                      propVal = placeholderResolver.resolvePlaceholder(actualPlaceholder);
                      if (propVal == null) {
                         propVal = defaultValue;
                      }
                   }
                }
                if (propVal != null) {
                   // Recursive invocation, parsing placeholders contained in the
                   // previously resolved placeholder value.
                   propVal = parseStringValue(propVal, placeholderResolver, visitedPlaceholders);
                   result.replace(startIndex, endIndex + this.placeholderSuffix.length(), propVal);
                   if (logger.isTraceEnabled()) {
                      logger.trace("Resolved placeholder '" + placeholder + "'");
                   }
                   startIndex = result.indexOf(this.placeholderPrefix, startIndex + propVal.length());
                }
                else if (this.ignoreUnresolvablePlaceholders) {
                   // Proceed with unprocessed value.
                   startIndex = result.indexOf(this.placeholderPrefix, endIndex + this.placeholderSuffix.length());
                }
                else {
                   throw new IllegalArgumentException("Could not resolve placeholder '" +
                         placeholder + "'" + " in value "" + value + """);
                }
                visitedPlaceholders.remove(originalPlaceholder);
             }
             else {
                startIndex = -1;
             }
          }
    
          return result.toString();
       }
    

    关于PropertyResolver以后再做解析

    refresh()

    这个方法很长,将会长篇幅来介绍,先看个大概干了什么:

    
    public void refresh() throws BeansException, IllegalStateException {
          synchronized (this.startupShutdownMonitor) {
             // Prepare this context for refreshing.
             prepareRefresh();
    
             // Tell the subclass to refresh the internal bean factory.
             ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
    
             // Prepare the bean factory for use in this context.
             prepareBeanFactory(beanFactory);
    
             try {
                // Allows post-processing of the bean factory in context subclasses.
                postProcessBeanFactory(beanFactory);
    
                // Invoke factory processors registered as beans in the context.
                invokeBeanFactoryPostProcessors(beanFactory);
    
                // Register bean processors that intercept bean creation.
                registerBeanPostProcessors(beanFactory);
    
                // Initialize message source for this context.
                initMessageSource();
    
                // Initialize event multicaster for this context.
                initApplicationEventMulticaster();
    
                // Initialize other special beans in specific context subclasses.
                onRefresh();
    
                // Check for listener beans and register them.
                registerListeners();
    
                // Instantiate all remaining (non-lazy-init) singletons.
                finishBeanFactoryInitialization(beanFactory);
    
                // Last step: publish corresponding event.
                finishRefresh();
             }
    
             catch (BeansException ex) {
                if (logger.isWarnEnabled()) {
                   logger.warn("Exception encountered during context initialization - " +
                         "cancelling refresh attempt: " + ex);
                }
    
                // Destroy already created singletons to avoid dangling resources.
                destroyBeans();
    
                // Reset 'active' flag.
                cancelRefresh(ex);
    
                // Propagate exception to caller.
                throw ex;
             }
    
             finally {
                // Reset common introspection caches in Spring's core, since we
                // might not ever need metadata for singleton beans anymore...
                resetCommonCaches();
             }
          }
       }
    
    

    接下来逐步解剖:

    1. synchronized
      为了避免多线程环境下容器还没启动完毕,再次启动引起的冲突

    2. prepareRefresh()
      这个方法做一些准备工作,记录容器的启动时间,标记以启动状态等

    
    protected void prepareRefresh() {
          this.startupDate = System.currentTimeMillis();
          this.closed.set(false);
          this.active.set(true);
    
          if (logger.isInfoEnabled()) {
             logger.info("Refreshing " + this);
          }
    
          // 初始化加载配置文件方法,并没有具体实现,一个留给用户的扩展点
          initPropertySources();
    
          // 检查环境变量
          getEnvironment().validateRequiredProperties();
    
          this.earlyApplicationEvents = new LinkedHashSet<>();
       }
    

    其中有个方法为validateRequiredProperties(),这个方法是为了检查所有需要的环境变量是否为空,如果为空就停止启动,然后抛出异常

    1. obtainFreshBeanFactory()
      这个方法负责了BeanFactory的初始化、Bean的加载和注册等事件
    
    protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
       // 核心
       refreshBeanFactory();
    
       // 返回创建的 BeanFactory
       ConfigurableListableBeanFactory beanFactory = getBeanFactory();
       if (logger.isDebugEnabled()) {
          logger.debug("Bean factory for " + getDisplayName() + ": " + beanFactory);
       }
       return beanFactory;
    }
    
    • refreshBeanFactory():
    /**
     * This implementation performs an actual refresh of this context's underlying
     * bean factory, shutting down the previous bean factory (if any) and
     * initializing a fresh bean factory for the next phase of the context's lifecycle.
     */
    @Override
    protected final void refreshBeanFactory() throws BeansException {
        // 判断当前ApplicationContext是否存在BeanFactory,如果存在的话就销毁所有 Bean,关闭 BeanFactory
        // 注意,一个应用可以存在多个BeanFactory,这里判断的是当前ApplicationContext是否存在BeanFactory
        if (hasBeanFactory()) {
            destroyBeans();
            closeBeanFactory();
        }
        try {
             // 初始化DefaultListableBeanFactory
            DefaultListableBeanFactory beanFactory = createBeanFactory();
            beanFactory.setSerializationId(getId());
            // 设置 BeanFactory 的两个配置属性:是否允许 Bean 覆盖、是否允许循环引用
            customizeBeanFactory(beanFactory);
            // 加载 Bean 到 BeanFactory 中
            loadBeanDefinitions(beanFactory);
            synchronized (this.beanFactoryMonitor) {
                this.beanFactory = beanFactory;
            }
        }
        catch (IOException ex) {
            throw new ApplicationContextException("I/O error parsing bean definition source for " + getDisplayName(), ex);
        }
    }
    

    在这里初始化了一个DefaultListableBeanFactory,看看这个类的继承图

    这是一个非常庞大的家伙

    • loadBeanDefinitions()

    先了解BeanDefinition,我们知道BeanFactory是一个Bean容器,而BeanDefinition就是Bean的一种形式(它里面包含了Bean指向的类、是否单例、是否懒加载、Bean的依赖关系等相关的属性)。BeanFactory中就是保存的BeanDefinition

    BeanDefinition的接口定义:

    public interface BeanDefinition extends AttributeAccessor, BeanMetadataElement {
    
       // Bean的生命周期,默认只提供sington和prototype两种,在WebApplicationContext中还会有request, session, globalSession, application, websocket 等
       String SCOPE_SINGLETON = ConfigurableBeanFactory.SCOPE_SINGLETON;
       String SCOPE_PROTOTYPE = ConfigurableBeanFactory.SCOPE_PROTOTYPE;
    
      
       // 设置父Bean
       void setParentName(String parentName);
    
       // 获取父Bean
       String getParentName();
    
       // 设置Bean的类名称
       void setBeanClassName(String beanClassName);
    
       // 获取Bean的类名称
       String getBeanClassName();
    
    
       // 设置bean的scope
       void setScope(String scope);
    
       String getScope();
    
       // 设置是否懒加载
       void setLazyInit(boolean lazyInit);
    
       boolean isLazyInit();
    
       // 设置该Bean依赖的所有Bean
       void setDependsOn(String... dependsOn);
    
       // 返回该Bean的所有依赖
       String[] getDependsOn();
    
       // 设置该Bean是否可以注入到其他Bean中
       void setAutowireCandidate(boolean autowireCandidate);
    
       // 该Bean是否可以注入到其他Bean中
       boolean isAutowireCandidate();
    
       // 同一接口的多个实现,如果不指定名字的话,Spring会优先选择设置primary为true的bean
       void setPrimary(boolean primary);
    
       // 是否是primary的
       boolean isPrimary();
    
       // 指定工厂名称
       void setFactoryBeanName(String factoryBeanName);
       // 获取工厂名称
       String getFactoryBeanName();
       // 指定工厂类中的工厂方法名称
       void setFactoryMethodName(String factoryMethodName);
       // 获取工厂类中的工厂方法名称
       String getFactoryMethodName();
    
       // 构造器参数
       ConstructorArgumentValues getConstructorArgumentValues();
    
       // Bean 中的属性值,后面给 bean 注入属性值的时候会说到
       MutablePropertyValues getPropertyValues();
    
       // 是否 singleton
       boolean isSingleton();
    
       // 是否 prototype
       boolean isPrototype();
    
       // 如果这个 Bean 是被设置为 abstract,那么不能实例化,常用于作为 父bean 用于继承
       boolean isAbstract();
    
       int getRole();
       String getDescription();
       String getResourceDescription();
       BeanDefinition getOriginatingBeanDefinition();
    }
    

    loadBeanDefinitions()方法会读取配置文件加载各个BeanDefinition,然后放到BeanFactory

    
    @Override
    protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) throws BeansException, IOException {
       // 实例化XmlBeanDefinitionReader
       XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory);
       beanDefinitionReader.setEnvironment(this.getEnvironment());
       beanDefinitionReader.setResourceLoader(this);
       beanDefinitionReader.setEntityResolver(new ResourceEntityResolver(this));
    
       // 初始化 BeanDefinitionReader
       initBeanDefinitionReader(beanDefinitionReader);
       // 接着往下看
       loadBeanDefinitions(beanDefinitionReader);
    }
    
    protected void loadBeanDefinitions(XmlBeanDefinitionReader reader) throws BeansException, IOException {
       Resource[] configResources = getConfigResources();
       if (configResources != null) {
          reader.loadBeanDefinitions(configResources);
       }
       String[] configLocations = getConfigLocations();
       if (configLocations != null) {
          reader.loadBeanDefinitions(configLocations);
       }
    }
    

    然后调用XmlBeanDefinitionReaderloadBeanDefinitions()方法

    public int loadBeanDefinitions(Resource... resources) throws BeanDefinitionStoreException {
       Assert.notNull(resources, "Resource array must not be null");
       int counter = 0;
       // 循环,处理所有配置文件,咱们这里就传了一个
       for (Resource resource : resources) {
          // 继续往下看
          counter += loadBeanDefinitions(resource);
       }
       // 最后返回加载的所有BeanDefinition的数量
       return counter;
    }
    
    @Override
    public int loadBeanDefinitions(String location) throws BeanDefinitionStoreException {
      return loadBeanDefinitions(location, null);
    }
    
    
    public int loadBeanDefinitions(String location, @Nullable Set<Resource> actualResources) throws BeanDefinitionStoreException {
      ResourceLoader resourceLoader = getResourceLoader();
      if (resourceLoader == null) {
         throw new BeanDefinitionStoreException(
               "Cannot import bean definitions from location [" + location + "]: no ResourceLoader available");
      }
    
      if (resourceLoader instanceof ResourcePatternResolver) {
         try {
           //将配置文件转换为Resource对象
            Resource[] resources = ((ResourcePatternResolver) resourceLoader).getResources(location);
           //接着往下看
            int loadCount = loadBeanDefinitions(resources);
            if (actualResources != null) {
               for (Resource resource : resources) {
                  actualResources.add(resource);
               }
            }
            if (logger.isDebugEnabled()) {
               logger.debug("Loaded " + loadCount + " bean definitions from location pattern [" + location + "]");
            }
            return loadCount;
         }
         catch (IOException ex) {
            throw new BeanDefinitionStoreException(
                  "Could not resolve bean definition resource pattern [" + location + "]", ex);
         }
      }
      else {
         // Can only load single resources by absolute URL.
         Resource resource = resourceLoader.getResource(location);
         int loadCount = loadBeanDefinitions(resource);
         if (actualResources != null) {
            actualResources.add(resource);
         }
         if (logger.isDebugEnabled()) {
            logger.debug("Loaded " + loadCount + " bean definitions from location [" + location + "]");
         }
         return loadCount;
      }
    }
    

    这里面多次提到了一个XmlBeanDefinitionReader,这个类主要实现的接口是BeanDefinitionReader

    这个类如何读取配置文件,创建BeanDefinition,然后注册到容器beanDefinitionMap,我们以后再来细讲,看太远就回不来了

    1. prepareBeanFactory(ConfigurableListableBeanFactory beanFactory)

    现在回到refresh()方法的主线上,现在refresh已经走到了prepareBeanFactory,看名字就知道是给BeanFactory准备一些东西,
    实际上这个方法就是BeanFactory的类加载器,添加BeanPostProcessor,然后手动注册几个特殊的bean

    
    /**
     * Configure the factory's standard context characteristics,
     * such as the context's ClassLoader and post-processors.
     * @param beanFactory the BeanFactory to configure
     */
    protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory) {
        // Tell the internal bean factory to use the context's class loader etc.
        // 设置当前BeanFacoty的类加载器
        beanFactory.setBeanClassLoader(getClassLoader());
        // 设置BeanExpressionResolver
        beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver(beanFactory.getBeanClassLoader()));
        // 注册PropertyEditor
        beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this, getEnvironment()));
    
        // Configure the bean factory with context callbacks.
        // 在所有实现了Aware接口的bean在初始化的时候,这个 processor负责回调
        // 例如,bean获取ApplicationContext 而 implement ApplicationContextAware
        // 当然,它也处理实现了 EnvironmentAware、ResourceLoaderAware 等的bean
        beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));
        
        // 下面几行的意思就是,如果某个 bean 依赖于以下几个接口的实现类的bean,在自动装配的时候忽略它们
        beanFactory.ignoreDependencyInterface(EnvironmentAware.class);
        beanFactory.ignoreDependencyInterface(EmbeddedValueResolverAware.class);
        beanFactory.ignoreDependencyInterface(ResourceLoaderAware.class);
        beanFactory.ignoreDependencyInterface(ApplicationEventPublisherAware.class);
        beanFactory.ignoreDependencyInterface(MessageSourceAware.class);
        beanFactory.ignoreDependencyInterface(ApplicationContextAware.class);
    
        // BeanFactory interface not registered as resolvable type in a plain factory.
        // MessageSource registered (and found for autowiring) as a bean.
        // 下面几行就是为特殊的几个 bean 赋值,如果有 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.
        // 如果存在bean名称为loadTimeWeaver的bean则注册一个BeanPostProcessor
        // 具体的这个LoadTimeWeaver是干啥的后面再说
        if (beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {
            beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));
            // Set a temporary ClassLoader for type matching.
            beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));
        }
    
        // Register default environment beans.
        // 注册environment这个bean
        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());
        }
        // JVM属性
        if (!beanFactory.containsLocalBean(SYSTEM_ENVIRONMENT_BEAN_NAME)) {
            beanFactory.registerSingleton(SYSTEM_ENVIRONMENT_BEAN_NAME, getEnvironment().getSystemEnvironment());
        }
    }
    
    1. postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory)

    这里是Spring中提供的一个扩展,调用类中的,这个留给子类去扩展,具体的子类可以在这步的时候添加一些特殊的 BeanFactoryPostProcessor 的实现类或做点什么事.方法定义如下

    /**
     * Modify the application context's internal bean factory after its standard
     * initialization. All bean definitions will have been loaded, but no beans
     * will have been instantiated yet. This allows for registering special
     * BeanPostProcessors etc in certain ApplicationContext implementations.
     * @param beanFactory the bean factory used by the application context
     */
    protected void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) {
    }
    
    
    1. invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory)

    这里是Spring中提供的一个扩展,若有bean实现了BeanFactoryPostProcessor,那么在容器初始化以后,Spring 会负责调用里面的 postProcessBeanFactory 方法
    这个接口的定义如下:

    public interface BeanFactoryPostProcessor {
        void postProcessBeanFactory(ConfigurableListableBeanFactory beanfactory) throws BeansException;
    }
    
    1. registerBeanPostProcessors(ConfigurableListableBeanFactory beanFactory);

    这里又是一个扩展点,注册拦截bean创建的bean处理器,每个bean创建的时候都会调用所有的BeanPostProcessor
    注册 BeanPostProcessor 的实现类,注意不是BeanFactoryPostProcessor
    此接口有两个方法: postProcessBeforeInitializationpostProcessAfterInitialization分别会在Bean初始化之前和初始化之后得到执行

    1. initMessageSource()

    初始化当前 ApplicationContextMessageSource,为了国际化

    1. initApplicationEventMulticaster()

    初始化当前BeanFactory事件广播器,会注册一个SimpleApplicationEventMulticaster单例,可以调用ApplicationEventMulticastermulticastEvent方法来触发一个事件,
    ApplicationEventMulticaster会调用相应的ApplicationListener,到后面讲Spring事件机制再细说

    1. onRefresh()

    这里又是给子类的一个扩展点,

    /**
     * Template method which can be overridden to add context-specific refresh work.
     * Called on initialization of special beans, before instantiation of singletons.
     * <p>This implementation is empty.
     * @throws BeansException in case of errors
     * @see #refresh()
     */
    protected void onRefresh() throws BeansException {
        // For subclasses: do nothing by default.
    }
    
    1. registerListeners();

    检测Listener然后注册到容器

    
    protected void registerListeners() {
      //先添加手动set的一些监听器
      for (ApplicationListener<?> listener : getApplicationListeners()) {
         getApplicationEventMulticaster().addApplicationListener(listener);
      }
    
      //取到监听器的名称,设置到广播器
      String[] listenerBeanNames = getBeanNamesForType(ApplicationListener.class, true, false);
      for (String listenerBeanName : listenerBeanNames) {
         getApplicationEventMulticaster().addApplicationListenerBean(listenerBeanName);
      }
    
      // 如果存在早期应用事件,发布
      Set<ApplicationEvent> earlyEventsToProcess = this.earlyApplicationEvents;
      this.earlyApplicationEvents = null;
      if (earlyEventsToProcess != null) {
         for (ApplicationEvent earlyEvent : earlyEventsToProcess) {
            getApplicationEventMulticaster().multicastEvent(earlyEvent);
         }
      }
    }
    
    1. finishBeanFactoryInitialization()

    在前面refresh方法内走了那么长的路,但是依然没有完成bean的初始化和依赖注入,到这里,Spring觉得时机成熟了,就开始初始化不是懒加载的单例bean

    这里又会迎来一段艰难的路程

    /**
     * Finish the initialization of this context's bean factory,
     * initializing all remaining singleton beans.
     */
    protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {
        // Initialize conversion service for this context.
        // 为当前BeanFactory初始化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 bean post-processor
        // (such as a PropertyPlaceholderConfigurer bean) registered any before:
        // at this point, primarily for resolution in annotation attribute values.
        if (!beanFactory.hasEmbeddedValueResolver()) {
            beanFactory.addEmbeddedValueResolver(strVal -> getEnvironment().resolvePlaceholders(strVal));
        }
    
        // Initialize LoadTimeWeaverAware beans early to allow for registering their transformers early.
        String[] weaverAwareNames = beanFactory.getBeanNamesForType(LoadTimeWeaverAware.class, false, false);
        for (String weaverAwareName : weaverAwareNames) {
            getBean(weaverAwareName);
        }
    
        // Stop using the temporary ClassLoader for type matching.
        beanFactory.setTempClassLoader(null);
    
        // Allow for caching all bean definition metadata, not expecting further changes.
        beanFactory.freezeConfiguration();
    
        // Instantiate all remaining (non-lazy-init) singletons.  
        beanFactory.preInstantiateSingletons();
    }
    
    • ConversionService
      这个是类型转换相关的类,场景之一就是将前端传过来的参数和后端的controller方法上的参数格式转换的时候使用

    • EmbeddedValueResolver
      利用EmbeddedValueResolver可以很方便的实现读取配置文件的属性

    @Component
    public class PropertiesUtil implements EmbeddedValueResolverAware {
    
        private StringValueResolver resolver;
    
        @Override
        public void setEmbeddedValueResolver(StringValueResolver resolver) {
            this.resolver = resolver;
        }
    
    
        /**
         * 获取属性时直接传入属性名称即可
         */
        public String getPropertiesValue(String key) {
            StringBuilder name = new StringBuilder("${").append(key).append("}");
            return resolver.resolveStringValue(name.toString());
        }
    
    }
    
    • beanFactory.preInstantiateSingletons()

    这个方法是重点

    public void preInstantiateSingletons() throws BeansException {
       if (this.logger.isDebugEnabled()) {
          this.logger.debug("Pre-instantiating singletons in " + this);
       }
       // this.beanDefinitionNames 保存了所有的 beanNames
       List<String> beanNames = new ArrayList<String>(this.beanDefinitionNames);
    
       for (String beanName : beanNames) {
          // Return a merged RootBeanDefinition, traversing the parent bean definition,if the specified bean corresponds to a child bean definition.
          RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
    
          // 不是抽象类、是单例的且不是懒加载的
          if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
             // 处理 FactoryBean
             if (isFactoryBean(beanName)) {
                //在 beanName 前面加上“&” 符号
                final FactoryBean<?> factory = (FactoryBean<?>) getBean(FACTORY_BEAN_PREFIX + beanName);
                // 判断当前 FactoryBean 是否是 SmartFactoryBean 的实现
                boolean isEagerInit;
                if (System.getSecurityManager() != null && factory instanceof SmartFactoryBean) {
                   isEagerInit = AccessController.doPrivileged(new PrivilegedAction<Boolean>() {
                      @Override
                      public Boolean run() {
                         return ((SmartFactoryBean<?>) factory).isEagerInit();
                      }
                   }, getAccessControlContext());
                }
                else {
                   isEagerInit = (factory instanceof SmartFactoryBean &&
                         ((SmartFactoryBean<?>) factory).isEagerInit());
                }
                if (isEagerInit) {
    
                   getBean(beanName);
                }
             }
             else {
                // 不是FactoryBean的直接使用此方法进行初始化
                getBean(beanName);
             }
          }
       }
    
    
      
       // 如果bean实现了 SmartInitializingSingleton 接口的,那么在这里得到回调
       for (String beanName : beanNames) {
          Object singletonInstance = getSingleton(beanName);
          if (singletonInstance instanceof SmartInitializingSingleton) {
             final SmartInitializingSingleton smartSingleton = (SmartInitializingSingleton) singletonInstance;
             if (System.getSecurityManager() != null) {
                AccessController.doPrivileged(new PrivilegedAction<Object>() {
                   @Override
                   public Object run() {
                      smartSingleton.afterSingletonsInstantiated();
                      return null;
                   }
                }, getAccessControlContext());
             }
             else {
                smartSingleton.afterSingletonsInstantiated();
             }
          }
       }
    }
    

    可以看到,无论是否是FactoryBean,最后都会调用getBean(String beanName)方法

    @Override
    public Object getBean(String name) throws BeansException {
       return doGetBean(name, null, null, false);
    }
    
    protected <T> T doGetBean(
          final String name, final Class<T> requiredType, final Object[] args, boolean typeCheckOnly)
          throws BeansException {
       // 获取beanName,处理两种情况,一个是前面说的 FactoryBean(前面带 ‘&’),再一个这个方法是可以根据别名来获取Bean的,所以在这里是要转换成最正统的BeanName
      //主要逻辑就是如果是FactoryBean就把&去掉如果是别名就把根据别名获取真实名称后面就不贴代码了
       final String beanName = transformedBeanName(name);
    
       //最后的返回值
       Object bean;
    
       // 检查是否已初始化
       Object sharedInstance = getSingleton(beanName);
      //如果已经初始化过了,且没有传args参数就代表是get,直接取出返回
       if (sharedInstance != null && args == null) {
          if (logger.isDebugEnabled()) {
             if (isSingletonCurrentlyInCreation(beanName)) {
                logger.debug("...");
             }
             else {
                logger.debug("Returning cached instance of singleton bean '" + beanName + "'");
             }
          }
          // 这里如果是普通Bean 的话,直接返回,如果是 FactoryBean 的话,返回它创建的那个实例对象
          bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
       }
    
       else {
          // 如果存在prototype类型的这个bean
          if (isPrototypeCurrentlyInCreation(beanName)) {
                    throw new BeanCurrentlyInCreationException(beanName);
          }
    
          // 如果当前BeanDefinition不存在这个bean且具有父BeanFactory
          BeanFactory parentBeanFactory = getParentBeanFactory();
          if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
             String nameToLookup = originalBeanName(name);
          // 返回父容器的查询结果
             if (args != null) {
                return (T) parentBeanFactory.getBean(nameToLookup, args);
             }
             else {
                return parentBeanFactory.getBean(nameToLookup, requiredType);
             }
          }
    
          if (!typeCheckOnly) {
             // typeCheckOnly 为 false,将当前 beanName 放入一个 alreadyCreated 的 Set 集合中。
             markBeanAsCreated(beanName);
          }
    
          /*
           * 到这就要创建bean了
           */
          try {
             final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
             checkMergedBeanDefinition(mbd, beanName, args);
    
             // 先初始化依赖的所有 Bean, depends-on 中定义的依赖
             String[] dependsOn = mbd.getDependsOn();
             if (dependsOn != null) {
                for (String dep : dependsOn) {
                   // 检查是不是有循环依赖
                   if (isDependent(beanName, dep)) {
                      throw new BeanCreationException(mbd.getResourceDescription(), beanName,
                            "Circular depends-on relationship between '" + beanName + "' and '" + dep + "'");
                   }
                   // 注册一下依赖关系
                   registerDependentBean(dep, beanName);
                   // 先初始化被依赖项
                   getBean(dep);
                }
             }
    
             // 如果是单例的
             if (mbd.isSingleton()) {
                sharedInstance = getSingleton(beanName, new ObjectFactory<Object>() {
                   @Override
                   public Object getObject() throws BeansException {
                      try {
                         // 执行创建 Bean,下面说
                         return createBean(beanName, mbd, args);
                      }
                      catch (BeansException ex) {
                         destroySingleton(beanName);
                         throw ex;
                      }
                   }
                });
                bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
             }
    
             // 如果是prototype
             else if (mbd.isPrototype()) {
                Object prototypeInstance = null;
                try {
                   beforePrototypeCreation(beanName);
                   // 执行创建 Bean
                   prototypeInstance = createBean(beanName, mbd, args);
                }
                finally {
                   afterPrototypeCreation(beanName);
                }
                bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
             }
    
             // 如果不是 singleton 和 prototype 那么就是自定义的scope、例如Web项目中的session等类型,这里就交给自定义scope的应用方去实现
             else {
                String scopeName = mbd.getScope();
                final Scope scope = this.scopes.get(scopeName);
                if (scope == null) {
                   throw new IllegalStateException("No Scope registered for scope name '" + scopeName + "'");
                }
                try {
                   Object scopedInstance = scope.get(beanName, new ObjectFactory<Object>() {
                      @Override
                      public Object getObject() throws BeansException {
                         beforePrototypeCreation(beanName);
                         try {
                            // 执行创建 Bean
                            return createBean(beanName, mbd, args);
                         }
                         finally {
                            afterPrototypeCreation(beanName);
                         }
                      }
                   });
                   bean = getObjectForBeanInstance(scopedInstance, name, beanName, mbd);
                }
                catch (IllegalStateException ex) {
                   throw new BeanCreationException(beanName,
                         "Scope '" + scopeName + "' is not active for the current thread; consider " +
                         "defining a scoped proxy for this bean if you intend to refer to it from a singleton",
                         ex);
                }
             }
          }
          catch (BeansException ex) {
             cleanupAfterBeanCreationFailure(beanName);
             throw ex;
          }
       }
    
       //检查bean的类型
       if (requiredType != null && bean != null && !requiredType.isInstance(bean)) {
          try {
             return getTypeConverter().convertIfNecessary(bean, requiredType);
          }
          catch (TypeMismatchException ex) {
             if (logger.isDebugEnabled()) {
                logger.debug("Failed to convert bean '" + name + "' to required type '" +
                      ClassUtils.getQualifiedName(requiredType) + "'", ex);
             }
             throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
          }
       }
       return (T) bean;
    }
    

    开始会先判断bean存不存在,如果存在就直接返回了。如果不存在调用createBean(String beanName, RootBeanDefinition mbd, Object[] args)方法了

    
    
    protected Object createBean(String beanName, RootBeanDefinition mbd, Object[] args) throws BeanCreationException {
       if (logger.isDebugEnabled()) {
          logger.debug("Creating instance of bean '" + beanName + "'");
       }
       RootBeanDefinition mbdToUse = mbd;
    
       // 确保 BeanDefinition 中的 Class 被加载
       Class<?> resolvedClass = resolveBeanClass(mbd, beanName);
       if (resolvedClass != null && !mbd.hasBeanClass() && mbd.getBeanClassName() != null) {
          mbdToUse = new RootBeanDefinition(mbd);
          mbdToUse.setBeanClass(resolvedClass);
       }
    
       // 准备方法覆写,如果bean中定义了 <lookup-method /> 和 <replaced-method />
       try {
          mbdToUse.prepareMethodOverrides();
       }
       catch (BeanDefinitionValidationException ex) {
          throw new BeanDefinitionStoreException(mbdToUse.getResourceDescription(),
                beanName, "Validation of method overrides failed", ex);
       }
    
       try {
          // 如果有代理的话直接返回
          Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
          if (bean != null) {
             return bean;
          }
       }
       catch (Throwable ex) {
          throw new BeanCreationException(mbdToUse.getResourceDescription(), beanName,
                "BeanPostProcessor before instantiation of bean failed", ex);
       }
       // 创建 bean
       Object beanInstance = doCreateBean(beanName, mbdToUse, args);
       if (logger.isDebugEnabled()) {
          logger.debug("Finished creating instance of bean '" + beanName + "'");
       }
       return beanInstance;
    }
    
    protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final Object[] args)
          throws BeanCreationException {
    
       BeanWrapper instanceWrapper = null;
       if (mbd.isSingleton()) {
        //如果是.factoryBean则从缓存删除
          instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
       }
       if (instanceWrapper == null) {
          // 实例化 Bean,这个方法里面才是终点,下面说
          instanceWrapper = createBeanInstance(beanName, mbd, args);
       }
       //bean实例
       final Object bean = (instanceWrapper != null ? instanceWrapper.getWrappedInstance() : null);
       //bean类型
       Class<?> beanType = (instanceWrapper != null ? instanceWrapper.getWrappedClass() : null);
       mbd.resolvedTargetType = beanType;
    
       synchronized (mbd.postProcessingLock) {
          if (!mbd.postProcessed) {
             try {
                // 循环调用实现了MergedBeanDefinitionPostProcessor接口的postProcessMergedBeanDefinition方法
             // Spring对这个接口有几个默认的实现,其中大家最熟悉的一个是操作@Autowired注解的
                applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
             }
             catch (Throwable ex) {
                throw new BeanCreationException(mbd.getResourceDescription(), beanName,
                      "Post-processing of merged bean definition failed", ex);
             }
             mbd.postProcessed = true;
          }
       }
    
     
       // 解决循环依赖问题
       boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
             isSingletonCurrentlyInCreation(beanName));
       if (earlySingletonExposure) {
          if (logger.isDebugEnabled()) {
             logger.debug("Eagerly caching bean '" + beanName +
                   "' to allow for resolving potential circular references");
          }
        //当正在创建A时,A依赖B,此时通过(8将A作为ObjectFactory放入单例工厂中进行early expose,此处B需要引用A,但A正在创建,从单例工厂拿到ObjectFactory,从而允许循环依赖
          addSingletonFactory(beanName, new ObjectFactory<Object>() {
             @Override
             public Object getObject() throws BeansException {
                return getEarlyBeanReference(beanName, mbd, bean);
             }
          });
       }
    
       Object exposedObject = bean;
       try {
          // 负责属性装配,很重要,下面说
          //  装配属性
          populateBean(beanName, mbd, instanceWrapper);
          if (exposedObject != null) {
             // 这里是处理bean初始化完成后的各种回调,例如init-method、InitializingBean 接口、BeanPostProcessor 接口
             exposedObject = initializeBean(beanName, exposedObject, mbd);
          }
       }
       catch (Throwable ex) {
          if (ex instanceof BeanCreationException && beanName.equals(((BeanCreationException) ex).getBeanName())) {
             throw (BeanCreationException) ex;
          }
          else {
             throw new BeanCreationException(
                   mbd.getResourceDescription(), beanName, "Initialization of bean failed", ex);
          }
       }
       //同样的,如果存在循环依赖
       if (earlySingletonExposure) {
          Object earlySingletonReference = getSingleton(beanName, false);
          if (earlySingletonReference != null) {
             if (exposedObject == bean) {
                exposedObject = earlySingletonReference;
             }
             else if (!this.allowRawInjectionDespiteWrapping && hasDependentBean(beanName)) {
                String[] dependentBeans = getDependentBeans(beanName);
                Set<String> actualDependentBeans = new LinkedHashSet<String>(dependentBeans.length);
                for (String dependentBean : dependentBeans) {
                   if (!removeSingletonIfCreatedForTypeCheckOnly(dependentBean)) {
                      actualDependentBeans.add(dependentBean);
                   }
                }
                if (!actualDependentBeans.isEmpty()) {
                   throw new BeanCurrentlyInCreationException(beanName,
                         "Bean with name '" + beanName + "' has been injected into other beans [" +
                         StringUtils.collectionToCommaDelimitedString(actualDependentBeans) +
                         "] in its raw version as part of a circular reference, but has eventually been " +
                         "wrapped. This means that said other beans do not use the final version of the " +
                         "bean. This is often the result of over-eager type matching - consider using " +
                         "'getBeanNamesOfType' with the 'allowEagerInit' flag turned off, for example.");
                }
             }
          }
       }
    
       // 把bean注册到相应的Scope中
       try {
          registerDisposableBeanIfNecessary(beanName, bean, mbd);
       }
       catch (BeanDefinitionValidationException ex) {
          throw new BeanCreationException(
                mbd.getResourceDescription(), beanName, "Invalid destruction signature", ex);
       }
    
       return exposedObject;
    }
    
    • populateBean((String beanName, RootBeanDefinition mbd, BeanWrapper bw)

    这个方法完成bean内部属性的注入

    
    protected void populateBean(String beanName, RootBeanDefinition mbd, BeanWrapper bw) {
       // bean的所有属性
       PropertyValues pvs = mbd.getPropertyValues();
    
       if (bw == null) {
          if (!pvs.isEmpty()) {
             throw new BeanCreationException(
                   mbd.getResourceDescription(), beanName, "Cannot apply property values to null instance");
          }
          else {
             return;
          }
       }
    
    
       boolean continueWithPropertyPopulation = true;
       if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
          for (BeanPostProcessor bp : getBeanPostProcessors()) {
             if (bp instanceof InstantiationAwareBeanPostProcessor) {
                InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
                // 如果返回 false,代表不需要进行后续的属性设值,也不需要再经过其他的 BeanPostProcessor 的处理
                if (!ibp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) {
                   continueWithPropertyPopulation = false;
                   break;
                }
             }
          }
       }
    
       if (!continueWithPropertyPopulation) {
          return;
       }
    
       if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_NAME ||
             mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_TYPE) {
          MutablePropertyValues newPvs = new MutablePropertyValues(pvs);
    
          // 通过名字找到所有属性值,如果是 bean 依赖,先初始化依赖的 bean。记录依赖关系
          if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_NAME) {
             autowireByName(beanName, mbd, bw, newPvs);
          }
    
          // 通过类型装配。复杂一些
          if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_TYPE) {
             autowireByType(beanName, mbd, bw, newPvs);
          }
    
          pvs = newPvs;
       }
    
       boolean hasInstAwareBpps = hasInstantiationAwareBeanPostProcessors();
       boolean needsDepCheck = (mbd.getDependencyCheck() != RootBeanDefinition.DEPENDENCY_CHECK_NONE);
    
       if (hasInstAwareBpps || needsDepCheck) {
          PropertyDescriptor[] filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
          if (hasInstAwareBpps) {
             for (BeanPostProcessor bp : getBeanPostProcessors()) {
                if (bp instanceof InstantiationAwareBeanPostProcessor) {
                   InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
                   // 这里就是上方曾经提到过得对@Autowired处理的一个BeanPostProcessor了
                   // 它会对所有标记@Autowired、@Value 注解的属性进行设值
                   pvs = ibp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName);
                   if (pvs == null) {
                      return;
                   }
                }
             }
          }
          if (needsDepCheck) {
             checkDependencies(beanName, mbd, filteredPds, pvs);
          }
       }
       // 设置 bean 实例的属性值
       applyPropertyValues(beanName, mbd, bw, pvs);
    }
    
    1. finishRefresh()
    protected void finishRefresh() {
      //看名字就知道了,清理刚才一系列操作使用到的资源缓存
      clearResourceCaches();
    
      // 初始化LifecycleProcessor
      initLifecycleProcessor();
    
      // 这个方法的内部实现是启动所有实现了Lifecycle接口的bean
      getLifecycleProcessor().onRefresh();
    
      //发布ContextRefreshedEvent事件
      publishEvent(new ContextRefreshedEvent(this));
    
      // 检查spring.liveBeansView.mbeanDomain是否存在,有就会创建一个MBeanServer
      LiveBeansView.registerApplicationContext(this);
    }
    

    3. 后记

    这里只是对于容器的初始化做了整体的分析,对于bean的创建和获取还涉及到很多知识点。后面会专门讲解

  • 相关阅读:
    转载: HashMap的工作原理
    什么web服务器、什么是应用服务器,常见的web服务器和应用服务器有哪些
    论文查重应对策略
    web测试方法总结
    软件测试中十大负面测试用例
    mysql 学习笔记
    Tomcat转jboss踩的那些坑
    实现简单的List功能
    java ScriptEngine 使用 (java运行脚本文件)
    rmi 工作原理
  • 原文地址:https://www.cnblogs.com/watertreestar/p/12591271.html
Copyright © 2011-2022 走看看