bg:25届毕业生,目前在实习,记录一下学习成长过程中的感悟。
个人心得:如果没有源码阅读经验的新手在刚接触源码的时候很容易晕头转向。网上关于Spring源码的资料和视频很多,但是都很杂,而且每个人的痛点都不一样,就需要从各个资料中去整合。这个过程。。。非常的痛苦。下面就具体说明一下我的学习方式和个人理解,理解有误的地方欢迎指正。
Spring IOC流程
根据流程图可以看IOC容器创建Bean对象可以大致分为三步:
1. 读取BeanDefinition(Bean定义信息)
2. 实例化(创建Bean)
3. 初始化(填充Bean)
读取BeanDefinition
Spring两大容器BeanFactory和ApplicationContext我就不介绍了,这里详细介绍一下ApplicationContext的实现子类AnnotationConfigApplicationContext(注解)以及对比一下ClassPathXmlApplicationContext(XML)。
两个类的构造函数都调用了refresh()方法,该方法继承于AbstractApplicationContext,也是容器管理Bean的主要方法。Spring要想管理Bean,首先要先new一个BeanFactory容器,依托这个容器去管理。这两个类第一个不同的地方就在于容器创建时间,AnnotationConfigApplicationContext在调用this()无参构造的同时会调用父类GenericApplicationContext的无参构造new一个DefaultListableBeanFactory。而ClassPathXmlApplicationContext发生在refresh()中的obtainFreshBeanFactory()方法。在容器准备就绪后就可以开始读取Beandefinition了。
第二个不同也来了,AnnotationConfigApplicationContext使用scan()方法读取,而ClassPathXmlApplicationContext同样发生在obtainFreshBeanFactory()方法里的
loadBeanDefinitions()方法中。接下来具体讲一下scan()方法。
scan()方法通过一次次套娃的重写和调用,定位到一个重要方法doScan()。在该方法中有一个findCandidateComponents()方法会去读取候选的BeanDefinition,也就是加了@Components注解的Bean。该方法首先会通过读取Resource的方式将指定包下的class文件读取出来,再通过isCandidateComponent()方法判断是否添加了@Components注解,在isCandidateComponent()方法中可以看到一个includeFilters,而这个list里Components的值哪里来的呢?这就要回到AnnotationConfigApplicationContext的构造函数了,在构造函数里new了一个ClassPathBeanDefinitionScanner。顺着这个scanner的构造函数能找到registerDefaultFilters()方法,在这个方法里将Components注册到了includeFilters。
protected Set<BeanDefinitionHolder> doScan(String... basePackages) {
Assert.notEmpty(basePackages, "At least one base package must be specified");
Set<BeanDefinitionHolder> beanDefinitions = new LinkedHashSet<>();
for (String basePackage : basePackages) {
Set<BeanDefinition> candidates = findCandidateComponents(basePackage);
for (BeanDefinition candidate : candidates) {
ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(candidate);
candidate.setScope(scopeMetadata.getScopeName());
String beanName = this.beanNameGenerator.generateBeanName(candidate, this.registry);
if (candidate instanceof AbstractBeanDefinition) {
postProcessBeanDefinition((AbstractBeanDefinition) candidate, beanName);
}
if (candidate instanceof AnnotatedBeanDefinition) {
AnnotationConfigUtils.processCommonDefinitionAnnotations((AnnotatedBeanDefinition) candidate);
}
if (checkCandidate(beanName, candidate)) {
BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(candidate, beanName);
definitionHolder =
AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);
beanDefinitions.add(definitionHolder);
registerBeanDefinition(definitionHolder, this.registry);
}
}
}
return beanDefinitions;
}
protected boolean isCandidateComponent(MetadataReader metadataReader) throws IOException {
for (TypeFilter tf : this.excludeFilters) {
if (tf.match(metadataReader, getMetadataReaderFactory())) {
return false;
}
}
for (TypeFilter tf : this.includeFilters) {
if (tf.match(metadataReader, getMetadataReaderFactory())) {
return isConditionMatch(metadataReader);
}
}
return false;
}
有了候选BeanDefinition之后,通过对这些BeanDefinition进行扩展处理、封装等操作,开始通过registerBeanDefinition()方法注册。同样的,通过一次次的套娃重写和调用,会来到DefaultListableBeanFactory的registerBeanDefinition(),该方法会把BeanDefinition注册到beanDefinitionMap中。至此读取BeanDefinition工作告一段落。
if (hasBeanCreationStarted()) {
// Cannot modify startup-time collection elements anymore (for stable iteration)
synchronized (this.beanDefinitionMap) {
this.beanDefinitionMap.put(beanName, beanDefinition);
List<String> updatedDefinitions = new ArrayList<>(this.beanDefinitionNames.size() + 1);
updatedDefinitions.addAll(this.beanDefinitionNames);
updatedDefinitions.add(beanName);
this.beanDefinitionNames = updatedDefinitions;
removeManualSingletonName(beanName);
}
}
else {
// Still in startup registration phase
this.beanDefinitionMap.put(beanName, beanDefinition);
this.beanDefinitionNames.add(beanName);
removeManualSingletonName(beanName);
}
this.frozenBeanDefinitionNames = null;}
剩下的后续慢慢写。。。