为了简化bean的配置,spring提供了注解方式,用来取代xml配置文件。在spring中管理注解的bean定义容器有两个:AnnotationConfigApplicationContext、AnnotationConfigWebApplicationContext,两者的用法以及对注解的处理几乎没有区别。这里以AnnotationConfigApplicationContext为例。

容器初始化

先从AnnotationConfigApplicationContext的初始化看起。该容器会先初始化bean定义读取器和bean定义扫描,后续所有的操作都是基于这两者。在两者初始化完之后,在构造方法中会调用各自的register()或scan(),开始对bean的处理。

其中register()或scan(),是分别对注解处理的两种方式。

  1. register(),直接将需要注册的bean传入,注册到IOC中
  2. scan(),通过传入指定包,扫描包下及其子包下的所有类进行处理
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
public class AnnotationConfigApplicationContext extends GenericApplicationContext implements AnnotationConfigRegistry {

private final AnnotatedBeanDefinitionReader reader;
private final ClassPathBeanDefinitionScanner scanner;

// 每个构造最后都会调用此构造,初始化reader和scanner
public AnnotationConfigApplicationContext() {
this.reader = new AnnotatedBeanDefinitionReader(this);
this.scanner = new ClassPathBeanDefinitionScanner(this);
}

public AnnotationConfigApplicationContext(DefaultListableBeanFactory beanFactory) {
super(beanFactory);
this.reader = new AnnotatedBeanDefinitionReader(this);
this.scanner = new ClassPathBeanDefinitionScanner(this);
}

// 传入配置类,实现相应配置类中bean自动注册到容器中
public AnnotationConfigApplicationContext(Class<?>... annotatedClasses) {
this();
register(annotatedClasses);
refresh();
}

// 扫描指定包路径下的所有类,自动识别所有spring bean,并注册到容器中。
public AnnotationConfigApplicationContext(String... basePackages) {
this();
scan(basePackages);
refresh();
}

// 为容器注册一个要被处理的注解bean,新注册的bean,需手动调用refresh()方法,触发IOC对新注册bean的处理
public void register(Class<?>... annotatedClasses) {
Assert.notEmpty(annotatedClasses, "At least one annotated class must be specified");
this.reader.register(annotatedClasses);
}

// 扫描指定包路径下的注解类,同样的新注册的bean,需手动调用refresh()方法
public void scan(String... basePackages) {
Assert.notEmpty(basePackages, "At least one base package must be specified");
this.scanner.scan(basePackages);
}
}

从上述代码中,可以看到,该容器在启动时会调用register()、scan()方法,而这两个方法为public,也可以由使用者在容器创建之后调用新注册的bean。但是需要注意的是,新注册的bean,必须手动调用refresh(),spring才会对其做后续的处理。

注册指定的bean

点击查看

扫描指定包bean定义

点击查看