解析自定义标签元素
public BeanDefinition parseCustomElement(Element ele) {
return this.parseCustomElement(ele, (BeanDefinition)null);
}
public BeanDefinition parseCustomElement(Element ele, BeanDefinition containingBd) {
String namespaceUri = this.getNamespaceURI(ele);
/**
*readerContext其实就是我们的XmlReaderContext
*readerContext.getNamespaceHandlerResolver()执行的具体是什么东西呢?
*private final NamespaceHandlerResolver namespaceHandlerResolver;就返回了这个实例变量
* 在XmlReaderContext构造方法进行属性初始化,我们继续查看XmlReaderContext初始化【分支5】
* 这里看到具体的DefaultNamespaceHandlerResolver
* this.readerContext.getNamespaceHandlerResolver().resolve(namespaceUri) == DefaultNamespaceHandlerResolver.resolve(namespaceUri);
* 这里获取了一个NamespaceHandler.具体这个NamespaceHandler是怎么获取的暂时不深究,不然进去又出不来了。
* 但是分析下面handler.parse(ele, new ParserContext(this.readerContext, this, containingBd));时又出现了不知所云,就是NamespaceHandler到底实现是什么?是什么?
*所以不得继续分析DefaultNamespaceHandlerResolver.resolve(namespaceUri)方法了【分支6】
*/
NamespaceHandler handler = this.readerContext.getNamespaceHandlerResolver().resolve(namespaceUri);
if(handler == null) {
this.error("Unable to locate Spring NamespaceHandler for XML schema namespace [" + namespaceUri + "]", ele);
return null;
} else {
return handler.parse(ele, new ParserContext(this.readerContext, this, containingBd));
}
}
//【分支5】在XmlBeanDefinitionReader中有这么一句代码
public int registerBeanDefinitions(Document doc, Resource resource) throws BeanDefinitionStoreException {
BeanDefinitionDocumentReader documentReader = this.createBeanDefinitionDocumentReader();
int countBefore = this.getRegistry().getBeanDefinitionCount();
//this.createReaderContext(resource)创建XmlReaderContext
documentReader.registerBeanDefinitions(doc, this.createReaderContext(resource));
return this.getRegistry().getBeanDefinitionCount() - countBefore;
}
//this.createReaderContext(resource)如何创建的呢?
public XmlReaderContext createReaderContext(Resource resource) {
return new XmlReaderContext(resource, this.problemReporter, this.eventListener, this.sourceExtractor, this, this.getNamespaceHandlerResolver());
}
public NamespaceHandlerResolver getNamespaceHandlerResolver() {
if(this.namespaceHandlerResolver == null) {
this.namespaceHandlerResolver = this.createDefaultNamespaceHandlerResolver();
}
return this.namespaceHandlerResolver;
}
//这里定义了NamespaceHandlerResolver最终的初始化;代码跟踪了半天终于找到具体需要的一个属性的初始化啦
protected NamespaceHandlerResolver createDefaultNamespaceHandlerResolver() {
//嘿,就是你DefaultNamespaceHandlerResolver
return new DefaultNamespaceHandlerResolver(this.getResourceLoader().getClassLoader());
}
//【分支6】DefaultNamespaceHandlerResolver.resolve(namespaceUri)
/**
* 大概分析了这个类里面的属性,我们看到这里去加载了一个这么META-INF/spring.handlers
*
*/
public class DefaultNamespaceHandlerResolver implements NamespaceHandlerResolver {
public static final String DEFAULT_HANDLER_MAPPINGS_LOCATION = "META-INF/spring.handlers";
protected final Log logger;
private final ClassLoader classLoader;
private final String handlerMappingsLocation;
private volatile Map<String, Object> handlerMappings;
public DefaultNamespaceHandlerResolver() {
this((ClassLoader)null, "META-INF/spring.handlers");
}
public DefaultNamespaceHandlerResolver(ClassLoader classLoader) {
this(classLoader, "META-INF/spring.handlers");
//通过这里我们就可以发现,其实干了什么事情?其实就是去读取spring.handlers配置文件信息去加载一个handlerMappings
//为什么这么做,看看类(DefaultNamespaceHandlerResolver)默认命名空间处理器,这里就是将我们xml上面的标签映射到不同的处理器
//原来是这样,经过分析我们发现将xml中的aop标签的处理器变成代码中的AopNamespaceHandler
private Map<String, Object> getHandlerMappings() {
if(this.handlerMappings == null) {
synchronized(this) {
if(this.handlerMappings == null) {
try {
Properties ex = PropertiesLoaderUtils.loadAllProperties(this.handlerMappingsLocation, this.classLoader);
if(this.logger.isDebugEnabled()) {
this.logger.debug("Loaded NamespaceHandler mappings: " + ex);
}
ConcurrentHashMap handlerMappings = new ConcurrentHashMap(ex.size());
CollectionUtils.mergePropertiesIntoMap(ex, handlerMappings);
this.handlerMappings = handlerMappings;
} catch (IOException var5) {
throw new IllegalStateException("Unable to load NamespaceHandler mappings from location [" + this.handlerMappingsLocation + "]", var5);
}
}
}
}
return this.handlerMappings;
}
}
---
//spring.handlers配置文件信息如下
http\://www.springframework.org/schema/aop=org.springframework.aop.config.AopNamespaceHandler
【注】
在这块代码出让我怀疑人生了?
当new DefaultNamespaceHandlerResolver(this.getResourceLoader().getClassLoader())后我们看到
DefaultNamespaceHandlerResolver这个对象中的
private volatile Map<String, Object> handlerMappings
居然有属性了?
观看构造方法
public DefaultNamespaceHandlerResolver(ClassLoader classLoader, String handlerMappingsLocation) { this.logger = LogFactory.getLog(this.getClass()); Assert.notNull(handlerMappingsLocation, "Handler mappings location must not be null"); this.classLoader = classLoader != null?classLoader:ClassUtils.getDefaultClassLoader(); this.handlerMappingsLocation = handlerMappingsLocation; }
其中并没有设置handlerMappings属性值?
那到底handlerMappings是什么时候初始化的呢?【我很晕】
经过调试我们可以看见handlerMappings属性信息如下图所属
里面其实就是加载整个项目
META-INF/spring.handlers
文件其中就包含上图所示,很多处理器。
-----到底为什么,我还要研究研究----有待补充啊
【经过一夜思考】
1、当前项目运行环境(IDEA)
2、测试代码
public class Kid {
String name;
double height;
GregorianCalendar bDay;
public Kid () {
this.name = "HEAD";
this.height = 1;
this.bDay = new GregorianCalendar(1111,1,1);
}
public Kid (String n, double h, String date) {
// method that toString() can't find somehow
StringTokenizer st = new StringTokenizer(date, "/", true);
this.name = n;
this.height = h;
}
//overriding the toString() method
public String toString(){
this.height = 10;
System.out.println("toString"+this.height);
return name+" "+height+" "+height;
}
}
测试用例
public class Test { public static void main(String[] args) { Kid kid1 = new Kid("Lexie", 2.6, "11/5/2009"); System.out.println(kid1); } }
一、当在IDEA中配置了这个属性时
通过调式代码查看
height就变成10了。而在实例化这个对象的时候我们给height赋值是2.6。
而在Kid类中我们看到只有toString方法设置了height=10;
故而我们可以分析出
在勾选了所有的class都必须重写toString()时,IDEA工具在实例化这个对象的时候就隐式调用了toString这个方法。(但是通过断点又发现没有执行toString方法,具体为什么会出现这样我也不知道)
二、当未勾选时
调式结果:
也就是说这个值的变化就跟toString有关系。
进而我们观察spring这部分的源代码
在DefaultNamespaceHandlerResolver类中的toString方法
//他去执行了this.getHandlerMappings()
public String toString() {
return "NamespaceHandlerResolver using mappings " + this.getHandlerMappings();
}
//而getHandlerMappings就是完成spring.handlers的初始化
private Map<String, Object> getHandlerMappings() {
if(this.handlerMappings == null) {
synchronized(this) {
if(this.handlerMappings == null) {
try {
Properties ex = PropertiesLoaderUtils.loadAllProperties(this.handlerMappingsLocation, this.classLoader);
if(this.logger.isDebugEnabled()) {
this.logger.debug("Loaded NamespaceHandler mappings: " + ex);
}
ConcurrentHashMap handlerMappings = new ConcurrentHashMap(ex.size());
CollectionUtils.mergePropertiesIntoMap(ex, handlerMappings);
this.handlerMappings = handlerMappings;
} catch (IOException var5) {
throw new IllegalStateException("Unable to load NamespaceHandler mappings from location [" + this.handlerMappingsLocation + "]", var5);
}
}
}
}
return this.handlerMappings;
}
//也就是说我们为什么执行完构造方法后,发现
private volatile Map<String, Object> handlerMappings;有值了