Spring Framework2.0开始,引入可扩展的XML编程机制,该机制要求XML Schema命名空间需要与Handler建立映射关系。该关系配置在相对于classpath下的/META-INF/spring.handlers中。
如上图所示 ContextNamespaceHandler对应<context:...> 分析的入口。
ContextNamespaceHandler
这些NameSpaceHandler是在什么时候实例化的呢?init()方法都是在什么时候调用的呢?
在AbstractApplicationContext的refresh()方法中,我们会调用一个obtainFreshBeanFactory()方法,源码如下:
protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
refreshBeanFactory();
ConfigurableListableBeanFactory beanFactory = getBeanFactory();
if (logger.isDebugEnabled()) {
logger.debug("Bean factory for " + getDisplayName() + ": " + beanFactory);
}
return beanFactory;
}
AbstractRefreshableApplicationContext#refreshBeanFactory中会调用所有AbstractRefreshableApplicationContext子类的loadBeanDefinitions()方法。
我们这里是XmlWebApplicationContext的loadBeanDefinitions方法。
一直跟踪代码,来到org.springframework.beans.factory.xml.XmlBeanDefinitionReader#doLoadBeanDefinitions,里面调用了org.springframework.beans.factory.xml.XmlBeanDefinitionReader#registerBeanDefinitions方法。
在createReaderContext(resource)中会创建NamespaceHandlerResolver接口的一个唯一实现类DefaultNamespaceHandlerResolver
回到documentReader.registerBeanDefinitions(doc, createReaderContext(resource));会调用org.springframework.beans.factory.xml.DefaultBeanDefinitionDocumentReader#doRegisterBeanDefinitions
protected void parseBeanDefinitions(Element root, BeanDefinitionParserDelegate delegate) {
// 1.默认命名空间的处理
if (delegate.isDefaultNamespace(root)) {
NodeList nl = root.getChildNodes();
// 遍历root的子节点列表
for (int i = 0; i < nl.getLength(); i++) {
Node node = nl.item(i);
if (node instanceof Element) {
Element ele = (Element) node;
if (delegate.isDefaultNamespace(ele)) {
// 1.1 默认命名空间节点的处理,例如: <bean id="test" class="" />
parseDefaultElement(ele, delegate);
}
else {
// 1.2 自定义命名空间节点的处理,例如:<context:component-scan/>、<aop:aspectj-autoproxy/>
delegate.parseCustomElement(ele);
}
}
}
} else {
// 2.自定义命名空间的处理
delegate.parseCustomElement(root);
}
}
自定义命名空间节点的处理
public BeanDefinition parseCustomElement(Element ele) {
return parseCustomElement(ele, null);
}
public BeanDefinition parseCustomElement(Element ele, BeanDefinition containingBd) {
// 1.拿到节点ele的命名空间,例如常见的:
// <context> 节点对应命名空间: http://www.springframework.org/schema/context
// <aop> 节点对应命名空间: http://www.springframework.org/schema/aop
String namespaceUri = getNamespaceURI(ele);
// 2.拿到命名空间对应的的handler, 例如:http://www.springframework.org/schema/context 对应 ContextNameSpaceHandler
// 2.1 getNamespaceHandlerResolver: 拿到namespaceHandlerResolver
// 2.2 resolve: 使用namespaceHandlerResolver解析namespaceUri, 拿到namespaceUri对应的NamespaceHandler
NamespaceHandler handler = this.readerContext.getNamespaceHandlerResolver().resolve(namespaceUri);
if (handler == null) {
error("Unable to locate Spring NamespaceHandler for XML schema namespace [" + namespaceUri + "]", ele);
return null;
}
// 3.使用拿到的handler解析节点(ParserContext用于存放解析需要的一些上下文信息)
return handler.parse(ele, new ParserContext(this.readerContext, this, containingBd));
}
拿到当时创建的 DefaultNamespaceHandlerResolver 对象,使用 DefaultNamespaceHandlerResolver 解析 namespaceUri,拿到对应的 handler。
ContextNamespaceHandler也就是在这时进行了init()方法初始化。
@Override
public NamespaceHandler resolve(String namespaceUri) {
// 1.拿到配置文件的所有命名空间和对应的handler
// 例如:"http://www.springframework.org/schema/aop" -> "org.springframework.aop.config.AopNamespaceHandler"
Map<String, Object> handlerMappings = getHandlerMappings();
// 2.拿到当前命名空间对应的handler (可能是handler的className,也可能是已经实例化的handler)
Object handlerOrClassName = handlerMappings.get(namespaceUri);
if (handlerOrClassName == null) {
// 2.1 如果不存在namespaceUri对应的handler,则返回null
return null;
}
else if (handlerOrClassName instanceof NamespaceHandler) {
// 2.2 如果是已经实例化的handler,则直接强转返回
return (NamespaceHandler) handlerOrClassName;
}
else {
// 2.3 如果是handler的className
String className = (String) handlerOrClassName;
try {
// 2.3.1 根据className,使用类加载器拿到该类
Class<?> handlerClass = ClassUtils.forName(className, this.classLoader);
// 2.3.2 校验是否是继承自NamespaceHandler(所有的handler都继承自NamespaceHandler)
if (!NamespaceHandler.class.isAssignableFrom(handlerClass)) {
throw new FatalBeanException("Class [" + className + "] for namespace [" + namespaceUri +
"] does not implement the [" + NamespaceHandler.class.getName() + "] interface");
}
// 2.3.3 使用无参构造函数实例化handlerClass类
NamespaceHandler namespaceHandler = (NamespaceHandler) BeanUtils.instantiateClass(handlerClass);
// 2.3.4 调用handler类的初始化方法(将命名空间下的节点名和对应的解析器注册到parsers缓存中)
namespaceHandler.init();
// 2.3.5 将实例化的handler放到缓存,替换原来的className
// 原来为: namespaceUri -> handler的className,会被覆盖成: namespaceUri -> 实例化的handler
handlerMappings.put(namespaceUri, namespaceHandler);
// 返回实例化后的handler对象
return namespaceHandler;
}
catch (ClassNotFoundException ex) {
throw new FatalBeanException("NamespaceHandler class [" + className + "] for namespace [" +
namespaceUri + "] not found", ex);
}
catch (LinkageError err) {
throw new FatalBeanException("Invalid NamespaceHandler class [" + className + "] for namespace [" +
namespaceUri + "]: problem with handler class file or dependent class", err);
}
}
}
使用拿到的 handler 解析 ele 节点。
org.springframework.beans.factory.xml.NamespaceHandlerSupport#parse
public BeanDefinition parse(Element element, ParserContext parserContext) {
// 1.findParserForElement: 给element寻找对应的BeanDefinition解析器
// 2.使用BeanDefinition解析器解析element节点
BeanDefinitionParser parser = findParserForElement(element, parserContext);
return (parser != null ? parser.parse(element, parserContext) : null);
}
private BeanDefinitionParser findParserForElement(Element element, ParserContext parserContext) {
// 1.1 拿到节点的localName,例如:annotation-config、component-scan
String localName = parserContext.getDelegate().getLocalName(element);
// 1.2 从parsers缓存中,拿到localName对应的解析器, 例如: component-scan -> ComponentScanBeanDefinitionParser
BeanDefinitionParser parser = this.parsers.get(localName);
if (parser == null) {
parserContext.getReaderContext().fatal(
"Cannot locate BeanDefinitionParser for element [" + localName + "]", element);
}
return parser;
}
ComponentScanBeanDefinitionParser
在上面我们拿到具体的BeanDefinitionParser解析器后就可以调用其parse方法进行解析了。
ClassPathBeanDefinitionScanner#doScan是扫描BeanDefinition并注册的实现 。
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);
for (BeanDefinition candidate : candidates) {
ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(candidate);
candidate.setScope(scopeMetadata.getScopeName());
String beanName = this.beanNameGenerator.generateBeanName(candidate, this.registry);
if (candidate instanceof AbstractBeanDefinition) {
postProcessBeanDefinition((AbstractBeanDefinition) candidate, beanName);
}
if (candidate instanceof AnnotatedBeanDefinition) {
AnnotationConfigUtils.processCommonDefinitionAnnotations((AnnotatedBeanDefinition) candidate);
}
if (checkCandidate(beanName, candidate)) {
BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(candidate, beanName);
definitionHolder =
AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);
beanDefinitions.add(definitionHolder);
registerBeanDefinition(definitionHolder, this.registry);
}
}
}
return beanDefinitions;
}
findCandidateComponents:从classPath扫描组件,并转换为备选BeanDefinition,也就是要做的解析@Component的核心方法。
findCandidateComponents在其父类ClassPathScanningCandidateComponentProvider 中。
public Set<BeanDefinition> findCandidateComponents(String basePackage) {
if (this.componentsIndex != null && indexSupportsIncludeFilters()) {
return addCandidateComponentsFromIndex(this.componentsIndex, basePackage);
}
else {
return scanCandidateComponents(basePackage);
}
}
private Set<BeanDefinition> scanCandidateComponents(String basePackage) {
Set<BeanDefinition> candidates = new LinkedHashSet<>();
try {
//将package转化为ClassLoader类资源搜索路径
String packageSearchPath = ResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX +
resolveBasePackage(basePackage) + '/' + this.resourcePattern;
//加载搜素路径下的资源。
Resource[] resources = getResourcePatternResolver().getResources(packageSearchPath);
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);
//判断是否是备选组件
if (isCandidateComponent(metadataReader)) {
ScannedGenericBeanDefinition sbd = new ScannedGenericBeanDefinition(metadataReader);
sbd.setResource(resource);
sbd.setSource(resource);
if (isCandidateComponent(sbd)) {
//添加到返回结果的list
candidates.add(sbd);
}
}
}
}
}
}
return candidates;
}
ClassPathScanningCandidateComponentProvider#isCandidateComponent其源码如下:
protected boolean isCandidateComponent(MetadataReader metadataReader) throws IOException {
//省略部分代码
for (TypeFilter tf : this.includeFilters) {
if (tf.match(metadataReader, getMetadataReaderFactory())) {
return isConditionMatch(metadataReader);
}
}
return false;
}
includeFilters由registerDefaultFilters()设置初始值,有@Component,没有@Service啊?
protected void registerDefaultFilters() {
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.trace("JSR-250 'javax.annotation.ManagedBean' found and supported for component scanning");
}
catch (ClassNotFoundException ex) {
// JSR-250 1.1 API (as included in Java EE 6) not available - simply skip.
}
try {
this.includeFilters.add(new AnnotationTypeFilter(
((Class<? extends Annotation>) ClassUtils.forName("javax.inject.Named", cl)), false));
logger.trace("JSR-330 'javax.inject.Named' annotation found and supported for component scanning");
}
catch (ClassNotFoundException ex) {
// JSR-330 API not available - simply skip.
}
}
Spring如何处理@Service的注解的呢?
其实@Component是任何Spring管理的组件的通用原型。@Repository、@Service和@Controller是派生自@Component。
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
// @Service 派生自@Component
@Component
public @interface Service {
/**
* The value may indicate a suggestion for a logical component name,
* to be turned into a Spring bean in case of an autodetected component.
* @return the suggested component name, if any (or empty String otherwise)
*/
@AliasFor(annotation = Component.class)
String value() default "";
}
@Component是@Service的元注解,在读取@Service,也读取了它的元注解,并将@Service作为@Component处理。
AnnotationAttributesReadingVisitor#visitEnd()内部方法recursivelyCollectMetaAnnotations 递归的读取注解,与注解的元注解(读@Service,再读元注解@Component),并设置到metaAnnotationMap。
final class AnnotationAttributesReadingVisitor extends RecursiveAnnotationAttributesVisitor {
private final MultiValueMap<String, AnnotationAttributes> attributesMap;
private final Map<String, Set<String>> metaAnnotationMap;
public AnnotationAttributesReadingVisitor(String annotationType, MultiValueMap<String, AnnotationAttributes> attributesMap, Map<String, Set<String>> metaAnnotationMap, @Nullable ClassLoader classLoader) {
super(annotationType, new AnnotationAttributes(annotationType, classLoader), classLoader);
this.attributesMap = attributesMap;
this.metaAnnotationMap = metaAnnotationMap;
}
public void visitEnd() {
super.visitEnd();
Class<?> annotationClass = this.attributes.annotationType();
if (annotationClass != null) {
List<AnnotationAttributes> attributeList = (List)this.attributesMap.get(this.annotationType);
if (attributeList == null) {
this.attributesMap.add(this.annotationType, this.attributes);
} else {
attributeList.add(0, this.attributes);
}
Set<Annotation> visited = new LinkedHashSet();
Annotation[] metaAnnotations = AnnotationUtils.getAnnotations(annotationClass);
if (!ObjectUtils.isEmpty(metaAnnotations)) {
Annotation[] var5 = metaAnnotations;
int var6 = metaAnnotations.length;
for(int var7 = 0; var7 < var6; ++var7) {
Annotation metaAnnotation = var5[var7];
if (!AnnotationUtils.isInJavaLangAnnotationPackage(metaAnnotation)) {
this.recursivelyCollectMetaAnnotations(visited, metaAnnotation);
}
}
}
Set<String> metaAnnotationTypeNames = new LinkedHashSet(visited.size());
Iterator var10 = visited.iterator();
while(var10.hasNext()) {
Annotation ann = (Annotation)var10.next();
metaAnnotationTypeNames.add(ann.annotationType().getName());
}
this.metaAnnotationMap.put(annotationClass.getName(), metaAnnotationTypeNames);
}
}
private void recursivelyCollectMetaAnnotations(Set<Annotation> visited, Annotation annotation) {
Class<? extends Annotation> annotationType = annotation.annotationType();
String annotationName = annotationType.getName();
if (!AnnotationUtils.isInJavaLangAnnotationPackage(annotationName) && visited.add(annotation)) {
try {
if (Modifier.isPublic(annotationType.getModifiers())) {
this.attributesMap.add(annotationName, AnnotationUtils.getAnnotationAttributes(annotation, false, true));
}
Annotation[] var5 = annotationType.getAnnotations();
int var6 = var5.length;
for(int var7 = 0; var7 < var6; ++var7) {
Annotation metaMetaAnnotation = var5[var7];
this.recursivelyCollectMetaAnnotations(visited, metaMetaAnnotation);
}
} catch (Throwable var9) {
if (this.logger.isDebugEnabled()) {
this.logger.debug("Failed to introspect meta-annotations on [" + annotation + "]: " + var9);
}
}
}
}
}
标签:xml,NamespaceHandler,return,String,Service,Spring,namespaceUri,handler,new From: https://www.cnblogs.com/xfeiyun/p/17871713.html