码迷,mamicode.com
首页 > 编程语言 > 详细

Spring源码学习(四)自定义标签的解析

时间:2020-01-07 01:07:54      阅读:124      评论:0      收藏:0      [点我收藏+]

标签:ota   nbsp   raw   source   error   bst   注册   on()   sim   

新的一年 只争朝夕 不负韶华 加油加油??   

 

(一)自定义便签使用

步骤:(前提要将Spring Core包加入项目中)

(1)创建需要扩展的组件

(2)定义一个XSD文件描述组件内容

(3)创建一个文件,实现BeanDefinitionParse接口,用来解析XSD文件中的定义和组件定义

(4)创建一个Handler文件,扩展自NamespaceHandleSupport,目的是将组件注册到Spring容器

(5)编写Spring.Handlers和Spring.schemas文件

具体代码如下:

技术图片
 1 public class User {
 2     private  String id;
 3     private String usrnm;
 4     private  String email;
 5 
 6     public String getUsrnm() {
 7         return usrnm;
 8     }
 9 
10     public String getId() {
11         return id;
12     }
13 
14     public User setId(String id) {
15         this.id = id;
16         return this;
17     }
18 
19     public User setUsrnm(String usrnm) {
20         this.usrnm = usrnm;
21         return this;
22     }
23 
24     public String getEmail() {
25         return email;
26     }
27 
28     public User setEmail(String email) {
29         this.email = email;
30         return this;
31     }
32 }
User
 
技术图片autotag.xsd
 
技术图片MyNamespaceHandle
 
技术图片
 1 public class UserBeanDefinitionParse extends AbstractSimpleBeanDefinitionParser {
 2 
 3     // 会用到的
 4     @Override
 5     protected Class getBeanClass(Element ele){
 6         return User.class;
 7     }
 8 
 9     @Override
10     protected void doParse(Element element, BeanDefinitionBuilder builder) {
11         String name = element.getAttribute("usrnm");
12         String email = element.getAttribute("email");
13         if (StringUtils.hasText(name)) {
14             builder.addPropertyValue("usrnm", name);
15         }
16         if (StringUtils.hasText(email)) {
17             builder.addPropertyValue("email", email);
18         }
19     }
20 }
UserBeanDefinitionParse
 
技术图片Spring.handlers
 
技术图片
1 http\://www.vi.com/schema/user.xsd=aotutag.xsd
Spring.schema
 
技术图片
 1 public class AppTest {
 2 
 3     @Test
 4     public void test() {
 5         String path = "spring-config.xml";
 6         BeanFactory beanFactory = new XmlBeanFactory(new ClassPathResource(path));
 7         ApplicationContext bf = new ClassPathXmlApplicationContext(path);
 8         User bean = bf.getBean(User.class);
 9         System.out.println("  name:  " + bean.getUsrnm() + "  email:  " + bean.getEmail());
10     }
11 
12 
13 }
Test类

 运行结果:

name:  miya  email:  miya@163.com

 

(二)自定义标签解析

 

技术图片
 1     /**
 2      * Parse a custom element (outside of the default namespace).
 3      * @param ele the element to parse
 4      * @param containingBd the containing bean definition (if any)
 5      * @return the resulting bean definition
 6      */
 7     @Nullable
 8     public BeanDefinition parseCustomElement(Element ele, @Nullable BeanDefinition containingBd) {
 9         // 获取对应的命名空间
10         String namespaceUri = getNamespaceURI(ele);
11         if (namespaceUri == null) {
12             return null;
13         }
14         NamespaceHandler handler = this.readerContext.getNamespaceHandlerResolver().resolve(namespaceUri);
15         if (handler == null) {
16             error("Unable to locate Spring NamespaceHandler for XML schema namespace [" + namespaceUri + "]", ele);
17             return null;
18         }
19         return handler.parse(ele, new ParserContext(this.readerContext, this, containingBd));
20     }
parseCustomElement

(1)获取命名空间

(2)根据命名空间找到对应的处理器

(3)解析

(一)获取自定义标签处理器

技术图片
 1     /**
 2      * Locate the {@link NamespaceHandler} for the supplied namespace URI
 3      * from the configured mappings.
 4      * @param namespaceUri the relevant namespace URI
 5      * @return the located {@link NamespaceHandler}, or {@code null} if none found
 6      */
 7     @Override
 8     @Nullable
 9     public NamespaceHandler resolve(String namespaceUri) {
10         //获取已配置的handlers
11         Map<String, Object> handlerMappings = getHandlerMappings();
12         //根据命名空间找到对应的处理类
13         Object handlerOrClassName = handlerMappings.get(namespaceUri);
14         if (handlerOrClassName == null) {
15             return null;
16         }
17         else if (handlerOrClassName instanceof NamespaceHandler) {
18             // 已经做过解析 直接从缓存中读取
19             return (NamespaceHandler) handlerOrClassName;
20         }
21         else {
22             String className = (String) handlerOrClassName;
23             try {
24                 // 使用反射将类路径转化为类
25                 Class<?> handlerClass = ClassUtils.forName(className, this.classLoader);
26                 if (!NamespaceHandler.class.isAssignableFrom(handlerClass)) {
27                     throw new FatalBeanException("Class [" + className + "] for namespace [" + namespaceUri +
28                             "] does not implement the [" + NamespaceHandler.class.getName() + "] interface");
29                 }
30                 //初始化类
31                 NamespaceHandler namespaceHandler = (NamespaceHandler) BeanUtils.instantiateClass(handlerClass);
32                 // 调用自定义的NamespaceHandler的init(方法)
33                 namespaceHandler.init();
34                 // 记录在缓存中
35                 handlerMappings.put(namespaceUri, namespaceHandler);
36                 return namespaceHandler;
37             }
38             catch (ClassNotFoundException ex) {
39                 throw new FatalBeanException("Could not find NamespaceHandler class [" + className +
40                         "] for namespace [" + namespaceUri + "]", ex);
41             }
42             catch (LinkageError err) {
43                 throw new FatalBeanException("Unresolvable class definition for NamespaceHandler class [" +
44                         className + "] for namespace [" + namespaceUri + "]", err);
45             }
46         }
47     }
resolve

