序
上篇博客中,介绍了对于自定义标签的解析,以及自己实现了一个标签供spring扫描,此篇博客会主要分析下component-scan 标签的解析过程中做了哪些事情.
解析前的准备
首先在xml文件的beans标签中引入context标签
<context:component-scan base-package="com"></context:component-scan>
在xml文件中加入上面的代码 base-package指的是扫描的包名
当spring启动后,解析到该段时,是会进入到自定义标签的解析的.
public class ContextNamespaceHandler extends NamespaceHandlerSupport {
@Override
public void init() {
registerBeanDefinitionParser("property-placeholder", new PropertyPlaceholderBeanDefinitionParser());
registerBeanDefinitionParser("property-override", new PropertyOverrideBeanDefinitionParser());
registerBeanDefinitionParser("annotation-config", new AnnotationConfigBeanDefinitionParser());
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());
}
}
context所对应的handler会注册上述的八个标签,其中当使用的是component-scan时,ComponentScanBeanDefinitionParser会负责去解析该标签
ComponentScanBeanDefinitionParser的 parse(Element element, ParserContext parserContext)方法
public BeanDefinition parse(Element element, ParserContext parserContext) {
//BASE_PACKAGE_ATTRIBUTE就是base-package,获取base-package的值
String basePackage = element.getAttribute(BASE_PACKAGE_ATTRIBUTE);
//这里貌似是对路径进行解析,可以支持"${}"这种写法,从Enviroment中获取resources注入进去
// <context:component-scan base-package="${LOCALAPPDATA}"></context:component-scan>这种配置下
//${LOCALAPPDATA}被正常解析了,主要还是要Enviroment中得propertySources拥有,应该都可以在此注入
basePackage = parserContext.getReaderContext().getEnvironment().resolvePlaceholders(basePackage);
//如果是多个包名,会在此被分析出来
String[] basePackages = StringUtils.tokenizeToStringArray(basePackage,
ConfigurableApplicationContext.CONFIG_LOCATION_DELIMITERS);
// 主角在此,获取一个 配置好的ClassPathBeanDefinitionScanner 对象
ClassPathBeanDefiniti