Spring的启动和注册

启动Spring应用

只需简单的几行代码便可声明、创建一个Spring应用容器。

1
2
3
4
5
6
7
8
9
10
11
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(BasicConfig.class);

// 前提是需要传入给定的class配置类
@Configuration // 使用Configuration 表明是个配置类
@ComponentScan("com.nanyin")//扫描包
public class BasicConfig {
@Bean("person")
public Person person(){
return new Person("1","2");
}
}

创建容器

在进入到 new AnnotationConfigApplicationContext() 方法后,进行对容器的声明和创建。其中会先对给定的配置文件类进行校验和注册。调用过程草图如下所示(仅参考):

创建容器.png

可以看到基本的调用顺序,下面根据图中所示,针对调用的方法进行源码的分析。

创建 AnnotationConfigApplicationContext

创建对象

20191123153835.png

因为在使用 new AnnotationConfigApplicationContext() 创建对象时会默认调用父类的无参构造函数,也就是默认调用 super() 方法。根据图中的类继承结构,看看在父类中都定义了哪些对象,并且这些对象的作用是什么。

  • 首先在AnnotationConfigApplicationContext继承了GenericApplicationContext,在构造方法内创建了beanFactory
1
2
3
public GenericApplicationContext() {
this.beanFactory = new DefaultListableBeanFactory();
}
  • GenericApplicationContext 继承 AbstractApplicationContext,在构造方法内定义了resourcePatternResolver
1
2
3
4
5
6
public AbstractApplicationContext() {
this.resourcePatternResolver = getResourcePatternResolver();
}
protected ResourcePatternResolver getResourcePatternResolver() {
return new PathMatchingResourcePatternResolver(this);
}
  • AbstractApplicationContext 继承了 DefaultResourceLoader,在构造方法内定义了 classLoader
1
2
3
public DefaultResourceLoader() {
this.classLoader = ClassUtils.getDefaultClassLoader();
}

通过上述代码和分析可以发现调用 new AnnotationConfigApplicationContext() 时会通过调用父类的无参构造函数鬼定义如下内容:

  1. 设置 beanFactoryDefaultListableBeanFactory 类型
  2. 设置 resourcePatternResolverPathMatchingResourcePatternResolver 类型
  3. 设置 classLoader 为默认的线程环境的 classLoader
1
2
3
4
5
6
7
8
9
10
public AnnotationConfigApplicationContext(Class<?>... componentClasses) {
this();
register(componentClasses); //注册给定的配置类Bean
refresh(); //刷新方法
}
// this调用空的构造函数,其中制定了 AnnotatedBeanDefinitionReader 和 ClassPathBeanDefinitionScanner
public AnnotationConfigApplicationContext() {
this.reader = new AnnotatedBeanDefinitionReader(this);
this.scanner = new ClassPathBeanDefinitionScanner(this);
}

调用构造函数时可以发现他会先初始化一个 reader 和一个 sacnner。 分别的作用为 :

  1. AnnotatedBeanDefinitionReader 用于以编程方式注册Bean类,这些Bean主要指的时一些PostProcessor
  2. ClassPathBeanDefinitionScanner 一个可在类路径上搜索候选bean的bean定义扫描器。

AnnotatedBeanDefinitionReader

用于以编程方式注册Bean类,这些Bean主要指的是一些PostProcessor。

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
public AnnotatedBeanDefinitionReader(BeanDefinitionRegistry registry, Environment environment) {
Assert.notNull(registry, "BeanDefinitionRegistry must not be null");
Assert.notNull(environment, "Environment must not be null");
this.registry = registry;
//ConditionEvaluator 用于对 @Condition 注解的评估
this.conditionEvaluator = new ConditionEvaluator(registry, environment, null);
AnnotationConfigUtils.registerAnnotationConfigProcessors(this.registry);
}
/**
* 处理相关注解的后置处理器如 ConfigurationClassPostProcessor 等
*/
public static Set<BeanDefinitionHolder> registerAnnotationConfigProcessors(
BeanDefinitionRegistry registry, @Nullable Object source) {
// 获取 BeanFactory,其实这里返回了一个this.beanFactory,也就是 DefaultListableBeanFactory
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());
}
}

Set<BeanDefinitionHolder> beanDefs = new LinkedHashSet<>(8);
// 注册ConfigurationClassPostProcessor 也就是对应的@Configuration注解postprocessor
if (!registry.containsBeanDefinition(CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME)) {
RootBeanDefinition def = new RootBeanDefinition(ConfigurationClassPostProcessor.class);
def.setSource(source);
beanDefs.add(registerPostProcessor(registry, def, CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME));
}
// 注册AutowiredAnnotationBeanPostProcessor,对应的时@Autowired对应的postProcessor
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));
}
// ........
return beanDefs;
}

通过代码总结一下,在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
2
3
4
5
6
7
8
9
10
11
12
13
public ClassPathBeanDefinitionScanner(BeanDefinitionRegistry registry, boolean useDefaultFilters,
Environment environment, @Nullable ResourceLoader resourceLoader) {

Assert.notNull(registry, "BeanDefinitionRegistry must not be null");
this.registry = registry;

if (useDefaultFilters) {
registerDefaultFilters();
}
// 这里的environment时在父类中的构造函数中给出的 new StandardEnvironment()
setEnvironment(environment);
setResourceLoader(resourceLoader);
}

其中最重要的是使用ClassPathScanningCandidateComponentProvider类中 registerDefaultFilters 方法注册默认的过滤器,主要包含三部分

  • 为@Component,同时保证了Repository、Service、Controller这四个注解添加过滤器
  • 为 ManagedBean(JSR-250) 添加过滤器
  • 为 Named(JSR-330) 添加过滤器

