前言
后续的所有文章将开始围绕上篇博客:spring 5.0.x源码学习系列二: 从AnnotationConfigApplicationContext开始,进入spring世界的运行流程图展开, 并根据实际的代码来详细解析。接下来开始进入正文
一、AnnotationConfigApplicationContext的无参构造方法
上篇博客(上面有链接, 可以自行查看)中,大致介绍了无参构造方法的主要作用, 接下来将根据源码详细介绍.
1.1 项目demo
项目结构非常简单,大致结构如下:
1.2 debug运行项目
1. 进入带参AnnotationConfigApplicationContext构造方法
2. 调用无参构造方法, 但因为继承了GenericApplicationContext类, 所以要先执行父类的无参构造方法, 此时实例化了bean工厂
3. bean工厂初始化完毕
4. 实例化AnnotationBeanDefinitionReader
5. AnnotationBeanDefinitionReader自己维护了spring的上下文, 并开始准备注册spring的6个内置bean
6. 重载方法
7. 从BeanDefinitionRegistry中获取bean工厂
8. 注册spring的六个内置bean(这些bean的作用是后置处理器)
-
源码注释图
-
判断是否存在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注册完毕
11. this.scanner = new ClassPathBeanDefinitionScanner(this)
关于这行代码, 它是初始化一个ClassPath的扫描器, 它的作用是扫描@ComponentScan注解中提供的扫描路径, 但它并没有起到这个作用, 因为真正在解析@ComponentScan注解时, 是在内部新new了一个ClassPathBeanDefinitionScanner对象
, 所以暂时没发现它有啥用, 先跳过它, 以后若发现它有其他作用再来补上
二、小结
- AnnotationConfigApplicationContext类的无参构造方法的主要作用就是:初始化bean工厂、注册spring的6个内置bean
- 需要着重记住的几个东西:
- spring的bean工厂类:
DefaultListableBeanFactory
- spring中最重要的内置bean:
ConfigurationClassPostProcessor
, 它的作用在refresh
方法中会着重体现出来, 后续再总结 - BeanDefinition的定义:
描述spring bean的数据结构
- BeanDefinition的几种类型:
RootBeanDefinition
、AnnotatedGenericBeanDefinition
、ScannedGenericBeanDefinition
、ConfigurationClassBeanDefinition(配置类中方法中拥有@Bean注解的类会被定义成这个)
- spring上下文的几种身份:
BeanDefinitionRegistry
和GenericApplicationContex
- spring源码学习对应GitHub 地址https://github.com/AvengerEug/spring/tree/develop/resourcecode-study
- I am a slow walker, but I never walk backwards.