spring 5.0.x源码学习系列三: spring context无参构造方法的作用

前言

后续的所有文章将开始围绕上篇博客:spring 5.0.x源码学习系列二: 从AnnotationConfigApplicationContext开始,进入spring世界的运行流程图展开, 并根据实际的代码来详细解析。接下来开始进入正文

一、AnnotationConfigApplicationContext的无参构造方法

上篇博客(上面有链接, 可以自行查看)中,大致介绍了无参构造方法的主要作用, 接下来将根据源码详细介绍.

1.1 项目demo

项目结构非常简单,大致结构如下:
spring 5.0.x源码学习系列三: spring context无参构造方法的作用_第1张图片
spring 5.0.x源码学习系列三: spring context无参构造方法的作用_第2张图片spring 5.0.x源码学习系列三: spring context无参构造方法的作用_第3张图片

1.2 debug运行项目

1. 进入带参AnnotationConfigApplicationContext构造方法

spring 5.0.x源码学习系列三: spring context无参构造方法的作用_第4张图片

2. 调用无参构造方法, 但因为继承了GenericApplicationContext类, 所以要先执行父类的无参构造方法, 此时实例化了bean工厂

spring 5.0.x源码学习系列三: spring context无参构造方法的作用_第5张图片

3. bean工厂初始化完毕

spring 5.0.x源码学习系列三: spring context无参构造方法的作用_第6张图片

4. 实例化AnnotationBeanDefinitionReader

spring 5.0.x源码学习系列三: spring context无参构造方法的作用_第7张图片

5. AnnotationBeanDefinitionReader自己维护了spring的上下文, 并开始准备注册spring的6个内置bean

spring 5.0.x源码学习系列三: spring context无参构造方法的作用_第8张图片

6. 重载方法

spring 5.0.x源码学习系列三: spring context无参构造方法的作用_第9张图片

7. 从BeanDefinitionRegistry中获取bean工厂

spring 5.0.x源码学习系列三: spring context无参构造方法的作用_第10张图片
spring 5.0.x源码学习系列三: spring context无参构造方法的作用_第11张图片
spring 5.0.x源码学习系列三: spring context无参构造方法的作用_第12张图片

8. 注册spring的六个内置bean(这些bean的作用是后置处理器)

  • 源码注释图

    spring 5.0.x源码学习系列三: spring context无参构造方法的作用_第13张图片

  • 判断是否存在beanName

        //AbstractApplicationContext.java
        @Override
        public boolean containsBeanDefinition(String beanName) {
            // getBeanFactory()获取的是DefaultListableBeanFactory, 
            // 所有会进到DefaultListableBeanFactory的containsBeanDefinition
            // 方法中
            return getBeanFactory().containsBeanDefinition(beanName);
        }
    
        // DefaultListableBeanFactory.java
        @Override
        public boolean containsBeanDefinition(String beanName) {
            Assert.notNull(beanName, "Bean name must not be null");
            return this.beanDefinitionMap.containsKey(beanName);
        }
    • 注册spring内置bean源码

          // 注册spring内置bean的源码
          private static BeanDefinitionHolder registerPostProcessor(
                  BeanDefinitionRegistry registry, RootBeanDefinition definition, String beanName) {
      
              definition.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
              // 这行代码很重要, 在spring中基本上所有的beanDefinition的注册
              // 都要走BeanDefinitionRegistry的registerBeanDefinition方法。
              // spring的单一原则做的真好(真香!)
              // 这里的register又是哪个对象呢? 同样的它是AnnotationConfigApplicationContext
              // 但registerBeanDefinition方法的调用不在父类的父类, 
              // 而是在父类GenericApplicationContext中
              registry.registerBeanDefinition(beanName, definition);
              return new BeanDefinitionHolder(definition, beanName);
          }

