启动Spring应用
只需简单的几行代码便可声明、创建一个Spring应用容器。
1 | AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(BasicConfig.class); |
创建容器
在进入到 new AnnotationConfigApplicationContext()
方法后,进行对容器的声明和创建。其中会先对给定的配置文件类进行校验和注册。调用过程草图如下所示(仅参考):
可以看到基本的调用顺序,下面根据图中所示,针对调用的方法进行源码的分析。
创建 AnnotationConfigApplicationContext
创建对象
因为在使用 new AnnotationConfigApplicationContext()
创建对象时会默认调用父类的无参构造函数,也就是默认调用 super()
方法。根据图中的类继承结构,看看在父类中都定义了哪些对象,并且这些对象的作用是什么。
- 首先在AnnotationConfigApplicationContext继承了GenericApplicationContext,在构造方法内创建了beanFactory
1 | public GenericApplicationContext() { |
- GenericApplicationContext 继承 AbstractApplicationContext,在构造方法内定义了resourcePatternResolver
1 | public AbstractApplicationContext() { |
- AbstractApplicationContext 继承了 DefaultResourceLoader,在构造方法内定义了 classLoader
1 | public DefaultResourceLoader() { |
通过上述代码和分析可以发现调用 new AnnotationConfigApplicationContext()
时会通过调用父类的无参构造函数鬼定义如下内容:
- 设置
beanFactory
为DefaultListableBeanFactory
类型 - 设置
resourcePatternResolver
为PathMatchingResourcePatternResolver
类型 - 设置
classLoader
为默认的线程环境的classLoader
1 | public AnnotationConfigApplicationContext(Class<?>... componentClasses) { |
调用构造函数时可以发现他会先初始化一个 reader
和一个 sacnner
。 分别的作用为 :
AnnotatedBeanDefinitionReader
用于以编程方式注册Bean类,这些Bean主要指的时一些PostProcessorClassPathBeanDefinitionScanner
一个可在类路径上搜索候选bean的bean定义扫描器。
AnnotatedBeanDefinitionReader
用于以编程方式注册Bean类,这些Bean主要指的是一些PostProcessor。
1 | public AnnotatedBeanDefinitionReader(BeanDefinitionRegistry registry, Environment environment) { |
通过代码总结一下,在new AnnotatedBeanDefinitionReader 的时候,都做了些什么;
- 将 AnnotationConfigApplicationContext 作为 register 设置到AnnotatedBeanDefinitionReader中
- 设置 ConditionEvaluator 用作与对 @Condition 的解析
- 在给定的register也就是AnnotationConfigApplicationContext中注册所有相关的注解后置处理器。
- 添加BeanFactory的相关属性,DependencyComparator和AutowireCandidateResolver
- 注册ConfigurationClassPostProcessor 用于解析
@Configuration
注解标注的类 - 注册AutowiredAnnotationBeanPostProcessor用于解析
@Autowire
注解标注的类 - 注册 CommonAnnotationBeanPostProcessor 用于解析
JSR-250
相关注解,如Resource、EJB、WebServiceRef - 注册PersistenceAnnotationBeanPostProcessor用于解析
JPA相关
注解 - 注册EventListenerMethodProcessor、DefaultEventListenerFactory用于事件监听
ClassPathBeanDefinitionScanner
一个可在类路径上搜索候选bean的bean定义扫描器。
1 | public ClassPathBeanDefinitionScanner(BeanDefinitionRegistry registry, boolean useDefaultFilters, |
其中最重要的是使用ClassPathScanningCandidateComponentProvider
类中 registerDefaultFilters
方法注册默认的过滤器,主要包含三部分
- 为@Component,同时保证了Repository、Service、Controller这四个注解添加过滤器
- 为 ManagedBean(JSR-250) 添加过滤器
- 为 Named(JSR-330) 添加过滤器
register 注册给定配置类
1 |
|
registerBean
在上一步的 registerBean 中调用了已经创建好的 AnnotatedBeanDefinitionReader
的 registerBean
方法:
1 | public void register(Class<?>... componentClasses) { |
对每一个 class 循环调用 doRegisterBean
方法进行 对 BeanClass
的注册操作。
doRegisterBean
在doRegisterBean中分为如下几步进行操作:
- 声明
BeanDefinition
为AnnotatedGenericBeanDefinition
。 - 通过
conditionEvaluator.shouldSkip()
方法通过对 @Conditional 注解来判断是否跳过注册 - 通过
scopeMetadataResolver.resolveScopeMetadata
来获取作用域,然后再放到 BeanDefinition 中。 - 通过
beanNameGenerator.generateBeanName
来设置Bean在容器中的名称。 - 通过
processCommonDefinitionAnnotations
设置Bean的基本属性 - 最后通过 调用
registerBeanDefinition
对包装好的 BeanDefinitionHolder 进行最后的注册操作。
1 | private <T> void doRegisterBean(Class<T> beanClass, @Nullable String name, |
registerBeanDefinition
1 | public static void registerBeanDefinition( |
之后会调用 DefaultListableBeanFactory
中的 registBeanDefinition
方法对Bean进行注册。
实际的注册过程就是将Bean的名称
作为key,Bean的BeanDefinition
作为value存储在一个全局的beanDefinitionMap
中。
1 | synchronized (this.beanDefinitionMap) { |
至此,Spring容器的创建,和对配置文件的注册就完成了。