曹工说Spring Boot源码(1)-- Bean Definition到底是什么,附spring思维导图分享
曹工说Spring Boot源码(2)-- Bean Definition到底是什么,咱们对着接口,逐个方法讲解
曹工说Spring Boot源码(3)-- 手动注册Bean Definition不比游戏好玩吗,我们来试一下
曹工说Spring Boot源码(4)-- 我是怎么自定义ApplicationContext,从json文件读取bean definition的?
曹工说Spring Boot源码(5)-- 怎么从properties文件读取bean
曹工说Spring Boot源码(6)-- Spring怎么从xml文件里解析bean的
曹工说Spring Boot源码(7)-- Spring解析xml文件,到底从中得到了什么(上)
曹工说Spring Boot源码(8)-- Spring解析xml文件,到底从中得到了什么(util命名空间)
曹工说Spring Boot源码(9)-- Spring解析xml文件,到底从中得到了什么(context命名空间上)
曹工说Spring Boot源码(10)-- Spring解析xml文件,到底从中得到了什么(context:annotation-config 解析)
曹工说Spring Boot源码(11)-- context:component-scan,你真的会用吗(这次来说说它的奇技淫巧)
工程代码地址 思维导图地址
工程结构图:
概要本篇已经是spring源码第12篇,前一篇讲了context:component-scan这个元素的用法,其中涉及到了各个属性的作用。本节呢,主要就是讲解该元素的解析流程,其中就会涉及到各个属性是怎么发挥作用的。
大体流程本来吧,这里画时序图比较好,但是uml图一直是半桶水,visio这台电脑也没装,就随便花了下流程图,将就看吧。
ComponentScanBeanDefinitionParser.parse这个就是在contextnamespacehandler里注册的,component-scan对应的beanDefinitionParser实现。
这个类呢,也是相当简洁明了,没有乱七八糟的类结构。
public class ComponentScanBeanDefinitionParser implements BeanDefinitionParser { configureScanner 类图这个方法,最终返回了一个ClassPathBeanDefinitionScanner,这个类的结构如下:
父类ClassPathScanningCandidateComponentProvider中的字段几个接口都没实质性内容,主要是继承了一个父类,我整理了一下,父类里,大概有如下字段:
// ClassPathScanningCandidateComponentProvider 中的fields // 指定包下,文件很多,可能不止有class,还有xml,比如mybatis的mapper等;这里指定要获取的资源的pattern static final String DEFAULT_RESOURCE_PATTERN = "**/*.class"; // 没啥说的,环境 private Environment environment; // 因为用户可以自己指定resource_pattern, (不喜欢前面那个**/*.class),这个field负责来解析用户的resouce_pattern private ResourcePatternResolver resourcePatternResolver = new PathMatchingResourcePatternResolver(); // 这个很重要,你给它一个class,它负责给你返回一个本class的元数据reader,通过元数据reader,你能取到class上的注解等信息 private MetadataReaderFactory metadataReaderFactory = new CachingMetadataReaderFactory(this.resourcePatternResolver); private String resourcePattern = DEFAULT_RESOURCE_PATTERN; // 通过这个来划定,是不是我的小弟 private final List<TypeFilter> includeFilters = new LinkedList<TypeFilter>(); // 通过这个来划定,不是我的小弟,这个里面的都是拉黑了的 private final List<TypeFilter> excludeFilters = new LinkedList<TypeFilter>();这里说下MetadataReaderFactory,因为吧,以后可能会频繁出现。
这是个接口,在spring-core包里,信息如下:
MetadataReader 的工厂接口,调用这个接口的方法,能得到一个MetadataReader /** * Factory interface for {@link MetadataReader} instances. * Allows for caching a MetadataReader per original resource. * */ public interface MetadataReaderFactory { /** * 根据一个类名,获取MetadataReader;这个reader,可以帮你获取class的class/注解等信息 * * Obtain a MetadataReader for the given class name. * @param className the class name (to be resolved to a ".class" file) * @return a holder for the ClassReader instance (never {@code null}) * @throws IOException in case of I/O failure */ MetadataReader getMetadataReader(String className) throws IOException; /** * Obtain a MetadataReader for the given resource. * @param resource the resource (pointing to a ".class" file) * @return a holder for the ClassReader instance (never {@code null}) * @throws IOException in case of I/O failure */ MetadataReader getMetadataReader(Resource resource) throws IOException; }