3.Spring源码关于annotation扫描(1)
- Spring对于的详细解释
-
- context:component-scan的配置详情
- ComponentScanBeanDefinitionParser的解析
-
- 基本包的扫描
-
- ComponentScanBeanDefinitionParser
- configureScanner(parserContext, element)
- createScanner(readerContext, useDefaultFilters)
- ClassPathBeanDefinitionScanner(readerContext.getRegistry(), useDefaultFilters)
- this(registry, useDefaultFilters, getOrCreateEnvironment(registry))
- super(useDefaultFilters, environment)
- registerDefaultFilters()
- 返回到前面的`configureScanner(parserContext, element)`方法
- parseTypeFilters(element, scanner, readerContext, parserContext)
- createTypeFilter((Element) node, classLoader)
- 返回 ComponentScanBeanDefinitionParser
<context:component-scan base-package="com.zhuang.spring" use-default-filters="false"/>
接上篇文章,通过对xml的自定义的解析,深入了解Spring源码中关于annotation扫描。
Spring对于context:component-scan的详细解释
context:component-scan的配置详情
<!-- 激活Spring注解方式:自动扫描,并注入bean -->
<context:component-scan base-package="com.zhuang.spring" use-default-filters="" annotation-config="">
<context:include-filter type="annotation" expression="org.springframework.stereotype.Controller" />
<context:exclude-filter type="annotation" expression="org.springframework.stereotype.Service" />
</context:component-scan>
context:component-scan/支持部分注解, 配置base-package会扫描com.zhuang.spring包下的。在这个包的下面有许多的类,可是有些类我不想被Spring扫描到。我们可以加上context:include-filter 过滤器进行过滤我们希望被扫描到的类。过滤器我们分为很多类型:
Filter Type | Examples Expression | Description | 个人描述 |
---|---|---|---|
annotation | org.example.SomeAnnotation | 符合SomeAnnoation的target class | 配置了annnotation注解的如@Component,@Service,@Controller |
assignable | org.example.SomeClass | 指定class或interface的全名 | 写死的类 |
aspectj | org.example…*Service+ | AspectJ語法 | 是一个aop的写法,扫描以Service后缀结尾的类 |
regex | org.example.Default.* | Regelar Expression | 正则表达式的写法 |
custom | org.example.MyTypeFilter | Spring3新增自訂Type,實作org.springframework.core.type.TypeFilter | 自定义过滤器的写法 |
这是对Spring的支持。
我还是根据上篇文章,记录一下ComponentScanBeanDefinitionParser的过程,component-scan标签解析类。
ComponentScanBeanDefinitionParser的解析
在解析类里面完成了
- 基本包的扫描,如配置在base-package下面的包的扫描
- 类型过滤器的配置
- annotation-config配置的兼容,如配置了
<context:component-scan base-package="com.zhuang.spring"/>
,就不需要配置<context:annotation-config/>
。 - 注解处理器BeanPostProcessor的注册
基本包的扫描
ComponentScanBeanDefinitionParser
@Override
public BeanDefinition parse(Element element, ParserContext parserContext) {
String[] basePackages = StringUtils.tokenizeToStringArray(element.getAttribute(BASE_PACKAGE_ATTRIBUTE),
ConfigurableApplicationContext.CONFIG_LOCATION_DELIMITERS);
// Actually scan for bean definitions and register them.
ClassPathBeanDefinitionScanner scanner = configureScanner(parserContext, element);
Set<BeanDefinitionHolder> beanDefinitions = scanner.doScan(basePackages);
registerComponents(parserContext.getReaderContext(), beanDefinitions, element);
return null;
}
它就是对<context:component-scan base-package="com.zhuang.spring"/>
元素的解析。
首先它的入参传入了一个元素进来。这个元素就是<context:component-scan base-package="com.zhuang.spring"/>
。
String[] basePackages = StringUtils.tokenizeToStringArray(element.getAttribute(BASE_PACKAGE_ATTRIBUTE),
ConfigurableApplicationContext.CONFIG_LOCATION_DELIMITERS);
获取元素属性的base-package,根据, ; \t\n
进行分隔,获取多个base-package并且封装成数组。
接着往下:
ClassPathBeanDefinitionScanner scanner = configureScanner(parserContext, element);
configureScanner(parserContext, element)
protected ClassPathBeanDefinitionScanner configureScanner(ParserContext parserContext, Element element) {
XmlReaderContext readerContext = parserContext.getReaderContext();
boolean useDefaultFilters = true;//如果没有执行过滤器,使用默认的过滤器
if (element.hasAttribute(USE_DEFAULT_FILTERS_ATTRIBUTE)) {
useDefaultFilters = Boolean.valueOf(element.getAttribute(USE_DEFAULT_FILTERS_ATTRIBUTE));
}
// Delegate bean definition registration to scanner class.
ClassPathBeanDefinitionScanner scanner = createScanner(readerContext, useDefaultFilters);//创建扫描器,会扫描配置路径下的所有文件
scanner.setResourceLoader(readerContext.getResourceLoader