(1)获取所有的handlers

(2)根据命名空间获取相应的handler

(3)已做解析直接获取

(4)没有做过解析,则使用反射获取类,调用自定义的handle,并记录在缓存中

(二)标签解析

技术图片
 1     /**
 2      * Parses the supplied {@link Element} by delegating to the {@link BeanDefinitionParser} that is
 3      * registered for that {@link Element}.
 4      */
 5     @Override
 6     @Nullable
 7     public BeanDefinition parse(Element element, ParserContext parserContext) {
 8         // 根据localname获取相应的解析器(在自定义的方法中注册的)
 9         BeanDefinitionParser parser = findParserForElement(element, parserContext);
10         return (parser != null ? parser.parse(element, parserContext) : null);
11     }
parse

(1)获取解析器

(2)解析

技术图片
 1 @Override
 2     @Nullable
 3     public final BeanDefinition parse(Element element, ParserContext parserContext) {
 4         AbstractBeanDefinition definition = parseInternal(element, parserContext);
 5         if (definition != null && !parserContext.isNested()) {
 6             try {
 7                 String id = resolveId(element, definition, parserContext);
 8                 // 必须有id
 9                 if (!StringUtils.hasText(id)) {
10                     parserContext.getReaderContext().error(
11                             "Id is required for element ‘" + parserContext.getDelegate().getLocalName(element)
12                                     + "‘ when used as a top-level tag", element);
13                 }
14                 String[] aliases = null;
15                 if (shouldParseNameAsAliases()) {
16                     String name = element.getAttribute(NAME_ATTRIBUTE);
17                     if (StringUtils.hasLength(name)) {
18                         aliases = StringUtils.trimArrayElements(StringUtils.commaDelimitedListToStringArray(name));
19                     }
20                 }
21                 BeanDefinitionHolder holder = new BeanDefinitionHolder(definition, id, aliases);
22                 registerBeanDefinition(holder, parserContext.getRegistry());
23                 if (shouldFireEvents()) {
24                     BeanComponentDefinition componentDefinition = new BeanComponentDefinition(holder);
25                     postProcessComponentDefinition(componentDefinition);
26                     parserContext.registerComponent(componentDefinition);
27                 }
28             }
29             catch (BeanDefinitionStoreException ex) {
30                 String msg = ex.getMessage();
31                 parserContext.getReaderContext().error((msg != null ? msg : ex.toString()), element);
32                 return null;
33             }
34         }
35         return definition;
36     }
parse

真正的解析

(1)调用自定义的解析函数,parseInternal方法

(2)将解析后的AbstractBeanDefinition封装成BeanDefinitionHolder,完成注册

技术图片
 1     @Override
 2     protected final AbstractBeanDefinition parseInternal(Element element, ParserContext parserContext) {
 3         BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition();
 4 
 5         String parentName = getParentName(element);
 6         if (parentName != null) {
 7             builder.getRawBeanDefinition().setParentName(parentName);
 8         }
 9         // 会调用自定会议解析器中的getBeanClass方法
10         Class<?> beanClass = getBeanClass(element);
11         if (beanClass != null) {
12             builder.getRawBeanDefinition().setBeanClass(beanClass);
13         }
14         else {
15             String beanClassName = getBeanClassName(element);
16             if (beanClassName != null) {
17                 builder.getRawBeanDefinition().setBeanClassName(beanClassName);
18             }
19         }
20         builder.getRawBeanDefinition().setSource(parserContext.extractSource(element));
21         BeanDefinition containingBd = parserContext.getContainingBeanDefinition();
22         if (containingBd != null) {
23             // Inner bean definition must receive same scope as containing bean.
24             builder.setScope(containingBd.getScope());
25         }
26         if (parserContext.isDefaultLazyInit()) {
27             // Default-lazy-init applies to custom bean definitions as well.
28             builder.setLazyInit(true);
29         }
30         //调用子类的doParse方法
31         doParse(element, parserContext, builder);
32         return builder.getBeanDefinition();
33     }
parseInternal

 

Spring源码学习(四)自定义标签的解析

标签:ota   nbsp   raw   source   error   bst   注册   on()   sim   

原文地址:https://www.cnblogs.com/VVII/p/12154249.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!