9. 后面还有5个内置bean需要注册, 注册方式跟第八步大同小异,都是先判断是否存在再创建RootBeanDefinition再注册到bean工厂, 这里就不累述了

  • 具体还剩哪5个内置bean可以参考我的上一篇博客spring 5.0.x源码学习系列二: 从AnnotationConfigApplicationContext开始,进入spring世界的第一封流程图, 或者看下面的源码

        public static Set registerAnnotationConfigProcessors(
                BeanDefinitionRegistry registry, @Nullable Object source) {
            // 此处是为了获取bean工厂, 获取bean工厂的目的很简单, 就是为了注册spring内置的六个bean
            DefaultListableBeanFactory beanFactory = unwrapDefaultListableBeanFactory(registry);
            if (beanFactory != null) {
                // 不知道具体干啥的, 后面有机会再补充
                if (!(beanFactory.getDependencyComparator() instanceof AnnotationAwareOrderComparator)) {
                    beanFactory.setDependencyComparator(AnnotationAwareOrderComparator.INSTANCE);
                }
                
                // 添加一个上下文注解自动装配的候选解析器(具体做啥的, 目前还没研究到)
                if (!(beanFactory.getAutowireCandidateResolver() instanceof ContextAnnotationAutowireCandidateResolver)) {
                    beanFactory.setAutowireCandidateResolver(new ContextAnnotationAutowireCandidateResolver());
                }
            }
            // 存储BeanDefinitionHolder的set集合, 在注册spring内置bean这一过程中, 这个变量没用, 虽然方法中return了, 但调用的地方并没有接收它
            Set beanDefs = new LinkedHashSet<>(8);
    
            // 验证bean工厂中是否包含名字叫 "这么一长串的beanDefinition" - -!
            // 什么叫BeanDefinition呢? Java中描述一个类(比如常用的User类)是用
            // 类型为Class的类来描述, 在spring中是用BeanDefinition来描述一个bean
            // 的。使用过spring的人就明白, 一个beans可以设置有许多属性, 比如scope、lazy、description、bean的class、bean的name等等.
            // BeanDefinition就是用来存储这些信息的, 在spring创建bean时, 会拿到这个bean对应的beanDefinition信息来创建它。
            // BeanDefinition的类型有许多种, 比如: 现在看到的RootBeanDefinition、AnnotatedBeanDefinition、ScannedGenericBeanDefinition等等,
            // 每个bean都有不同的作用, 比如ScannedGenericBeanDefinition类型的beanDefinition,
            // 咱们可以为这样的beanDefinition手动设置它的自动装配模式(Mybatis集成spring的源码中利用了这一点,后续有机会再记录总结)。
            // 在往bean工厂注册beanDefinition时, 会往两个数据结构中存值, 一个是叫
            // beanDefinitionMap另一个叫beanDefinitionNames。顾名思义, 分别是用来存储beanDefinition(key为bean name)和bean name
            if (!registry.containsBeanDefinition(CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME)) {
                // spring内置bean的beanDefinition类型为RootBeanDefinition
                RootBeanDefinition def = new RootBeanDefinition(ConfigurationClassPostProcessor.class);
                // 传入的为null, 所以先不管它
                def.setSource(source);
                // 这行代码做了两件事, 一件是注册bean, 另一件是添加到beanDefs, 虽然它的方法名叫注册后置处理器, 但方法内部还是注册beanDefinition
                // 这里又用到了registry, 这个registry就是spring上下文
                beanDefs.add(registerPostProcessor(registry, def, CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME));
            }
    
            if (!registry.containsBeanDefinition(AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME)) {
                RootBeanDefinition def = new RootBeanDefinition(AutowiredAnnotationBeanPostProcessor.class);
                def.setSource(source);
                beanDefs.add(registerPostProcessor(registry, def, AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME));
            }
    
            if (!registry.containsBeanDefinition(REQUIRED_ANNOTATION_PROCESSOR_BEAN_NAME)) {
                RootBeanDefinition def = new RootBeanDefinition(RequiredAnnotationBeanPostProcessor.class);
                def.setSource(source);
                beanDefs.add(registerPostProcessor(registry, def, REQUIRED_ANNOTATION_PROCESSOR_BEAN_NAME));
            }
    
            // Check for JSR-250 support, and if present add the CommonAnnotationBeanPostProcessor.
            if (jsr250Present && !registry.containsBeanDefinition(COMMON_ANNOTATION_PROCESSOR_BEAN_NAME)) {
                RootBeanDefinition def = new RootBeanDefinition(CommonAnnotationBeanPostProcessor.class);
                def.setSource(source);
                beanDefs.add(registerPostProcessor(registry, def, COMMON_ANNOTATION_PROCESSOR_BEAN_NAME));
            }
    
            // Check for JPA support, and if present add the PersistenceAnnotationBeanPostProcessor.
            if (jpaPresent && !registry.containsBeanDefinition(PERSISTENCE_ANNOTATION_PROCESSOR_BEAN_NAME)) {
                RootBeanDefinition def = new RootBeanDefinition();
                try {
                    def.setBeanClass(ClassUtils.forName(PERSISTENCE_ANNOTATION_PROCESSOR_CLASS_NAME,
                            AnnotationConfigUtils.class.getClassLoader()));
                }
                catch (ClassNotFoundException ex) {
                    throw new IllegalStateException(
                            "Cannot load optional framework class: " + PERSISTENCE_ANNOTATION_PROCESSOR_CLASS_NAME, ex);
                }
                def.setSource(source);
                beanDefs.add(registerPostProcessor(registry, def, PERSISTENCE_ANNOTATION_PROCESSOR_BEAN_NAME));
            }
    
            if (!registry.containsBeanDefinition(EVENT_LISTENER_PROCESSOR_BEAN_NAME)) {
                RootBeanDefinition def = new RootBeanDefinition(EventListenerMethodProcessor.class);
                def.setSource(source);
                beanDefs.add(registerPostProcessor(registry, def, EVENT_LISTENER_PROCESSOR_BEAN_NAME));
            }
    
            if (!registry.containsBeanDefinition(EVENT_LISTENER_FACTORY_BEAN_NAME)) {
                RootBeanDefinition def = new RootBeanDefinition(DefaultEventListenerFactory.class);
                def.setSource(source);
                beanDefs.add(registerPostProcessor(registry, def, EVENT_LISTENER_FACTORY_BEAN_NAME));
            }
    
            return beanDefs;
        }

