阅读须知
- Spring源码版本:4.3.8
- 文章中使用/* */注释的方法会做深入分析
正文
现在我们使用Spring的时候,基本上很少使用标签配置的方式来声明bean了,都是使用注解的方式来声明bean,下面我们就来分析一下这部分的源码实现。
在使用注解之前,我们要首先配置一下<context:component-scan/>
标签,我们就以这个标签的解析作为入口来分析,这里需要读者了解Spring自定义标签解析的流程,不了解的可以看一下笔者之前关于Spring自定义标签解析的的文章,这里给出传送门,锁定ContextNamespaceHandler:
public void init() {
registerBeanDefinitionParser("property-placeholder", new PropertyPlaceholderBeanDefinitionParser());
registerBeanDefinitionParser("property-override", new PropertyOverrideBeanDefinitionParser());
registerBeanDefinitionParser("annotation-config", new AnnotationConfigBeanDefinitionParser());
/* 注册<context:component-scan/>标签解析器 */
registerBeanDefinitionParser("component-scan", new ComponentScanBeanDefinitionParser());
registerBeanDefinitionParser("load-time-weaver", new LoadTimeWeaverBeanDefinitionParser());
registerBeanDefinitionParser("spring-configured", new SpringConfiguredBeanDefinitionParser());
registerBeanDefinitionParser("mbean-export", new MBeanExportBeanDefinitionParser());
registerBeanDefinitionParser("mbean-server", new MBeanServerBeanDefinitionParser());
}
分析ComponentScanBeanDefinitionParser的parse方法:
public BeanDefinition parse(Element element, ParserContext parserContext) {
// 获取base-package属性
String basePackage = element.getAttribute(BASE_PACKAGE_ATTRIBUTE);
// 处理包路径中的特殊符号,如${}
basePackage = parserContext.getReaderContext().getEnvironment().resolvePlaceholders(basePackage);
// 分割
String[] basePackages = StringUtils.tokenizeToStringArray(basePackage,
ConfigurableApplicationContext.CONFIG_LOCATION_DELIMITERS);
/* 配置Scanner */
ClassPathBeanDefinitionScanner scanner = configureScanner(parserContext, element);
/* 扫描 */
Set<BeanDefinitionHolder> beanDefinitions = scanner.doScan(basePackages);
/* 注册一些注解相关的PostProcessor,将BeanDefinition注册完成的事件通知给相关监听器 */
registerComponents(parserContext.getReaderContext(), beanDefinitions, element);
return null;
}
ComponentScanBeanDefinitionParser:
protected ClassPathBeanDefinitionScanner configureScanner(ParserContext parserContext, Element element) {
boolean useDefaultFilters = true;
// use-default-filters属性,默认为true
if (element.hasAttribute(USE_DEFAULT_FILTERS_ATTRIBUTE)) {
useDefaultFilters = Boolean.valueOf(element.getAttribute(USE_DEFAULT_FILTERS_ATTRIBUTE));
}
/* 创建Scanner */
ClassPathBeanDefinitionScanner scanner = createScanner(parserContext.getReaderContext(), useDefaultFilters);
scanner.setBeanDefinitionDefaults(parserContext.getDelegate().getBeanDefinitionDefaults());
scanner.setAutowireCandidatePatterns(parserContext.getDelegate().getAutowireCandidatePatterns());
// resource-pattern属性
if (element.hasAttribute(RESOURCE_PATTERN_ATTRIBUTE)) {
scanner.setResourcePattern(element.getAttribute(RESOURCE_PATTERN_ATTRIBUTE));
}
try {
/* 解析name-generator属性 */
parseBeanNameGenerator(element, scanner);
}
catch (Exception ex) {
parserContext.getReaderContext().error(ex.getMessage(), parserContext.extractSource(element), ex.getCause());
}
try {
/* 解析scope-resolver属性和scoped-proxy属性 */
parseScope(element, scanner);
}
catch (Exception ex) {
parserContext.getReaderContext().error(ex.getMessage(), parserContext.extractSource(element), ex.getCause());
}
/* 解析include-filter子标签和exclude-filter子标签 */
parseTypeFilters(element, scanner, parserContext);
return scanner;
}
ComponentScanBeanDefinitionParser:
protected ClassPathBeanDefinitionScanner createScanner(XmlReaderContext readerContext, boolean useDefaultFilters) {
/* 创建ClassPathBeanDefinitionScanner */
return new ClassPathBeanDefinitionScanner(readerContext.getRegistry(), useDefaultFilters,
readerContext.getEnvironment(), readerContext.getResourceLoader());
}
ClassPathBeanDefinitionScanner:
public ClassPathBeanDefinitionScanner(BeanDefinitionRegistry registry, boolean useDefaultFilters,
Environment environment, ResourceLoader resourceLoader) {
Assert.notNull(registry, "BeanDefinitionRegistry must not be null");
this.registry = registry;
if (useDefaultFilters) {
/* 注册默认的过滤器 */
registerDefaultFilters();
}
setEnvironment(environment);
setResourceLoader(resourceLoader);
}
ClassPathScanningCandidateComponentProvider:
protected void registerDefaultFilters() {
// 添加默认的Component注解的过滤器
this.includeFilters.add(new AnnotationTypeFilter(Component.class));
ClassLoader cl = ClassPathScanningCandidateComponentProvider.class.getClassLoader();
try {
this.includeFilters.add(new AnnotationTypeFilter(
((Class<? extends Annotation>) ClassUtils.forName("javax.annotation.ManagedBean", cl)), false));
logger.debug("JSR-250 'javax.annotation.ManagedBean' found and supported for component scanning");
}
catch (ClassNotFoundException ex) {
}
try {
this.includeFilters.add(new AnnotationTypeFilter(
((Class<? extends Annotation>) ClassUtils.forName("javax.inject.Named", cl)), false));
logger.debug("JSR-330 'javax.inject.Named' annotation found and supported for component scanning");
}
catch (ClassNotFoundException ex) {
}
}
这里我们看到了默认的@Component注解过滤器的添加,而我们常用的@Service、@Controller等注解都使用了@Component注解,所以同样会匹配这个过滤器。
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Component // @Service注解也使用了@Component
public @interface Service {
String value() default "";
}
ClassPathBeanDefinitionScanner:
protected void parseBeanNameGenerator(Element element, ClassPathBeanDefinitionScanner scanner) {
// 如果配置了name-generator属性则设置为自定义的BeanNameGenerator
if (element.hasAttribute(NAME_GENERATOR_ATTRIBUTE)) {
BeanNameGenerator beanNameGenerator = (BeanNameGenerator) instantiateUserDefinedStrategy(
element.getAttribute(NAME_GENERATOR_ATTRIBUTE), BeanNameGenerator.class,
scanner.getResourceLoader().getClassLoader());
scanner.setBeanNameGenerator(beanNameGenerator);
}
}
ClassPathBeanDefinitionScanner:
protected void parseScope(Element element, ClassPathBeanDefinitionScanner scanner) {
// scope-resolver属性
if (element.hasAttribute(SCOPE_RESOLVER_ATTRIBUTE)) {
// 不能与scoped-proxy同时出现
if (element.hasAttribute(SCOPED_PROXY_ATTRIBUTE)) {
throw new IllegalArgumentException(
"Cannot define both 'scope-resolver' and 'scoped-proxy' on <component-scan> tag");
}
ScopeMetadataResolver scopeMetadataResolver = (ScopeMetadataResolver) instantiateUserDefinedStrategy(
element.getAttribute(SCOPE_RESOLVER_ATTRIBUTE), ScopeMetadataResolver.class,
scanner.getResourceLoader().getClassLoader());
scanner.setScopeMetadataResolver(scopeMetadataResolver);
}
// scope-proxy属性
if (element.hasAttribute(SCOPED_PROXY_ATTRIBUTE)) {
String mode = element.getAttribute(SCOPED_PROXY_ATTRIBUTE);
// targetClass、interfaces、no三个属性值的设置
if ("targetClass".equals(mode)) {
scanner.setScopedProxyMode(ScopedProxyMode.TARGET_CLASS);
}
else if ("interfaces".equals(mode)) {
scanner.setScopedProxyMode(ScopedProxyMode.INTERFACES);
}
else if ("no".equals(mode)) {
scanner.setScopedProxyMode(ScopedProxyMode.NO);
}
else {
throw new IllegalArgumentException("scoped-proxy only supports 'no', 'interfaces' and 'targetClass'");
}
}
}
ClassPathBeanDefinitionScanner:
protected void parseTypeFilters(Element element, ClassPathBeanDefinitionScanner scanner, ParserContext parserContext) {
ClassLoader classLoader = scanner.getResourceLoader().getClassLoader();
NodeList nodeList = element.getChildNodes();
for (int i = 0; i < nodeList.getLength(); i++) {
Node node = nodeList.item(i);
if (node.getNodeType() == Node.ELEMENT_NODE) {
String localName = parserContext.getDelegate().getLocalName(node);
try {
// 子标签include-filter
if (INCLUDE_FILTER_ELEMENT.equals(localName)) {
TypeFilter typeFilter = createTypeFilter((Element) node, classLoader, parserContext);
scanner.addIncludeFilter(typeFilter);
}
// 子标签exclude-filter
else if (EXCLUDE_FILTER_ELEMENT.equals(localName)) {
TypeFilter typeFilter = createTypeFilter((Element) node, classLoader, parserContext);
scanner.addExcludeFilter(typeFilter);
}
}
catch (Exception ex) {
parserContext.getReaderContext().error(
ex.getMessage(), parserContext.extractSource(element), ex.getCause());
}
}
}
}
到这配置解析的准备工作就完成了,我们会在后面的文章继续分析注解的扫描流程。