• spring源码分析 - AnnotationConfigApplicationContext启动之refresh


    前言

    我们在使用spring framework时一般都喜欢按照以下方式写启动

    AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(AppConfig.class);
    而我们的AnnotationConfigApplicationContext的内容如下
    public AnnotationConfigApplicationContext(Class<?>... componentClasses) {
       // 构造DefaultListableBeanFactory、AnnotatedBeanDefinitionReader、ClassPathBeanDefinitionScanner
       this();
       register(componentClasses);
       refresh();
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    在前面的文章中我们介绍了AnnotationConfigApplicationContext 里reader、scaner、AppConfig.class的beandefiniton如何建创,这里我主要介绍一下refresh()方法里主要逻辑

    refresh()方法代码内容

    从以下代码内容看其实主要调用的各个方法,我们来深入了解一下具体功能,具体方法里的代码内容不展示,主要说明各个方法功能

    public void refresh() throws BeansException, IllegalStateException {
       synchronized (this.startupShutdownMonitor) {
          StartupStep contextRefresh = this.applicationStartup.start("spring.context.refresh");     
          prepareRefresh();      
           ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();       
          prepareBeanFactory(beanFactory);
          try {          
             postProcessBeanFactory(beanFactory);
             StartupStep beanPostProcess = this.applicationStartup.start("spring.context.beans.post-process");
             invokeBeanFactoryPostProcessors(beanFactory);   
             registerBeanPostProcessors(beanFactory);
             beanPostProcess.end(); 
             initMessageSource(); 
             initApplicationEventMulticaster();  
             onRefresh();   
             registerListeners(); 
             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();
          }
       }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34

    prepareRefresh逻辑

    1.initPropertySources
    初始化系统属性信息,主要是向Environment中保存,如果我们启动的是webapplicationcontext的话主要生成MutablePropertySources对象StandardServletEnvironment的属性propertySources,主要向其中放如servlet的servletContextInitParams和servletConfigInitParams两种数据,数据是真正保存在MutablePropertySources的propertySourceList中,它的定义如下:
    List> propertySourceList = new CopyOnWriteArrayList<>();

    2.getEnvironment().validateRequiredProperties();

    • 检查1中加载的环境属性值是否有空值的情况,如有抛出异常
    • 生成beanfactory的属性earlyApplicationListeners,new
      LinkedHashSet<>(this.applicationListeners)
    • 生成beanfactory的属性earlyApplicationEvents = new LinkedHashSet<>()

    obtainFreshBeanFactory()逻辑

    1.生成并设定beanfactory的serializationId
    2.返回beanfactory

    prepareBeanFactory逻辑

    1. 设定beanfactory的beanLassLoader

    2. 设定beanfactory的beanExpressionResolver,主要是 通过new SpelExpressionParser(new SpelParserConfiguration(null,beanClassLoader))

    3. 向beanfactory的属性propertyEditorRegistrars加入new
      ResourceEditorRegistrar(this, getEnvironment(),主用于注册编辑转换器

    4. 向beanfactory的属性ignoredDependencyInterfaces加入EnvironmentAware、EmbeddedValueResolverAware、ResourceLoaderAware、 ApplicationEventPublisherAware、MessageSourceAware、ApplicationContextAware、ApplicationStartupAware
      主要用于忽略的依赖和自动注入的class,主要通过beanFactory.ignoreDependencyInterface个方法来实现,在系统开发时如果某个class不想作为自动依赖注入,可以将此作为扩展点

    5. 向beanfactory的属性resolvableDependencies加入BeanFactory、ResourceLoader、ApplicationEventPublisher、ApplicationContext
      主要用于向beanfactory放入自动依赖注入时可以注入的类型,主要通过beanFactory.registerResolvableDependency方法实现,在系统开发也可以作为一个扩展点

    6. 向beanfactory的属性beanPostProcessors加入ApplicationListenerDetector对象
      这个对象主要用于bean对像初始化后和销毁之前的事件广播,主要通过postProcessAfterInitialization、postProcessBeforeDestruction这两个方法调用,主要是从beanfactory的属性中applicationEventMulticaster加入或删除,这样前提条件如果bean集成了ApplicationListener接口类对象

    7. 向beanfactory的属性singletonObjects加入以下单例bean,及registeredSingletons放入已经实例的名字

         ENVIRONMENT_BEAN_NAME:    StandardEnvironment
         SYSTEM_PROPERTIES_BEAN_NAME: getEnvironment().getSystemProperties()
         SYSTEM_ENVIRONMENT_BEAN_NAME:  getEnvironment().getSystemEnvironment()
         APPLICATION_STARTUP_BEAN_NAME :  getApplicationStartup()           
      
      • 1
      • 2
      • 3
      • 4

    postProcessBeanFactory逻辑

    这里主要用web有关的逻辑,主要功能如下:

    1. 向beanfactory的属性beanPostProcessors加入ServletContextAwareProcessor
    2. 向beanfactory的属性put加入以下内容
      SCOPE_REQUEST:RequestScope
      SCOPE_SESSION:SessionScope
      SCOPE_APPLICATION:ServletContextScope(sc)
    3. 向beanfactory的属性resolvableDependencies加入可自动依赖类型
    beanFactory.registerResolvableDependency(ServletRequest.class, new RequestObjectFactory());
    beanFactory.registerResolvableDependency(ServletResponse.class, new ResponseObjectFactory());
    beanFactory.registerResolvableDependency(HttpSession.class, new SessionObjectFactory());
    beanFactory.registerResolvableDependency(WebRequest.class, new WebRequestObjectFactory());
    if (jsfPresent) {
       FacesDependencyRegistrar.registerFacesDependencies(beanFactory);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    invokeBeanFactoryPostProcessors逻辑

    1. .从beanfactory的属性beanFactoryPostProcessors获取BeanDefinitionRegistryPostProcessor对象并执行其postProcessBeanDefinitionRegistry方法
      在启动阶段beanFactoryPostProcessors没有内容

    2. 从factory的属性中beanDefinitionNames、manualSingletonNames找出是BeanDefinitionRegistryPostProcessor类型的beanname
      在启动阶段只有ConfigurationClassPostProcessor的beandefinition满足条件的

    3. 从2找中满足条件beanname,在判断这个是否为PriorityOrdered子类,若是调用beanfactory.getBean生成bean,并放入变量currentRegistryProcessors中,并在processedBeans加入beanname
      这里getBean逻辑细节单节整理,主要是参考beandefinition的信息生成bean

    4. 对currentRegistryProcessors中的bean按照dependencyComparator进行排序,并加入registryProcessors变量中

    5. 调用执行postProcessBeanDefinitionRegistry方法

    • 启动阶段主要是执行ConfigurationClassPostProcessor类的postProcessBeanDefinitionRegistry方法,然后内部在调用processConfigBeanDefinitions方法

    • 从factory的属性中beanDefinitionMap中得到有@Configuration的类,主要是通过ConfigurationClassUtils.checkConfigurationClassCandidate方法查找,并对beandefinition设定如下内容:

    if (config != null && !Boolean.FALSE.equals(config.get("proxyBeanMethods"))) {
       beanDef.setAttribute(CONFIGURATION_CLASS_ATTRIBUTE, CONFIGURATION_CLASS_FULL);
    } 
    else if (config != null || isConfigurationCandidate(metadata)) {
       beanDef.setAttribute(CONFIGURATION_CLASS_ATTRIBUTE, CONFIGURATION_CLASS_LITE);
    }
    else {
       return false;
    } 
    Integer order = getOrder(metadata);
    if (order != null) {
       beanDef.setAttribute(ORDER_ATTRIBUTE, order);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 然后对找到所有@Configuration类进行排序,按照beandefinition的order值排序,如果order没有设定取Integer.MAX_VALUE

    • 获取factory的属性singletonObjects获取org.springframework.context.annotation.internalConfigurationBeanNameGenerator类型bean,并赋给成员属性componentScanBeanNameGenerator、importBeanNameGenerator,在启动阶段factory中没有此类型的bean

    • 给environment属性设定StandardEnvironment

    • 创建ConfigurationClassParser类的对象parser

    • 执行parser对象的parse()方法进行解析含有@Configuration类的beandefinition,在执行processConfigurationClass(new ConfigurationClass(metadata, beanName), DEFAULT_EXCLUSION_FILTER)这个方法:

      1. 如果beandefinition的类有@condition注解,直接返回

      2. 调用asSourceClass方法生成SouceClass对象sourceClass

        a) 解析beandefinition类上各个注解有效性,主要通过测试注解类包含的方法返回类型为(type == Class.class || type == Class[].class || type.isEnum())是否抛异常,主要是通过调用AttributeMethods.forAnnotationType(annotation.annotationType()).validate(annotation)来实现
        b) 如果2中没有抛出异常,生成SourceClass对象

      3.执行doProcessConfigurationClass(configClass, sourceClass, filter)方法

       a). 判断注解类是否为Component.class,在通过执行processMemberClasses(configClass,sourceClass,filter)方法判断内部类是否不是接口、是否为@Component、@ComponentScan、@Import、@ImportResouce其中一个、是否有@Bean注解,若满足条件之一对内部注解类按照这里的1、2、3、4的步骤递归调用执行
       b).  解析@PropertySource,通过通过以下方法
            AnnotationConfigUtils.attributesForRepeatable(sourceClass.getMetadata(), PropertySources.class, org.springframework.context.annotation.PropertySource.class))
              i.获取@PropertySource和@PropertySources的value、encoding、name、ignoreResourceNotFoud属性数据
              ii.根据value的内容,生成value内容的propertySource对象,放入parse对象environment属性中的propertySources属性
              iii.将value内容放入parse对象的propertySourceNames属性中
       c). 解析@CompoentScan
           i. 通过调用AnnotationConfigUtils得到注解的属性值Set componentScans,主要有value、basePackages、basePackageClasses、resourcePattern(默认值:**/*.class)等相关属性
       		componentScan = {AnnotationAttributes@2077}  size = 11
       		 "basePackageClasses" -> {Class[0]@2092} 
       		 "basePackages" -> {String[1]@2094} ["com.test"]
       		 "excludeFilters" -> {AnnotationAttributes[0]@2096} 
       		 "includeFilters" -> {AnnotationAttributes[0]@2098} 
       		 "lazyInit" -> {Boolean@2100} false
       		 "nameGenerator" -> {Class@846} "interface org.springframework.beans.factory.support.BeanNameGenerator"
       		 "resourcePattern" -> "**/*.class"
       		 "scopeResolver" -> {Class@849} "class org.springframework.context.annotation.AnnotationScopeMetadataResolver"
       		 "scopedProxy" -> {ScopedProxyMode@2106} "DEFAULT"
       		 "useDefaultFilters" -> {Boolean@2108} true
       		 "value" -> {String[1]@2109} ["com.test"]
       		 如果useDefaultFilters为true,设定defaultFilter,可以为@Component、@Named、@ManagedBean
       	ii. 执行parse.componentScanParser.parse(componentScan, sourceClass.getMetadata().getClassName()),componentScanParser为ComponentScanAnnotationParser实例化对象,这部分逻辑单独整理,主要扫描类也生成beandefition有关逻辑
      **找到相关类通过以下代码来扫描,主要根据basepackage属性**
      *****************************************************************************
       	protected void doRetrieveMatchingFiles(String fullPattern, File dir, Set result) throws IOException {
       if (logger.isTraceEnabled()) {
       	logger.trace("Searching directory [" + dir.getAbsolutePath() +
       			"] for files matching pattern [" + fullPattern + "]");
       }
       for (File content : listDirectory(dir)) {
       	String currPath = StringUtils.replace(content.getAbsolutePath(), File.separator, "/");
       	if (content.isDirectory() && getPathMatcher().matchStart(fullPattern, currPath + "/")) {
       		if (!content.canRead()) {
       			if (logger.isDebugEnabled()) {
       				logger.debug("Skipping subdirectory [" + dir.getAbsolutePath() +
       						"] because the application is not allowed to read the directory");
       			}
       		}
       		else {
       			doRetrieveMatchingFiles(fullPattern, content, result);
       		}
       	}
       	if (getPathMatcher().match(fullPattern, currPath)) {
       		result.add(content);
       	}
       }
       }
      *****************************************************************
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
      • 14
      • 15
      • 16
      • 17
      • 18
      • 19
      • 20
      • 21
      • 22
      • 23
      • 24
      • 25
      • 26
      • 27
      • 28
      • 29
      • 30
      • 31
      • 32
      • 33
      • 34
      • 35
      • 36
      • 37
      • 38
      • 39
      • 40
      • 41
      • 42
      • 43
      • 44
      • 45
      • 46
      • 47
      • 48
      1. 解析注解@Import,逻辑复杂单独整理 ConfigurationClassParser.processImports
        主要处理Import的class是否为普通类、继承ImportSelecto、DeferredImportSelector、ImportBeanDefinitionRegistrar这些类,最终将import的类生成对象放入parse的importStack属性中

      2. 解析@ImportResource,将得到的文件信息加入到configclass对象属性importedResources

      3. 解析configuration类中含有@Bean注解的方法,读取到方法加入configClass属性beanMethods中
        在读取含有@Bean注解时会在次读取一次,确认是否一致,具体的参考retrieveBeanMethodMetadata这个方法

      4. 分析configuration类的接口方法中是否含有@Bean注解方法,并加入到configclass对象属性importedResources

      5. 分析configuration的父类,如果不java基础类放入parse的knownSuperclasses属性中

    • 执行完doProcessConfigurationClass方法后将其返回的父类
      继续循环执行doProcessConfigurationClass方法,直到没有父类,并将解析过类放入parse的configurationClasses属性中

    • 处理configuration类中@Import有关逻辑,后面单独和解析注解@Import一整理
      ConfigurationClassParser.componentScanParser.process()

    • 执行parse对象的validate()方法

      1. 检查parse对象中属性configurationClasses的class是有@Configuration注解属性proxyBeanMethods是否为true,且class为final类认为异常problemReporter.error(newFinalConfigurationProblem())

      2. 检查parse对象中属性configurationClasses的class是有@Configuration注解,对有@Bean注解的方法检查是否为不可覆盖方法,若是不可覆盖产生problemReporter.error(new
        NonOverridableMethodError());

    • 生成ConfigurationClassBeanDefinitionReader类对象reader

    • 通过调用reader.loadBeanDefinitions方法,生成parse分析过的class的beandefinition并入beanfactory的beanDefinitionMap中

       	a. 判断是否需要skip,通过trackedConditionEvaluator.shouldSkip(configClass)
       	b.若class是被@Import进行的,生成beandefinition
       	c.若class中含有@注解方法,如果@Bean 注解没有设定值直接取方法名为beanname,主要是通过调用
       	   ConfigurationClassBeanDefinitionReader.loadBeanDefinitionsForBeanMethod方法,细节单独整理
       	d.处理@ImportResource逻辑,主要是处理按照xml生成beandefinition, 调用XmlBeanDefinitionReader.loadBeanDefinitions(resource)方法,细节单独整理
      
      • 1
      • 2
      • 3
      • 4
      • 5
    • 判断经过parse.parse()解析过的类是否有新的有@Configuration注解类,若有重复以下过程,直到没有新的@Configuration类,这个通过注解@ComponentScan的basePackges可能扫到多个Configuration类

    if (registry.getBeanDefinitionCount() > candidateNames.length) {
       String[] newCandidateNames = registry.getBeanDefinitionNames();
       Set<String> oldCandidateNames = new HashSet<>(Arrays.asList(candidateNames));
       Set<String> alreadyParsedClasses = new HashSet<>();
       for (ConfigurationClass configurationClass : alreadyParsed) {
          alreadyParsedClasses.add(configurationClass.getMetadata().getClassName());
       }
       for (String candidateName : newCandidateNames) {
          if (!oldCandidateNames.contains(candidateName)) {
             BeanDefinition bd = registry.getBeanDefinition(candidateName);
    
             // 检查多出来的BeanDefinition是不是配置类,需不需要解析
             if (ConfigurationClassUtils.checkConfigurationClassCandidate(bd, this.metadataReaderFactory) &&
                   !alreadyParsedClasses.contains(bd.getBeanClassName())) {
                candidates.add(new BeanDefinitionHolder(bd, candidateName));
             }
          }
       }
       candidateNames = newCandidateNames;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 在beanfactory的singletonObjects加入parse对象importStack中的内容,beanname为IMPORT_REGISTRY_BEAN_NAME【ConfigurationClassPostProcessor…importRegistry】
    1. 在次从factory的属性中beanDefinitionNames、manualSingletonNames找出是BeanDefinitionRegistryPostProcessor类型的beanname,确认是否和2中找到是一样class,若不是执行3、4、5、6

      在这里是个扩展点可以自定义BeanDefinitionRegistryPostProcessor接口实现对bean的初始化过程进行修改,或者对beanfactory进行各操作,
      ConfigurationClassPostProcessor.postProcessBeanDefinitionRegistry
      
      • 1
      • 2
    2. 在次重复6的过程
      可能是为了防止在6过程中自定义实现BeanDefinitionRegistryPostProcessor的接口类

    3. 用2、6、7中找出BeanDefinitionRegistryPostProcessor实现类执行postProcessBeanFactory这个方法

      在启动阶段如果没有实现BeanDefinitionRegistryPostProcessor自定义类只ConfigurationClassPostProcessor.postProcessBeanFactory
      查找beanfactory中beandefinition中没有加载class的都只加载,主要是lite和full类及@Bean方法对应的方法

    4. 执行beanfactory.beanFactoryPostProcessors属性中实现了BeanFactoryPostProcessor接口的对象方法postProcessBeanFactory,除了实现BeanDefinitionRegistryPostProcessor接口的对象

      启动阶段没有可以执行的,因为启动阶段beanFactoryPostProcessors里没有内容

    • 从前面生成的beandefinition中找出所有实现了BeanFactoryPostProcessor接口类:

      1. 找出实现了PriorityOrdered类,排序后执行postProcessBeanFactory方法

      2. 找出实现了Ordered类,排序后执行postProcessBeanFactory方法

      3. 除了以上两种类,执行postProcessBeanFactory方法

      扩展点:
      1.可以自定义实现BeanFactoryPostProcessor接口类来对beanfactory的属性进行操作,大多情况下对beandefinition操作,
      2.如果多个BeanFactoryPostProcessor这样类,可以实现PriorityOrder、Order接口来控制顺序
      另外从代码上来看10是对9补充,可能随着版本升级加入@ComponentScan和@Configuration之后9可能有点问题

    registerBeanPostProcessors逻辑

    1. 找出前面生成的所有beandefinition是BeanPostProcessor接口的实现类,包括自定义实现BeanPostProcessor接口类,且按照实现PriorityOrdered、Ordered接口、未实现PriorityOrder&Ordeded、实现MergedBeanDefinitionPostProcessor的顺序排序后放入beanfactory的beanPostProcessors属性中
    2. 在beanfactory的beanPostProcessors属性中放入ApplicationListenerDetector对象
      第2个过程其实在prepareBeanFactory()进行过一次,这样做的目的是为将事件广播的放在所有的BeanPostProcessor类之后处理

    initMessageSource逻辑

    初始化MessageSouce Bean,并作为singleton bean名字messageSource放入容器中
    如果系统开发时需要使用国际化功能,需要在@Configuration类中通@Bean方法生成messageSource的bean,否则无法使用国际化功能,原困如下:

    1.在得到国际化信息时spring需要按照以下如下代码方进行
    public String getMessage(String code, @Nullable Object[] args, Locale locale) throws NoSuchMessageException {
       if (this.parentMessageSource != null) {
          return this.parentMessageSource.getMessage(code, args, locale);
       }
       else {
          throw new NoSuchMessageException(code, locale);
       }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
     2.生成bean的逻辑如下,如果beanfactory没有messageSource bean,但是getInternalParentMessageSource()这个方法是没有值的  
    
    • 1
       // Use empty MessageSource to be able to accept getMessage calls.
          DelegatingMessageSource dms = new DelegatingMessageSource();
          dms.setParentMessageSource(getInternalParentMessageSource());
          this.messageSource = dms;
          beanFactory.registerSingleton(MESSAGE_SOURCE_BEAN_NAME, this.messageSource);
          if (logger.isTraceEnabled()) {
             logger.trace("No '" + MESSAGE_SOURCE_BEAN_NAME + "' bean, using [" + this.messageSource + "]");
          }
       }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    initApplicationEventMulticaster逻辑

    1.从beanfactory获取前beanname为applicationEventMulticaster的bean,如果beanfactory不存在生成SimpleApplicationEventMulticaster对象为
    2.将1中得到的bean赋给beanfactory的属性applicationEventMulticaster
    扩展点:
    前面提到类ApplicationListenerDetector非常关键(调用beanfactory的addApplicationListener方法)

    public Object postProcessAfterInitialization(Object bean, String beanName) {
       if (bean instanceof ApplicationListener) {
          // potentially not detected as a listener by getBeanNamesForType retrieval
          Boolean flag = this.singletonNames.get(beanName);
          if (Boolean.TRUE.equals(flag)) {
             // singleton bean (top-level or inner): register on the fly
             this.applicationContext.addApplicationListener((ApplicationListener<?>) bean);
          }
          else if (Boolean.FALSE.equals(flag)) {
             if (logger.isWarnEnabled() && !this.applicationContext.containsBean(beanName)) {
                // inner bean with other scope - can't reliably process events
                logger.warn("Inner bean '" + beanName + "' implements ApplicationListener interface " +
                      "but is not reachable for event multicasting by its containing ApplicationContext " +
                      "because it does not have singleton scope. Only top-level listener beans are allowed " +
                      "to be of non-singleton scope.");
             }
             this.singletonNames.remove(beanName);
          }
       }
       return bean;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21

    他在bean初始化如查发现bean是ApplicationListener接口实现会通过beanfactory的属性applicationEventMulticaster的方法addApplicationListener让bean也可侦听事件,比如下类

    @Component
    public class UserService implements ApplicationListener {
       public void test() {
          System.out.println("test");
       }
       @Override
       public void onApplicationEvent(ApplicationEvent event) {
          System.out.println(this.getClass().getName()+" trigger event:"+event.getSource());
       }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    另外我们需要准备以下类(若不准备就利用spring内部的SimpleApplicationEventMulticaster来侦听所有事件,不能客制化侦听所需的事件):

    @Component(AbstractApplicationContext.APPLICATION_EVENT_MULTICASTER_BEAN_NAME)
    public class MyApplicationEventMulticaster extends AbstractApplicationEventMulticaster {
       private ArrayList<ApplicationListener>  applicationListeners=new ArrayList<ApplicationListener>();
       @Override
       public void addApplicationListener(ApplicationListener<?> listener) {
           applicationListeners.add(listener);
       }
    
       @Override
       public void multicastEvent(ApplicationEvent event) {
          System.out.println(this.getClass().getName()+" multicastEvent "+ event);
       }
    
       @Override
       public void multicastEvent(ApplicationEvent event, ResolvableType eventType) {
          System.out.println(this.getClass().getName()+" multicastEvent+ResolvableType "+ event.getSource()+" "+applicationListeners.size());
          for(ApplicationListener listener:applicationListeners){
             listener.onApplicationEvent(event);
          }
       }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21

    这样的话我们向beanfactory发布事件时@Compoent类才能侦听事件,上面的addApplicationListener方法必须实现,否则实现了ApplicationListener 接口bean无法侦听到事件
    applicationContext.publishEvent(new ApplicationEvent(“test event”));
    当然这里的事件你可以自定义一个ApplicationEvent接口实现类,然后在MyApplicationEventMulticaster.multicastEvent方法event是否为自定义类型来侦听自已的事件

    onRefresh()逻辑

    这里没有用处,如果不是用于web,主要生成ResourceBundleThemeSource对象给beanfactory属性themeSource
    registerListeners()逻辑

    1. 将beanfactory属性applicationListeners的ApplicationListener对对象放入beanfactory的applicationEventMulticaster.defaultRetriever.applicationListeners中,通过调用getApplicationEventMulticaster().addApplicationListener(listener)方来实现,如果beanfactory中的APPLICATION_EVENT_MULTICASTER_BEAN_NAME是AbstractApplicationEventMulticaster子类,得确认是否覆盖此方法,确认listener如何放
      但是在启动阶段applicationListeners里没有数据

    2. 从beanforty里所有beandefinition里找出实现ApplicationListener类beanname放入applicationEventMulticaster.defaultRetriever.applicationListenerBeans中
      这一步其实和ApplicationListenerDetector.postProcessAfterInitialization()方法其实是重复逻辑,搞不清为什么要进行两次

    finishBeanFactoryInitialization逻辑

    1. 确认beanfactory有没有conversionService bean,如有指定给beanfactory的属性conversionService
    2. 执行以下内容,功能未知,后面在分析
    if (!beanFactory.hasEmbeddedValueResolver()) {
       beanFactory.addEmbeddedValueResolver(strVal -> getEnvironment().resolvePlaceholders(strVal));
    }
    
    • 1
    • 2
    • 3
    1. 确认beandefinition中是否有LoadTimeWeaverAware接口实现类,如果进地实列化bean
    2. 将beanfactory的属性configurationFrozen变为true,意味着类解析已完成
    3. 根据所有内容beandefinition加载非lazy-init、非抽象bean,非要是通过getBean方法来实进行
      AbstractBeanFactory.getBean()逻辑较为复杂单独整理

    finishRefresh逻辑

    1. 确认beanfactory有没有自定义lifecycleProcessor bean,若没有用DefaultLifecycleProcessor生成bean,并指定给beanfactory的属性lifecycleProcessor
    2. 调用lifecycleProcess 的onrefresh()方法,右启动时没定义lifecycleProcessor bean,将执行
      DefaultLifecycleProcessor.onrefresh()方法,调用beanfactory中所有实现Lifecycle接口bean的start()方法,包括lifecycleProcessor
      bean的start()方法
    3. 向beanfactory pulish事件ContextRefreshedEvent
    4. 向ManagementFactory注册beanfactory

    总结

    从上面整理的spring启动逻辑, invokeBeanFactoryPostProcessors至关重要,主要带有@Configuration的类比较重要,主要是得到整个系统需要生成的bean definition信息,主要是通过java的反射机制和cglib技术得到class的相关信息。

  • 相关阅读:
    【pen200-lab】10.11.1.5
    Dcoker学习笔记(一)
    MST56XXB 60V,150mA,2.1uA,高PSRR,高压低压差线性稳压器
    华为OD机试 - 敏感字段加密(Java 2023 B卷 100分)
    ky10 server x86 安装、更新openssl3.1.4(在线编译安装、离线安装)
    DDoS渗透与攻防实战 (一) : 初识DDoS
    关于稳定扩散最详细的介绍
    深入理解 Dockerfile 和 docker-compose[实战篇]
    4. MongoDB部署
    Slim GAIN(SGAIN)介绍及代码实现——基于生成对抗网络的缺失数据填补
  • 原文地址:https://blog.csdn.net/lin000_0/article/details/127914799