1.创建AnnotationConfigApplicationContext
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext("com.eragon");
这里传的参数是包名,spring会自动扫描该包下所有的类,对bean进行配置。
public AnnotationConfigApplicationContext(String... basePackages) {
// 初始化AnnotatedBeanDefinitionReader和ClassPathBeanDefinitionScanner
this();
// 对包进行扫描
scan(basePackages);
// 刷新容器
refresh();
}
我们先来看scan(basePackages),对包下所有类的扫描
public void scan(String... basePackages) {
Assert.notEmpty(basePackages, "At least one base package must be specified");
this.scanner.scan(basePackages);
}
public int scan(String... basePackages) {
// 当前容器已注册的bean的个数
int beanCountAtScanStart = this.registry.getBeanDefinitionCount();
// 真正扫描包的方法
doScan(basePackages);
// Register annotation config processors, if necessary.
if (this.includeAnnotationConfig) {
AnnotationConfigUtils.registerAnnotationConfigProcessors(this.registry);
}
return (this.registry.getBeanDefinitionCount() - beanCountAtScanStart);
}
doScan(basePackages):
protected Set<BeanDefinitionHolder> doScan(String... basePackages) {
// 断言,package至少有一个
Assert.notEmpty(basePackages, "At least one base package must be specified");
// 使用BeanDefinitionHolder封装
Set<BeanDefinitionHolder> beanDefinitions = new LinkedHashSet<>();
for (String basePackage : basePackages) {
// 获得所有需要注册的bean(主要是使用了@Compoment注解的类)
Set<BeanDefinition> candidates = findCandidateComponents(basePackage);
// 注册bean
for (BeanDefinition candidate : candidates) {
ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(candidate);
// 设置scope
candidate.setScope(scopeMetadata.getScopeName());
// 获得beanName
String beanName = this.beanNameGenerator.generateBeanName(candidate, this.registry);
if (candidate instanceof AbstractBeanDefinition) {
/**
* 处理@Autowire当能找到多个类时的问题,会根据scan.setAutowireCandidatePatterns
* 设置的匹配规则查找对应的bean
*/
postProcessBeanDefinition((AbstractBeanDefinition) candidate, beanName);
}
if (candidate instanceof AnnotatedBeanDefinition) {
/**
* BeanDefinition设置一些常规的属性,比如lazy,role等,
*/
AnnotationConfigUtils.processCommonDefinitionAnnotations((AnnotatedBeanDefinition) candidate);
}
// 校验beanName必须唯一
if (checkCandidate(beanName, candidate)) {
BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(candidate, beanName);
/**
* 是否需要代理,分为cglib和jdk两种动态代理方式
*/
definitionHolder =
AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);
beanDefinitions.add(definitionHolder);
/**
* 注册beanDefinition到容器中
*/
registerBeanDefinition(definitionHolder, this.registry);
}
}
}
return beanDefinitions;
}
registerBeanDefinition()在xml的注册中已经跟踪过,就是把beanDefinition放到容器里,这里省略。
总结:
通过注解方式的注册Bean和XML基本逻辑都是一样,先解析再注册,我们发现从源码层面通过注解的方式配置Bean比XML方式简洁的多,所以Spring也推荐使用注解。