解析自定义标签元素java
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
【注】spring
在这块代码出让我怀疑人生了?app
当new DefaultNamespaceHandlerResolver(this.getResourceLoader().getClassLoader())后咱们看到工具
DefaultNamespaceHandlerResolver这个对象中的测试
private volatile Map<String, Object> handlerMappings
竟然有属性了?this
观看构造方法spa
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属性值?debug
那到底handlerMappings是何时初始化的呢?【我很晕】调试
通过调试咱们能够看见handlerMappings属性信息以下图所属code
里面其实就是加载整个项目
META-INF/spring.handlers
文件其中就包含上图所示,不少处理器。
-----到底为何,我还要研究研究----有待补充啊
【通过一晚上思考】
一、当前项目运行环境(IDEA)
二、测试代码
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); } }
1、当在IDEA中配置了这个属性时
经过调式代码查看
height就变成10了。而在实例化这个对象的时候咱们给height赋值是2.6。
而在Kid类中咱们看到只有toString方法设置了height=10;
故而咱们能够分析出
在勾选了全部的class都必须重写toString()时,IDEA工具在实例化这个对象的时候就隐式调用了toString这个方法。(可是经过断点又发现没有执行toString方法,具体为何会出现这样我也不知道)
2、当未勾选时
调式结果:
也就是说这个值的变化就跟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;有值了