Spring XML解析的详细过程 2
本章要点
- 自定义节点的解析过程
1.自定义节点的解析过程
代码片段:
<context:component-scan
base-package="com.ailk" use-default-filters="false" name-generator=""
scope-resolver=" " scoped-proxy="no">
<context:include-filter type="annotation"
expression="org.springframework.stereotype.Service">
</context:include-filter>
<context:exclude-filter type="annotation"
expression="org.springframework.stereotype.Controller">
</context:exclude-filter>
</context:component-scan>
org.springframework.beans.factory.xml.BeanDefinitionParserDelegate.parseCustomElement(Element)
public BeanDefinition parseCustomElement(Element ele, @Nullable BeanDefinition containingBd) {
String namespaceUri = getNamespaceURI(ele);//1)
if (namespaceUri == null) {
return null;
}
NamespaceHandler handler = this.readerContext.getNamespaceHandlerResolver().resolve(namespaceUri);//2)
if (handler == null) {
error("Unable to locate Spring NamespaceHandler for XML schema namespace [" + namespaceUri + "]", ele);
return null;
}
return handler.parse(ele, new ParserContext(this.readerContext, this, containingBd));
}
- 1)获取对应标签节点的namespace
-2)获取相应的NamespaceHandlerResovler,具体信息是在META-INF/spring.handlers
里配置的
org.springframework.beans.factory.xml.DefaultNamespaceHandlerResolver.resolve(String)
public NamespaceHandler resolve(String namespaceUri) {
Map<String, Object> handlerMappings = getHandlerMappings();//1)
Object handlerOrClassName = handlerMappings.get(namespaceUri);//2)
if (handlerOrClassName == null) {
return null;
}
else if (handlerOrClassName instanceof NamespaceHandler) {
return (NamespaceHandler) handlerOrClassName;
}
else {
String className = (String) handlerOrClassName;
try {
Class<?> handlerClass = ClassUtils.forName(className, this.classLoader);//3)
if (!NamespaceHandler.class.isAssignableFrom(handlerClass)) {
throw new FatalBeanException("Class [" + className + "] for namespace [" + namespaceUri +
"] does not implement the [" + NamespaceHandler.class.getName() + "] interface");
}
NamespaceHandler namespaceHandler = (NamespaceHandler) BeanUtils.instantiateClass(handlerClass);//4)
namespaceHandler.init();//5)
handlerMappings.put(namespaceUri, namespaceHandler);//6)
return namespaceHandler;
}
catch (ClassNotFoundException ex) {
throw new FatalBeanException("Could not find NamespaceHandler class [" + className +
"] for namespace [" + namespaceUri + "]", ex);
}
catch (LinkageError err) {
throw new FatalBeanException("Unresolvable class definition for NamespaceHandler class [" +
className + "] for namespace [" + namespaceUri + "]", err);
}
}
}
-1)加载配置文件META-INF/spring.handlers
-2)根据nanespace获取相应的handler字符串,例如:http://www.springframework.org/schema/context
对应org.springframework.context.config.ContextNamespaceHandler
- 3)、4)根据字符串反射实例化NamespaceHandler
-5)调用NamespaceHandler的init()初始化方法,初始化一些对应标签的解析器 - 6)将字符串替换成对应NamespaceHandler的实例类对象
org.springframework.context.config.ContextNamespaceHandler.init()
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());
}
}
- 初始化一些标签对应的解析器
org.springframework.beans.factory.xml.NamespaceHandlerSupport.parse(Element, ParserContext)
public BeanDefinition parse(Element element, ParserContext parserContext) {
BeanDefinitionParser parser = findParserForElement(element, parserContext);
return (parser != null ? parser.parse(element, parserContext) : null);
}
org.springframework.beans.factory.xml.NamespaceHandlerSupport.findParserForElement(Element, ParserContext)
private BeanDefinitionParser findParserForElement(Element element, ParserContext parserContext) {
String localName = parserContext.getDelegate().getLocalName(element);//1)
BeanDefinitionParser parser = this.parsers.get(localName);//2)
if (parser == null) {
parserContext.getReaderContext().fatal(
"Cannot locate BeanDefinitionParser for element [" + localName + "]", element);
}
return parser;
}
- 获取localname,例如
context:component-scan:
得到的就是component-scan
- 获取localname,例如
- 2)根据localname获取相应的解析器,例如:
component-scan
获取的就是org.springframework.context.annotation.ComponentScanBeanDefinitionParser
org.springframework.context.annotation.ComponentScanBeanDefinitionParser.parse(Element, ParserContext)
public BeanDefinition parse(Element element, ParserContext parserContext) {
String basePackage = element.getAttribute(BASE_PACKAGE_ATTRIBUTE);//1)获取base-package
basePackage = parserContext.getReaderContext().getEnvironment().resolvePlaceholders(basePackage);//2)
String[] basePackages = StringUtils.tokenizeToStringArray(basePackage,
ConfigurableApplicationContext.CONFIG_LOCATION_DELIMITERS);//3)
ClassPathBeanDefinitionScanner scanner = configureScanner(parserContext, element);//4)
Set<BeanDefinitionHolder> beanDefinitions = scanner.doScan(basePackages);//5)
registerComponents(parserContext.getReaderContext(), beanDefinitions, element);//6)
return null;
}
- 1)获取context标签对应的base-package属性
- 2)如果有环境变量,则替换掉环境变量
- 3)可以配置多个包路径,以逗号“,”或分号“;”隔开
- 4)配置扫描器
- 5)进行扫描出所配置包下,所有的BeanDefinition,并注册到map中
- 6)激活componentRegistered事件
org.springframework.context.annotation.ComponentScanBeanDefinitionParser.configureScanner(ParserContext, Element)
protected ClassPathBeanDefinitionScanner configureScanner(ParserContext parserContext, Element element) {
boolean useDefaultFilters = true;
if (element.hasAttribute(USE_DEFAULT_FILTERS_ATTRIBUTE)) {
useDefaultFilters = Boolean.valueOf(element.getAttribute(USE_DEFAULT_FILTERS_ATTRIBUTE));//1)
}
ClassPathBeanDefinitionScanner scanner = createScanner(parserContext.getReaderContext(), useDefaultFilters);//2)
scanner.setBeanDefinitionDefaults(parserContext.getDelegate().getBeanDefinitionDefaults());//3)
scanner.setAutowireCandidatePatterns(parserContext.getDelegate().getAutowireCandidatePatterns());//4)
if (element.hasAttribute(RESOURCE_PATTERN_ATTRIBUTE)) {
scanner.setResourcePattern(element.getAttribute(RESOURCE_PATTERN_ATTRIBUTE));
}
try {
parseBeanNameGenerator(element, scanner);//5)设置名字生成器
}
catch (Exception ex) {
parserContext.getReaderContext().error(ex.getMessage(), parserContext.extractSource(element), ex.getCause());
}
try {
parseScope(element, scanner);//6)
}
catch (Exception ex) {
parserContext.getReaderContext().error(ex.getMessage(), parserContext.extractSource(element), ex.getCause());
}
parseTypeFilters(element, scanner, parserContext);//7)
return scanner;
}
- 1)获取use-default-filters的属性值
- 2)创建ClassPathBeanDefinitionScanner实例对象
- 3)设置一些默认值
- 4)获取beans标签下的default-autowire-candidates属性
- 5)设置beanname生成器,通过
name-generator
标签配置 - 6)解析
scope-resolver和scoped-proxy
标签,并设置scanner对应的属性 - 6)解析filter配置,并添加到scanner属性中
org.springframework.context.annotation.ComponentScanBeanDefinitionParser.createScanner(XmlReaderContext, boolean)
protected ClassPathBeanDefinitionScanner createScanner(XmlReaderContext readerContext, boolean useDefaultFilters) {
return new ClassPathBeanDefinitionScanner(readerContext.getRegistry(), useDefaultFilters,
readerContext.getEnvironment(), readerContext.getResourceLoader());
}
org.springframework.context.annotation.ClassPathBeanDefinitionScanner.ClassPathBeanDefinitionScanner(BeanDefinitionRegistry, boolean, Environment, ResourceLoader)
public ClassPathBeanDefinitionScanner(BeanDefinitionRegistry registry, boolean useDefaultFilters,
Environment environment, @Nullable ResourceLoader resourceLoader) {
Assert.notNull(registry, "BeanDefinitionRegistry must not be null");
this.registry = registry;
if (useDefaultFilters) {
registerDefaultFilters();//1)
}
setEnvironment(environment);
setResourceLoader(resourceLoader);
}
- 1)默认的支持扫描的注解,主要包括org.springframework.stereotype.Component、javax.annotation.ManagedBean、javax.inject.Named
- 2)设置环境变量
- 3)设置加载器
org.springframework.context.annotation.ComponentScanBeanDefinitionParser.parseTypeFilters(Element, ClassPathBeanDefinitionScanner, ParserContext)
protected void parseTypeFilters(Element element, ClassPathBeanDefinitionScanner scanner, ParserContext parserContext) {
// Parse exclude and include filter elements.
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 {
if (INCLUDE_FILTER_ELEMENT.equals(localName)) {
TypeFilter typeFilter = createTypeFilter((Element) node, classLoader, parserContext);
scanner.addIncludeFilter(typeFilter);//1)
}
else if (EXCLUDE_FILTER_ELEMENT.equals(localName)) {
TypeFilter typeFilter = createTypeFilter((Element) node, classLoader, parserContext);
scanner.addExcludeFilter(typeFilter);//2)
}
}
catch (ClassNotFoundException ex) {
parserContext.getReaderContext().warning(
"Ignoring non-present type filter class: " + ex, parserContext.extractSource(element));
}
catch (Exception ex) {
parserContext.getReaderContext().error(
ex.getMessage(), parserContext.extractSource(element), ex.getCause());
}
}
}
}
- 1)解析include-filter
- 2)解析exclude-filter
org.springframework.context.annotation.ClassPathBeanDefinitionScanner.doScan(String...)
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);//1)拿到该包下所有的符合条件的Class
for (BeanDefinition candidate : candidates) {
ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(candidate);//2)
candidate.setScope(scopeMetadata.getScopeName());
String beanName = this.beanNameGenerator.generateBeanName(candidate, this.registry);//3)
if (candidate instanceof AbstractBeanDefinition) {
postProcessBeanDefinition((AbstractBeanDefinition) candidate, beanName);//4)
}
if (candidate instanceof AnnotatedBeanDefinition) {
AnnotationConfigUtils.processCommonDefinitionAnnotations((AnnotatedBeanDefinition) candidate);//5)
}
if (checkCandidate(beanName, candidate)) {//6)
BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(candidate, beanName);
definitionHolder =
AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);//7)
beanDefinitions.add(definitionHolder);
registerBeanDefinition(definitionHolder, this.registry);//7)
}
}
}
return beanDefinitions;
}
- 1)拿到该包下所有的符合条件的Class
- 2)解析
scope-resolver和scoped-proxy
- 3)生成beanName
- 4)设置一些默认值
- 5)解析一些注解,例如
@DependsOn
和@Role
等 - 6)检查名字是否唯一,缓存中
org.springframework.beans.factory.support.DefaultListableBeanFactory.beanDefinitionMap
是否已经存在 - 7)注册到缓存map中
org.springframework.context.annotation.AnnotationBeanNameGenerator.generateBeanName(BeanDefinition, BeanDefinitionRegistry)
public String generateBeanName(BeanDefinition definition, BeanDefinitionRegistry registry) {
if (definition instanceof AnnotatedBeanDefinition) {
String beanName = determineBeanNameFromAnnotation((AnnotatedBeanDefinition) definition);//1)
if (StringUtils.hasText(beanName)) {
return beanName;
}
}
return buildDefaultBeanName(definition, registry);//2)
}
- 1)获取注解上是否指定了bean名称
- 2)生成默认名称,类名首字母小写
org.springframework.context.annotation.ClassPathScanningCandidateComponentProvider.findCandidateComponents(String)
public Set<BeanDefinition> findCandidateComponents(String basePackage) {
if (this.componentsIndex != null && indexSupportsIncludeFilters()) {
return addCandidateComponentsFromIndex(this.componentsIndex, basePackage);
}
else {
return scanCandidateComponents(basePackage);
}
}
org.springframework.context.annotation.ClassPathScanningCandidateComponentProvider.scanCandidateComponents(String)
private Set<BeanDefinition> scanCandidateComponents(String basePackage) {
Set<BeanDefinition> candidates = new LinkedHashSet<>();
try {
String packageSearchPath = ResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX +
resolveBasePackage(basePackage) + '/' + this.resourcePattern;//1)
Resource[] resources = getResourcePatternResolver().getResources(packageSearchPath);//2)
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);//2)
if (isCandidateComponent(metadataReader)) {//3)
ScannedGenericBeanDefinition sbd = new ScannedGenericBeanDefinition(metadataReader);
sbd.setResource(resource);
sbd.setSource(resource);
if (isCandidateComponent(sbd)) {//4)
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;
}
- 1)将包名替换成路径名
- 2)根据class的Resource生成MetadataReader,读取Class字节流封装到ClassReader中,然后并对MetadataReader进行缓存,放到
org.springframework.core.type.classreading.CachingMetadataReaderFactory.metadataReaderCache
中 - 3)匹配filter,看看是否匹配
include-filter
和exclude-filter
- 4)是否是独立类(非内部类),具体的类(非接口、和抽象类)或是抽象类带有Lookup注解
具体代码如下:
protected boolean isCandidateComponent(AnnotatedBeanDefinition beanDefinition) {
AnnotationMetadata metadata = beanDefinition.getMetadata();
return (metadata.isIndependent() && (metadata.isConcrete() ||
(metadata.isAbstract() && metadata.hasAnnotatedMethods(Lookup.class.getName()))));
}
org.springframework.core.io.support.PathMatchingResourcePatternResolver.getResources(String)
public Resource[] getResources(String locationPattern) throws IOException {
Assert.notNull(locationPattern, "Location pattern must not be null");
if (locationPattern.startsWith(CLASSPATH_ALL_URL_PREFIX)) {
if (getPathMatcher().isPattern(locationPattern.substring(CLASSPATH_ALL_URL_PREFIX.length()))) {
return findPathMatchingResources(locationPattern);
}
else {
return findAllClassPathResources(locationPattern.substring(CLASSPATH_ALL_URL_PREFIX.length()));
}
}
else {
int prefixEnd = (locationPattern.startsWith("war:") ? locationPattern.indexOf("*/") + 1 :
locationPattern.indexOf(':') + 1);
if (getPathMatcher().isPattern(locationPattern.substring(prefixEnd))) {
return findPathMatchingResources(locationPattern);
}
else {
return new Resource[] {getResourceLoader().getResource(locationPattern)};
}
}
}
- 获取Class文件封装为Resource