register 注册给定配置类

1
2
3
4
5
6
7
8
9
10
11
12
@Override
public void register(Class<?>... componentClasses) {
Assert.notEmpty(componentClasses, "At least one component class must be specified");
this.reader.register(componentClasses); //调用 AnnotatedBeanDefinitionReader 的register 方法
}

public void register(Class<?>... componentClasses) {
for (Class<?> componentClass : componentClasses) {
// 对每个给定的class进行 registerBean
registerBean(componentClass);
}
}

registerBean

在上一步的 registerBean 中调用了已经创建好的 AnnotatedBeanDefinitionReaderregisterBean方法:

1
2
3
4
5
6
7
8
9
10
public void register(Class<?>... componentClasses) {
for (Class<?> componentClass : componentClasses) {
// 对每个给定的class进行 registerBean
registerBean(componentClass);
}
}

public void registerBean(Class<?> beanClass) {
doRegisterBean(beanClass, null, null, null, null);
}

对每一个 class 循环调用 doRegisterBean 方法进行 对 BeanClass 的注册操作。

doRegisterBean

在doRegisterBean中分为如下几步进行操作:

  1. 声明 BeanDefinitionAnnotatedGenericBeanDefinition
  2. 通过 conditionEvaluator.shouldSkip() 方法通过对 @Conditional 注解来判断是否跳过注册
  3. 通过 scopeMetadataResolver.resolveScopeMetadata 来获取作用域,然后再放到 BeanDefinition 中。
  4. 通过 beanNameGenerator.generateBeanName 来设置Bean在容器中的名称。
  5. 通过 processCommonDefinitionAnnotations 设置Bean的基本属性
  6. 最后通过 调用registerBeanDefinition 对包装好的 BeanDefinitionHolder 进行最后的注册操作。
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
private <T> void doRegisterBean(Class<T> beanClass, @Nullable String name,
@Nullable Class<? extends Annotation>[] qualifiers, @Nullable Supplier<T> supplier,
@Nullable BeanDefinitionCustomizer[] customizers) {

AnnotatedGenericBeanDefinition abd = new AnnotatedGenericBeanDefinition(beanClass);
if (this.conditionEvaluator.shouldSkip(abd.getMetadata())) {
// 通过判断Conditional注解,来判断是否跳过
return;
}
//处理创建的回调
abd.setInstanceSupplier(supplier);
ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(abd);
// 处理作用域 放到scopeMetadata里面
abd.setScope(scopeMetadata.getScopeName());//再放到 BeanDefinition 里
String beanName = (name != null ? name : this.beanNameGenerator.generateBeanName(abd, this.registry)); //设置BeanName

AnnotationConfigUtils.processCommonDefinitionAnnotations(abd);
// 设置一些基本属性 如 Lazy,Primary 。。。
if (qualifiers != null) {
for (Class<? extends Annotation> qualifier : qualifiers) {
if (Primary.class == qualifier) {
abd.setPrimary(true);
}
else if (Lazy.class == qualifier) {
abd.setLazyInit(true);
}
else {
abd.addQualifier(new AutowireCandidateQualifier(qualifier));
}
}
}
if (customizers != null) {
for (BeanDefinitionCustomizer customizer : customizers) {
customizer.customize(abd);
}
}

BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(abd, beanName); // 创建一个definitionHolder,作用是 具有名称和别名的BeanDefinition的持有人
definitionHolder = AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry); //设置作用域
BeanDefinitionReaderUtils.registerBeanDefinition(definitionHolder, this.registry);
}

registerBeanDefinition

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public static void registerBeanDefinition(
BeanDefinitionHolder definitionHolder, BeanDefinitionRegistry registry)
throws BeanDefinitionStoreException {

String beanName = definitionHolder.getBeanName();
registry.registerBeanDefinition(beanName, definitionHolder.getBeanDefinition());

// 注册别名
String[] aliases = definitionHolder.getAliases();
if (aliases != null) {
for (String alias : aliases) {
registry.registerAlias(beanName, alias);
}
}
}

之后会调用 DefaultListableBeanFactory 中的 registBeanDefinition 方法对Bean进行注册。

实际的注册过程就是将Bean的名称作为key,Bean的BeanDefinition作为value存储在一个全局的beanDefinitionMap中。

1
2
3
4
5
6
7
8
synchronized (this.beanDefinitionMap) {
this.beanDefinitionMap.put(beanName, beanDefinition); //实际上就是一个ConcurrentHashMap 存储 beanDefinition 使用BeanName作为Key
List<String> updatedDefinitions = new ArrayList<>(this.beanDefinitionNames.size() + 1); // 添加到updatedDefinitions里面
updatedDefinitions.addAll(this.beanDefinitionNames);
updatedDefinitions.add(beanName);
this.beanDefinitionNames = updatedDefinitions;
removeManualSingletonName(beanName);
}

至此,Spring容器的创建,和对配置文件的注册就完成了。

-------------本文结束感谢您的阅读-------------

本文标题:Spring的启动和注册

文章作者:NanYin

发布时间:2019年12月05日 - 15:12

最后更新:2020年07月16日 - 22:07

原始链接:https://nanyiniu.github.io/2019/12/05/Spring%E4%BB%8E%E9%9B%B6%E5%BC%80%E5%A7%8B%E4%B9%8B%E6%BA%90%E7%A0%81%E5%88%86%E6%9E%90%EF%BC%88%E4%B8%80%EF%BC%89/

许可协议: 署名-非商业性使用-禁止演绎 4.0 国际 转载请保留原文链接及作者。