注意,看完这篇文章需要很长很长很长时间。。。
准备工作
本文会基于注解的方向分析SpringIOC模块的整体流程,在阅读本篇文章之前建议您先阅读基于XML分析的两篇文章: SpringIOC源码解析(上),SpringIOC源码解析(下)
Demo工程
本次源码分析的demo工程我已经准备好了,大家可自行前往以下地址下载
1
| https://github.com/shiyujun/spring-framework
|
本次工程复用了之前工程的包cn.shiyujun.service中的接口和实现类,同时新增了一个基于注解的配置类,此类在cn.shiyujun.config包下
1 2 3 4 5 6 7
| @Configuration public class AnnotationConfig { @Bean public IOCService iocService(){ return new IOCServiceImpl(); } }
|
然后就是启动类了,启动类在cn.shiyujun.demo包下
1 2 3 4 5 6 7
| public class AnnotationIOCDemo { public static void main (String args[]){ ApplicationContext context = new AnnotationConfigApplicationContext("cn.shiyujun.config"); IOCService iocService=context.getBean(IOCService.class); System.out.println(iocService.hollo()); } }
|
AnnotationConfigApplicationContext
继承关系
再次拿出之前的一张图片,可以看到相较于ClassPathXmlApplicationContext
和FileSystemXmlApplicationContext
来说AnnotationConfigApplicationContext
这个类的辈分好像更高一些
接着我们看一下它的方法
我们会发现除了register注册bean的方法以外,有一个scan方法,有没有感觉很熟悉。@CompantScan用过没,他们之间什么关系,在启动类中new AnnotationConfigApplicationContext的时候传的一个包名是不是跟这个有关系?带着疑问往下看吧
源码分析
构造方法
源码分析第一站就是进入如下构造方法
1 2 3 4 5
| public AnnotationConfigApplicationContext(String... basePackages) { this(); scan(basePackages); refresh(); }
|
千万不要小瞧上方简简单单的三行代码,我们整篇文章都会基于这三行代码来展开
首先看this
1 2 3 4 5 6
| public AnnotationConfigApplicationContext() { this.reader = new AnnotatedBeanDefinitionReader(this); this.scanner = new ClassPathBeanDefinitionScanner(this); }
|
同时子类的构造方法执行之前肯定会先执行父类的构造方法,所以还有父类
GenericApplicationContext的构造方法
1 2 3 4
| public GenericApplicationContext() { this.beanFactory = new DefaultListableBeanFactory(); }
|
注册bean
接着看scan
方法
1 2 3 4
| public void scan(String... basePackages) { Assert.notEmpty(basePackages, "At least one base package must be specified") this.scanner.scan(basePackages); }
|
可以看到这里调用的是bean扫描器ClassPathBeanDefinitionScanner
的scan
方法
1 2 3 4 5 6 7 8 9 10 11 12 13
| public int scan(String... basePackages) { int beanCountAtScanStart = this.registry.getBeanDefinitionCount(); doScan(basePackages);
if (this.includeAnnotationConfig) { AnnotationConfigUtils.registerAnnotationConfigProcessors(this.registry); } return (this.registry.getBeanDefinitionCount() - beanCountAtScanStart); }
|
接着往下看doScan
方法
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
| 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; }
|
扫描包
1 2 3 4 5 6 7 8 9 10
| public Set<BeanDefinition> findCandidateComponents(String basePackage) { if (this.componentsIndex != null && indexSupportsIncludeFilters()) { return addCandidateComponentsFromIndex(this.componentsIndex, basePackage); } else { return scanCandidateComponents(basePackage); }
|
在接着往下看之前,我们有必要先认识一个东东,MetadataReader。这个接口有三个方法
1 2 3 4 5 6 7 8 9
| public interface MetadataReader {
Resource getResource(); ClassMetadata getClassMetadata(); AnnotationMetadata getAnnotationMetadata();
}
|
第一个返回Resource就不必多说了,就是配置类的资源对象。第二个第三个根据名字我们可以猜到是类的元数据和注解的元数据
可以看一下它们两个的方法
接着往下看
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 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58
| private Set<BeanDefinition> scanCandidateComponents(String basePackage) { Set<BeanDefinition> candidates = new LinkedHashSet<>(); try { String packageSearchPath = ResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX + resolveBasePackage(basePackage) + '/' + this.resourcePattern; Resource[] resources = getResourcePatternResolver().getResources(packageSearchPath); boolean traceEnabled = logger.isTraceEnabled(); boolean debugEnabled = logger.isDebugEnabled(); for (Resource resource : resources) { if (traceEnabled) { logger.trace("Scanning " + resource); } if (resource.isReadable()) { try { MetadataReader metadataReader = getMetadataReaderFactory().getMetadataReader(resource); if (isCandidateComponent(metadataReader)) { ScannedGenericBeanDefinition sbd = new ScannedGenericBeanDefinition(metadataReader); sbd.setResource(resource); sbd.setSource(resource); if (isCandidateComponent(sbd)) { if (debugEnabled) { logger.debug("Identified candidate component class: " + resource); } candidates.add(sbd); } else { if (debugEnabled) { logger.debug("Ignored because not a concrete top-level class: " + resource); } } } else { if (traceEnabled) { logger.trace("Ignored because not matching any filter: " + resource); } } } catch (Throwable ex) { throw new BeanDefinitionStoreException( "Failed to read candidate component class: " + resource, ex); } } else { if (traceEnabled) { logger.trace("Ignored because not readable: " + resource); } } } } catch (IOException ex) { throw new BeanDefinitionStoreException("I/O failure during classpath scanning", ex); } return candidates; }
|
创建BeanDefinition
现在回到开始的doScan
方法
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
| 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) { //获取所有符合条件的BeanDefinition Set<BeanDefinition> candidates = findCandidateComponents(basePackage); for (BeanDefinition candidate : candidates) { //绑定BeanDefinition与Scope ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(candidate) candidate.setScope(scopeMetadata.getScopeName()) //查看是否配置类是否指定bean的名称,如没指定则使用类名首字母小写 String beanName = this.beanNameGenerator.generateBeanName(candidate, this.registry) //下面两个if是处理lazy、Autowire、DependencyOn、initMethod、enforceInitMethod、destroyMethod、enforceDestroyMethod、Primary、Role、Description这些逻辑的 if (candidate instanceof AbstractBeanDefinition) { postProcessBeanDefinition((AbstractBeanDefinition) candidate, beanName); } if (candidate instanceof AnnotatedBeanDefinition) { AnnotationConfigUtils.processCommonDefinitionAnnotations((AnnotatedBeanDefinition) candidate) } //检查bean是否存在 if (checkCandidate(beanName, candidate)) { //又包装了一层 BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(candidate, beanName); //检查scope是否创建,如未创建则进行创建 definitionHolder = AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry) beanDefinitions.add(definitionHolder); //重点来了,往下看 registerBeanDefinition(definitionHolder, this.registry) } } } return beanDefinitions; }
|
注册bean
到了一个比较重要的节点了,跟着上文的registerBeanDefinition
方法走
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| protected void registerBeanDefinition(BeanDefinitionHolder definitionHolder, BeanDefinitionRegistry registry) { BeanDefinitionReaderUtils.registerBeanDefinition(definitionHolder, registry) }
public static void registerBeanDefinition( BeanDefinitionHolder definitionHolder, BeanDefinitionRegistry registry) throws BeanDefinitionStoreException {
String beanName = definitionHolder.getBeanName() // 注册bean,往下看 registry.registerBeanDefinition(beanName, definitionHolder.getBeanDefinition())
//如果存在别名则循环注册别名,逻辑跟上方差不多,就不展开了 String[] aliases = definitionHolder.getAliases() if (aliases != null) { for (String alias: aliases) { registry.registerAlias(beanName, alias) } } }
|
其实这个注册bean的方法是DefaultListableBeanFactory
的方法,之前的文章已经解析过了,大体就是下面这么个流程
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 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90
| public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition) throws BeanDefinitionStoreException {
Assert.hasText(beanName, "Bean name must not be empty") Assert.notNull(beanDefinition, "BeanDefinition must not be null")
if (beanDefinition instanceof AbstractBeanDefinition) { try { ((AbstractBeanDefinition) beanDefinition).validate(); } catch (BeanDefinitionValidationException ex) { throw new BeanDefinitionStoreException(...); } }
BeanDefinition oldBeanDefinition
// 所有的 Bean 注册后都会被放入到这个beanDefinitionMap 中,查看是否已存在这个bean oldBeanDefinition = this.beanDefinitionMap.get(beanName);
// 处理重复名称的 Bean 定义的情况 if (oldBeanDefinition != null) { if (!isAllowBeanDefinitionOverriding()) { // 如果不允许覆盖的话,抛异常 throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName, "Cannot register bean definition [" + beanDefinition + "] for bean '" + beanName + "': There is already [" + oldBeanDefinition + "] bound.") } else if (oldBeanDefinition.getRole() < beanDefinition.getRole()) { // 用框架定义的 Bean 覆盖用户自定义的 Bean if (this.logger.isWarnEnabled()) { this.logger.warn("Overriding user-defined bean definition for bean '" + beanName + "' with a framework-generated bean definition: replacing [" + oldBeanDefinition + "] with [" + beanDefinition + "]") } } else if (!beanDefinition.equals(oldBeanDefinition)) { // 用新的 Bean 覆盖旧的 Bean if (this.logger.isWarnEnabled()) { this.logger.warn("Overriding user-defined bean definition for bean '" + beanName + "' with a framework-generated bean definition: replacing [" + oldBeanDefinition + "] with [" + beanDefinition + "]") } } else { // log...用同等的 Bean 覆盖旧的 Bean if (this.logger.isInfoEnabled()) { this.logger.info("Overriding bean definition for bean '" + beanName + "' with a different definition: replacing [" + oldBeanDefinition + "] with [" + beanDefinition + "]") } } // 覆盖 this.beanDefinitionMap.put(beanName, beanDefinition); } else { // 判断是否已经有其他的 Bean 开始初始化了.注意,"注册Bean" 这个动作结束,Bean 依然还没有初始化 在 Spring 容器启动的最后,会 预初始化 所有的 singleton beans 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<String>(this.beanDefinitionNames.size() + 1) updatedDefinitions.addAll(this.beanDefinitionNames); updatedDefinitions.add(beanName); this.beanDefinitionNames = updatedDefinitions if (this.manualSingletonNames.contains(beanName)) { Set<String> updatedSingletons = new LinkedHashSet<String>(this.manualSingletonNames); updatedSingletons.remove(beanName); this.manualSingletonNames = updatedSingletons } } } else {
// 将 BeanDefinition 放到这个 map 中,这个 map 保存了所有的 BeanDefinition this.beanDefinitionMap.put(beanName, beanDefinition); // 这是个 ArrayList,所以会按照 bean 配置的顺序保存每一个注册的 Bean 的名字 this.beanDefinitionNames.add(beanName); // 这是个 LinkedHashSet,代表的是手动注册的 singleton bean, this.manualSingletonNames.remove(beanName); } this.frozenBeanDefinitionNames = null }
if (oldBeanDefinition != null || containsSingleton(beanName)) { resetBeanDefinition(beanName); } }
|
现在回到文章开始的三句代码
1 2 3 4 5
| public AnnotationConfigApplicationContext(String... basePackages) { this(); scan(basePackages); refresh(); }
|
可以看到,只剩最后一个refresh()
方法了,如果看过之前文章的同学可能都已经知道这里面是什么东西了
refresh()
首先整个方法进来以后跟使用XML的时候是一样的
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 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63
| public void refresh() throws BeansException, IllegalStateException { synchronized (this.startupShutdownMonitor) {
prepareRefresh();
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
prepareBeanFactory(beanFactory);
try { postProcessBeanFactory(beanFactory); invokeBeanFactoryPostProcessors(beanFactory);
registerBeanPostProcessors(beanFactory);
initMessageSource();
initApplicationEventMulticaster();
onRefresh();
registerListeners();
finishBeanFactoryInitialization(beanFactory);
finishRefresh(); }
catch (BeansException ex) { if (logger.isWarnEnabled()) { logger.warn("Exception encountered during context initialization - " + "cancelling refresh attempt: " + ex); }
destroyBeans();
cancelRefresh(ex);
throw ex; }
finally { resetCommonCaches(); } } }
|
与XML的不同点
obtainFreshBeanFactory()
方法
还记得在之前的文章中列出了好几万行代码来解析这个方法,但是回忆一个这个方法是干啥的来着,创建bean容器,但是呢,bean容器在scan方法里就已经创建好了,所以这里就没必要再进行额外的逻辑了,你看现在它的代码现在多简单
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| protected ConfigurableListableBeanFactory obtainFreshBeanFactory() { refreshBeanFactory(); ConfigurableListableBeanFactory beanFactory = getBeanFactory(); if (logger.isDebugEnabled()) { logger.debug("Bean factory for " + getDisplayName() + ": " + beanFactory); } return beanFactory; } protected final void refreshBeanFactory() throws IllegalStateException { if (!this.refreshed.compareAndSet(false, true)) { throw new IllegalStateException( "GenericApplicationContext does not support multiple refresh attempts: just call 'refresh' once"); } this.beanFactory.setSerializationId(getId()); }
|
再接下来,其实就没了,有一个重点就是初始化,但是初始化逻辑是放在这个Spring家族的超级富二代DefaultListableBeanFactory
身上的。
心得体会
源码阅读入门很难,面对几十兆几百兆的代码不是一时半会就能看明白的,也不是一遍两遍debug就能搞懂的。阅读源码,一定要静下心来花上几个小时甚至几天的时间来钻研。
一通百通,当你研究明白一部分以后,再去看另外的部分,就好像有人推着你走一样,无比的顺利