10. spring内置6个bean注册完毕

spring 5.0.x源码学习系列三: spring context无参构造方法的作用_第14张图片

11. this.scanner = new ClassPathBeanDefinitionScanner(this)

关于这行代码, 它是初始化一个ClassPath的扫描器, 它的作用是扫描@ComponentScan注解中提供的扫描路径, 但它并没有起到这个作用, 因为真正在解析@ComponentScan注解时, 是在内部新new了一个ClassPathBeanDefinitionScanner对象, 所以暂时没发现它有啥用, 先跳过它, 以后若发现它有其他作用再来补上

二、小结

  • AnnotationConfigApplicationContext类的无参构造方法的主要作用就是:初始化bean工厂注册spring的6个内置bean
  • 需要着重记住的几个东西:

    1. spring的bean工厂类: DefaultListableBeanFactory
    2. spring中最重要的内置bean: ConfigurationClassPostProcessor, 它的作用在refresh方法中会着重体现出来, 后续再总结
    3. BeanDefinition的定义: 描述spring bean的数据结构
    4. BeanDefinition的几种类型: RootBeanDefinitionAnnotatedGenericBeanDefinitionScannedGenericBeanDefinitionConfigurationClassBeanDefinition(配置类中方法中拥有@Bean注解的类会被定义成这个)
    5. spring上下文的几种身份: BeanDefinitionRegistryGenericApplicationContex
  • spring源码学习对应GitHub 地址https://github.com/AvengerEug/spring/tree/develop/resourcecode-study
  • I am a slow walker, but I never walk backwards.

你可能感兴趣的:(javaspring)