• spring源码解析-ApplicationContext解析


    ApplicationContext和BeanFactory一样都是bean的容器,而BeanFactory是一切Bean容器的父类,ApplicationContext继承于BeanFactory(继承之BeanFactory的子类)
    ApplicationContext包含了BeanFactory的所有功能,并且扩展了其他功能。先从ApplicationContext的案例入手,代码如下:
    ApplicationContext ctx = new ClassPathXmlApplicationContext("application.xml");
    ctx.getBean("myBean");

     可以看出ApplicationContext和BeanFactory的用法基本一样,初始化之后就可以直接获取Bean了,那么我们就先从ApplicationContext的初始化入手,也就是先从ClassPathXmlApplicationContext的构造函数入手,代码如下:

    public ClassPathXmlApplicationContext(String configLocation) throws BeansException {
            this(new String[] {configLocation}, true, null);
        }
     1 public ClassPathXmlApplicationContext(
     2             String[] configLocations, boolean refresh, @Nullable ApplicationContext parent)
     3             throws BeansException {
     4 
     5         //调用父类的构造函数
     6         super(parent);
     7         //设置配置xml
     8         setConfigLocations(configLocations);
     9         //ApplicationContext初始化
    10         if (refresh) {
    11             refresh();
    12         }
    13     }
    初始化配置xml可以传入数组形式,设置方法setConfigLocations代码如下:
     1 public void setConfigLocations(@Nullable String... locations) {
     2         if (locations != null) {
     3             Assert.noNullElements(locations, "Config locations must not be null");
     4             this.configLocations = new String[locations.length];
     5             for (int i = 0; i < locations.length; i++) {
     6                 this.configLocations[i] = resolvePath(locations[i]).trim();
     7             }
     8         }
     9         else {
    10             this.configLocations = null;
    11         }
    12     }

     主要用于解析配置的xml信息,将xml路径信息赋值给configLocations,设置了配置信息之后就需要对ApplicationContext进行初始化操作了,也就是最后一步的refresh方法了,代码如下:

     1 @Override
     2     public void refresh() throws BeansException, IllegalStateException {
     3         synchronized (this.startupShutdownMonitor) {
     4             // Prepare this context for refreshing.
     5             //准备刷新
     6             prepareRefresh();
     7 
     8             // Tell the subclass to refresh the internal bean factory.
     9             //初始化BeanFactory,并进行XML文件读取
    10             ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
    11 
    12             // Prepare the bean factory for use in this context.
    13             //对BeanFactory进行各种功能扩展
    14             prepareBeanFactory(beanFactory);
    15 
    16             try {
    17                 // Allows post-processing of the bean factory in context subclasses.
    18                 //子类覆盖方法做额外对处理
    19                 postProcessBeanFactory(beanFactory);
    20 
    21                 // Invoke factory processors registered as beans in the context.
    22                 //激活各种BeanFactory处理器
    23                 invokeBeanFactoryPostProcessors(beanFactory);
    24 
    25                 // Register bean processors that intercept bean creation.
    26                 //注册拦截Bean创建对Bean处理器,这里只是注册,真正调用是在getBean对时候
    27                 registerBeanPostProcessors(beanFactory);
    28 
    29                 // Initialize message source for this context.
    30                 //为上下文初始化Message
    31                 initMessageSource();
    32 
    33                 // Initialize event multicaster for this context.
    34                 //初始化应用消息广播器
    35                 initApplicationEventMulticaster();
    36 
    37                 // Initialize other special beans in specific context subclasses.
    38                 //留给子类来初始化其他对Bean
    39                 onRefresh();
    40 
    41                 // Check for listener beans and register them.
    42                 //在所有注册对bean中寻找Lestener bean,注册到消息广播器中
    43                 registerListeners();
    44 
    45                 // Instantiate all remaining (non-lazy-init) singletons.
    46                 //初始化剩下对单例bean
    47                 finishBeanFactoryInitialization(beanFactory);
    48 
    49                 // Last step: publish corresponding event.
    50                 //完成刷新过程,通知生命周期处理器刷新过程,同时发出ContextRefreshEvent通知别人
    51                 finishRefresh();
    52             }
    53 
    54             catch (BeansException ex) {
    55                 if (logger.isWarnEnabled()) {
    56                     logger.warn("Exception encountered during context initialization - " +
    57                             "cancelling refresh attempt: " + ex);
    58                 }
    59 
    60                 // Destroy already created singletons to avoid dangling resources.
    61                 destroyBeans();
    62 
    63                 // Reset 'active' flag.
    64                 cancelRefresh(ex);
    65 
    66                 // Propagate exception to caller.
    67                 throw ex;
    68             }
    69 
    70             finally {
    71                 // Reset common introspection caches in Spring's core, since we
    72                 // might not ever need metadata for singleton beans anymore...
    73                 resetCommonCaches();
    74             }
    75         }
    76     }
    77 }
    主要过程为:
    1.初始化前对准备工作,对系统属性或者环境变量的验证
    2.初始化BeanFactory,并进行xml文件读取,相当于复用了BeanFactory的配置文件读取解析过程,相当于进行了一次BeanFactory的初始化,剩下的都是对BeanFactory的扩展了
    3.对BeanFactory进行功能填充(如@Autowired @Qualifier注解对支持等)
    4. 子类覆盖父类方法做额外的处理(postProcessBeanFactory方法是空函数,方便子类进行扩展)
    5.激活各种BeanFactory处理器
    6.注册拦截bean创建的bean处理器
    7.剩下的可以看代码中的注解
     
    接下来再细看,初始化前的准备验证直接跳过,直接看如何初始化BeanFactory的,
    1 protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
    2         refreshBeanFactory();
    3         return getBeanFactory();
    4     }

    第一步初始化BeanFactory,进行xml配置读取解析

    第二步返回BeanFactory

     1 @Override
     2     protected final void refreshBeanFactory() throws BeansException {
     3         if (hasBeanFactory()) {
     4             destroyBeans();
     5             closeBeanFactory();
     6         }
     7         try {
     8             DefaultListableBeanFactory beanFactory = createBeanFactory();
     9             beanFactory.setSerializationId(getId());
    10             customizeBeanFactory(beanFactory);
    11             loadBeanDefinitions(beanFactory);
    12             synchronized (this.beanFactoryMonitor) {
    13                 this.beanFactory = beanFactory;
    14             }
    15         }
    16         catch (IOException ex) {
    17             throw new ApplicationContextException("I/O error parsing bean definition source for " + getDisplayName(), ex);
    18         }
    19     }
    大致过程如下:
    1.创建DefaultListableBeanFactory对象,BeanFactory的初始化实际也是创建了这个对象
    2.指定序列号ID
    3.定制BeanFactory
    4.加载BeanDefinition
    5.使用全局变量记录BeanFactory实例
     
    这里的第三步的customizeBeanFactory方法是对BeanFactory的扩展,添加了@Qualifier和@Autowired的支持
    loadBeanDefinitions方法是加载BeanDefinition,首先是加载Xml,使用XmlBeanDefinitionReader的loadBeanDefinitions方法进行配置文件的加载注册和BeanFactory的逻辑一样
     
    在BeanFactory初始化之后就是对BeanFactory的扩展,也就是prepareBeanFactory方法及之后的内容
     
     1 protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory) {
     2         // Tell the internal bean factory to use the context's class loader etc.
     3         beanFactory.setBeanClassLoader(getClassLoader());
     4         beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver(beanFactory.getBeanClassLoader()));
     5         beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this, getEnvironment()));
     6 
     7         // Configure the bean factory with context callbacks.
     8         beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));
     9         beanFactory.ignoreDependencyInterface(EnvironmentAware.class);
    10         beanFactory.ignoreDependencyInterface(EmbeddedValueResolverAware.class);
    11         beanFactory.ignoreDependencyInterface(ResourceLoaderAware.class);
    12         beanFactory.ignoreDependencyInterface(ApplicationEventPublisherAware.class);
    13         beanFactory.ignoreDependencyInterface(MessageSourceAware.class);
    14         beanFactory.ignoreDependencyInterface(ApplicationContextAware.class);
    15 
    16         // BeanFactory interface not registered as resolvable type in a plain factory.
    17         // MessageSource registered (and found for autowiring) as a bean.
    18         beanFactory.registerResolvableDependency(BeanFactory.class, beanFactory);
    19         beanFactory.registerResolvableDependency(ResourceLoader.class, this);
    20         beanFactory.registerResolvableDependency(ApplicationEventPublisher.class, this);
    21         beanFactory.registerResolvableDependency(ApplicationContext.class, this);
    22 
    23         // Register early post-processor for detecting inner beans as ApplicationListeners.
    24         beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(this));
    25 
    26         // Detect a LoadTimeWeaver and prepare for weaving, if found.
    27         if (beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {
    28             beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));
    29             // Set a temporary ClassLoader for type matching.
    30             beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));
    31         }
    32 
    33         // Register default environment beans.
    34         if (!beanFactory.containsLocalBean(ENVIRONMENT_BEAN_NAME)) {
    35             beanFactory.registerSingleton(ENVIRONMENT_BEAN_NAME, getEnvironment());
    36         }
    37         if (!beanFactory.containsLocalBean(SYSTEM_PROPERTIES_BEAN_NAME)) {
    38             beanFactory.registerSingleton(SYSTEM_PROPERTIES_BEAN_NAME, getEnvironment().getSystemProperties());
    39         }
    40         if (!beanFactory.containsLocalBean(SYSTEM_ENVIRONMENT_BEAN_NAME)) {
    41             beanFactory.registerSingleton(SYSTEM_ENVIRONMENT_BEAN_NAME, getEnvironment().getSystemEnvironment());
    42         }
    43     }

     方法主要内容是:

    1.增加对SPEL语言的支持(如#{XXX.xxx}设置属性)

    2.增加对属性编辑器的支持

    3.设置依赖功能可忽略的接口

    4.注册一些固定依赖的属性

    5.增加AspectJ的支持

    6.将相关环境变量及属性注册以单例模式注册

     
    接下来再看下初始化非延迟加载单例的bean
     1 protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {
     2         // Initialize conversion service for this context.
     3         if (beanFactory.containsBean(CONVERSION_SERVICE_BEAN_NAME) &&
     4                 beanFactory.isTypeMatch(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class)) {
     5             beanFactory.setConversionService(
     6                     beanFactory.getBean(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class));
     7         }
     8 
     9         // Register a default embedded value resolver if no bean post-processor
    10         // (such as a PropertyPlaceholderConfigurer bean) registered any before:
    11         // at this point, primarily for resolution in annotation attribute values.
    12         if (!beanFactory.hasEmbeddedValueResolver()) {
    13             beanFactory.addEmbeddedValueResolver(strVal -> getEnvironment().resolvePlaceholders(strVal));
    14         }
    15 
    16         // Initialize LoadTimeWeaverAware beans early to allow for registering their transformers early.
    17         String[] weaverAwareNames = beanFactory.getBeanNamesForType(LoadTimeWeaverAware.class, false, false);
    18         for (String weaverAwareName : weaverAwareNames) {
    19             getBean(weaverAwareName);
    20         }
    21 
    22         // Stop using the temporary ClassLoader for type matching.
    23         beanFactory.setTempClassLoader(null);
    24 
    25         // Allow for caching all bean definition metadata, not expecting further changes.
    26         beanFactory.freezeConfiguration();
    27 
    28         // Instantiate all remaining (non-lazy-init) singletons.
    29         beanFactory.preInstantiateSingletons();
    30     }

     这里的26行的freezeConfiguration方法是对bean定义的冻结,也就是说bean注册之后就不可改了,而ApplicationContext默认说会将所有的单例bean提前进行初始化的,也就是方法preInstantiateSingletons方法

     1 @Override
     2     public void preInstantiateSingletons() throws BeansException {
     3         if (logger.isTraceEnabled()) {
     4             logger.trace("Pre-instantiating singletons in " + this);
     5         }
     6 
     7         // Iterate over a copy to allow for init methods which in turn register new bean definitions.
     8         // While this may not be part of the regular factory bootstrap, it does otherwise work fine.
     9         List<String> beanNames = new ArrayList<>(this.beanDefinitionNames);
    10 
    11         // Trigger initialization of all non-lazy singleton beans...
    12         for (String beanName : beanNames) {
    13             RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
    14             if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
    15                 if (isFactoryBean(beanName)) {
    16                     Object bean = getBean(FACTORY_BEAN_PREFIX + beanName);
    17                     if (bean instanceof FactoryBean) {
    18                         final FactoryBean<?> factory = (FactoryBean<?>) bean;
    19                         boolean isEagerInit;
    20                         if (System.getSecurityManager() != null && factory instanceof SmartFactoryBean) {
    21                             isEagerInit = AccessController.doPrivileged((PrivilegedAction<Boolean>)
    22                                             ((SmartFactoryBean<?>) factory)::isEagerInit,
    23                                     getAccessControlContext());
    24                         }
    25                         else {
    26                             isEagerInit = (factory instanceof SmartFactoryBean &&
    27                                     ((SmartFactoryBean<?>) factory).isEagerInit());
    28                         }
    29                         if (isEagerInit) {
    30                             getBean(beanName);
    31                         }
    32                     }
    33                 }
    34                 else {
    35                     getBean(beanName);
    36                 }
    37             }
    38         }
    39 
    40         // Trigger post-initialization callback for all applicable beans...
    41         for (String beanName : beanNames) {
    42             Object singletonInstance = getSingleton(beanName);
    43             if (singletonInstance instanceof SmartInitializingSingleton) {
    44                 final SmartInitializingSingleton smartSingleton = (SmartInitializingSingleton) singletonInstance;
    45                 if (System.getSecurityManager() != null) {
    46                     AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
    47                         smartSingleton.afterSingletonsInstantiated();
    48                         return null;
    49                     }, getAccessControlContext());
    50                 }
    51                 else {
    52                     smartSingleton.afterSingletonsInstantiated();
    53                 }
    54             }
    55         }
    56     }
    高频面试题:ApplicationContext和BeanFactory的区别?
    1.BeanFactory是容器所有容器接口的父类,提供了最基本的bean相关的功能,而ApplicationContext是继承之BeanFactory,在BeanFactory的基础上扩展了更多的功能
    2.ApplicationContext的初始化过程就包含了BeanFactory的初始化过程,如何额外扩展,
    3.BeanFactory中的bean是在获取的时候才初始化,而ApplicationContext是初始化的时候就初始化所有的单例bean(好处是在启动的时候就可以检查到不合法的bean)
    4.ApplicationContext增加了SPEL语言的支持(#{xx.xx}等配置)、 消息发送、响应机制(ApplicationEventPublisher)、支持了@Qualiiar和@Autowired等注解
     
  • 相关阅读:
    SOJ 4580 动态规划之01背包 (01背包)
    文件比较与同步工具——FreeFileSync
    肺结节CT影像特征提取(五)——肺结节CT影像ROI区域灰度直方图及其图形化
    JAVA学习笔记(4)—— 排序算法
    JAVA学习笔记(3)—— 抽象类与接口
    JAVA学习笔记(2)—— java初始化三个原则
    JAVA学习笔记(1)—— eclipse自动补全和主题及字体配置
    3D Slicer中文教程(八)—导出STL文件
    3D Slicer中文教程(七)—图像中值滤波
    “Excel-建议不可用于您所选择的数据”错误提示
  • 原文地址:https://www.cnblogs.com/jackion5/p/10991825.html
Copyright © 2020-2023  润新知