All things are difficult before they are easy. The first chapter has started, and the rest is relatively easy. So last time we defined the DTD that we needed for the framework which is what we should write in XML, what elements we should have. We also bind THE DTD and XML together, have the DTD validate the XML format, and provide a Document object in DocumentHolder that retrieves the XML file according to the XML file path. This time we should switch our focus to getting the tag Element we need from the Document object.

Step by step, we have the Document object, let’s start from the Document object, by the way, this framework project adopts the idea of layered, layer by layer processing, for those who are not cold to IOC can also refer to this idea. We set up the element.loader package under the XML package. Since we don’t know at this stage what elements we need from the XML, we are going to provide a generic loader layer in this layer that will load all the tags in the XML file into memory and store them in a good format. According to the DTD file we defined, we know that there are only two elements in XML files: beans and bean elements. We focus on bean elements, and each bean element must have an ID element. We should also provide a method to get bean elements according to the ID. So how are we going to provide these two methods in terms of the document argument, are we going to start at document and go down every time, so what I’m going to do is I’m going to add another method that loads all the elements, Document loads all element objects into memory using key-value pairs to store ids and Element objects. Define the interface ElementLoader as follows

package com.tear.ioc.bean.xml.element.loader; import java.util.Collection; import org.dom4j.Document; import org.dom4j.Element; @author rongdi/public interface ElementLoader {/** * add all elements of a Document object *  * @param document */ public void addBeanElements(Document document); ** @param id * @return */ public Element getBeanElement(String id); Public Collection<Element> getBeanElements(); }Copy the code

If you need to handle beans, you can provide a similar method. We ignore this method.

The implementation class ElementLoaderImpl is as follows

package com.tear.ioc.bean.xml.element.loader; import java.util.Collection; import java.util.HashMap; import java.util.List; import java.util.Map; import org.dom4j.Document; import org.dom4j.Element; Public class ElementLoaderImpl implements ElementLoader {/** * defines a Map that holds all Element objects * under the root node (beans) of a Document object BeanElements = new HashMap<String,Element>(); beanElements = new HashMap<String,Element>(); @param Document */ @override public void addBeanElements(Document) Document) {/ / @suppressWarnings ("unchecked") List<Element> elementList = document.getRootElement().elements(); For (Element e:elementList) {/** * get the Element id attribute */ String id = e.attributeValue("id"); /** * Add the id attribute to the Map with the element */ this.beanelements. }} @override public Element getBeanElement(String id) {/** * return beanElements. } @override public Collection<Element> getBeanElements() {/** * getBeanElements(); */ return beanElements. Values (); }}Copy the code

At this level we can get all of the tag Element objects from the Document object, and we can also get individual elements from the ID, so we can go to the next level and parse the attributes of the bean Element or the child elements of the bean Element from the Element object. Create the element.parser package and define the interface BeanElementParser:

package com.rongdi.ioc.xml.element.parser; import java.util.List; import org.dom4j.Element; import com.rongdi.ioc.xml.autowire.Autowire; import com.rongdi.ioc.xml.element.LeafElement; import com.rongdi.ioc.xml.element.PropertyElement; /** * this is the interface to parse the loaded element, Provide a series of methods * @author rongdi ** / public Interface BeanElementParser {** ** Determine if a bean element needs lazy loading * @param Element * @return */ public boolean isLazy(Element beanElement); /** * Get the constructor-arg subtag of a bean element * @param Element * @return */ public List< element > getConstructorArgsElements(Element bean); * @param element * @param name * @return */ public String getAttribute(Element element, String name); Public Boolean isSingleton(Element bean); public Boolean isSingleton(element bean); Public List<Element> getPropertyElements(Element bean); @param Element @return public Autowire getAutowire(Element bean); Public List<LeafElement> public List<LeafElement> getConstructorValue(Element bean); /** * Get the value of all property elements under the bean element (including value and ref) * @param Element * @return */ List<PropertyElement> getPropertyValue(element) bean); }Copy the code

You can see from above that our source of processing has gone from a Document to an Element object, and that’s the idea of layering, layer by layer, layer by layer. As can be seen from the above, we have customized some bean elements, among which the LeafElement element is an interface. We have defined two common attributes type and value of all the elements we need, that is, the main attributes of any tag element, whether value or ref, are these two, for example, the following XML fragment:

<bean id="test12" class="com.rongdi.Test17">
        <property name="property1">
            <value type="java.lang.String">rongdi</value>
        </property>
        <property name="property2">
            <ref bean="test13"/>
        </property>
        <property name="property3">
            <value type="java.lang.Integer">22</value>
        </property>
        <property name="property4">
            <collection type="list">
                <value type="java.lang.Integer">1212</value>
                <value type="java.lang.String">rongdi</value>
            </collection>
        </property>
    </bean>
Copy the code

The ValueElement and RefElement codes are as follows

package com.tear.ioc.bean.xml.element; /** * this is the node element representing the ref tag, * @author rongdi */ public class RefElement implements LeafElement {/** * */ Private Object value; @param value */ public RefElement(Object value) {this.value = value; } /** Override public String getType() {return "ref"; } /** * overridden from the getValue method of the interface, returns the value of the element already stored in the member variable * via the constructor, Public Object getValue() {return this.value; }}Copy the code
package com.tear.ioc.bean.xml.element; /** * this is the node element representing the value tag, @author rongdi */ public class ValueElement implements LeafElement {/** * As with the RefNodeElement, provide a member variable that holds values between elements */ private Object value; @param value */ public ValueElement(Object value) {this.value = value; } @override public String getType() {return "value"; } /** * overridden from the getValue method of the interface, returns the value of the element already stored in the member variable * via the constructor, Public Object getValue() {return this.value; }}Copy the code

The PropertyElement itself has a name property and a child element that is either value or ref based on the label above

package com.tear.ioc.bean.xml.element; /** * this is the upper element of the ref and value node elements, This element may contain a ref or value child * @author rongdi ** / public class PropertyElement {/** * holds the name of the property element */ private String name; /** * private LeafElement LeafElement; * @return */ public String getName() {return name; } @param name */ public void setName(String name) {this.name = name; } @return public LeafElement getLeafElement() {return LeafElement; } @param nodeElement public void setLeafElement(LeafElement LeafElement) { this.leafElement = leafElement; } /** * The constructor saves the name of the property element and the following child elements to the member variable * @param name * @param leafElement */ public PropertyElement(String name, LeafElement leafElement) { this.name = name; this.leafElement = leafElement; }}Copy the code

There’s also Autowire involved in the interface, so we’re going to create a new Autowire package in the XML and then we’re going to create a new Autowire interface

package com.tear.ioc.bean.xml.autowire; @author rongdi */ public interface Autowire {/** * returns the value of the type of class that needs Autowire * @return */ public String getType(); }Copy the code

In fact, there are many kinds of autowire. In spring, there are byName and byType. In order to reflect the idea of object-oriented, either define interface and subclass. You can either define enumerations to distinguish between them, but I chose interfaces and subclasses for convenience. Subclasses are as follows

package com.tear.ioc.bean.xml.autowire; /** * Auto-assemble classes by name, * @author rongdi ** / public class ByNameAutowire implements Autowire {/** ** Implements Autowire with a constructor */ private String type; public ByNameAutowire(String type) { this.type = type; } /** * public String getType() {return type; }}Copy the code
package com.tear.ioc.bean.xml.autowire; @author rongdi ** / public class NoAutowire implements Autowire {@suppressWarnings ("unused"); private String type; public NoAutowire(String type) { this.type = type; */ public String getType() {return "no"; }}Copy the code

. One might find such fragments in XML elements

<bean id="test2" class="com.xx.Test4">
     <constructor-arg>
         <value type="java.lang.String">xx</value>
     </constructor-arg>
     <constructor-arg>
         <value type="java.lang.String">12</value>
     </constructor-arg>
</bean>
Copy the code

How did not mention a constructor in the interface – arg this element, this element has no attributes, actually only have one child, we getConstructorArgsElements can go directly to obtain his this value or ref element. We’ve covered all the beans involved in the BeanElementParser interface since then. Let’s look at the implementation class.

package com.tear.ioc.bean.xml.element.parser;

import java.util.ArrayList;
import java.util.List;

import org.dom4j.Element;

import com.tear.ioc.bean.xml.autowire.Autowire;
import com.tear.ioc.bean.xml.autowire.ByNameAutowire;
import com.tear.ioc.bean.xml.autowire.NoAutowire;
import com.tear.ioc.bean.xml.element.CollectionElement;
import com.tear.ioc.bean.xml.element.LeafElement;
import com.tear.ioc.bean.xml.element.PropertyElement;
import com.tear.ioc.bean.xml.element.RefElement;
import com.tear.ioc.bean.xml.element.ValueElement;

public class BeanElementParserImpl implements BeanElementParser {
    /**
     * 判断某一个元素(bean)是否需要延迟加载
     */
    @Override
    public boolean isLazy(Element beanElement) {
        /**
         * 得到该元素的lazy-init属性
         */
        String elementLazy = this.getAttribute(beanElement, "lazy-init");
        /**
         * 得到该元素的上层元素(beans)
         */
        Element parentElement = beanElement.getParent();
        /**
         * 得到该元素的上层元素(beans)的default-lazy-init属性
         */
        Boolean parentElementLazy = new Boolean(this.getAttribute(parentElement, "default-lazy-init"));
        if (parentElementLazy) {
            /**
             * 在根元素需要延迟加载的情况下,子节点(bean)不需要延迟那么不延迟加载
             */
            if ("false".equals(elementLazy)) {
                return false;
            }
            /**
             * 子节点需要延迟加载那么就延迟加载
             */
            return true;
        } else {
            /**
             * 根节点不需要延迟加载的情况下,子节点需要延迟加载那么就延迟加载
             */
            if ("true".equals(elementLazy)) {
                return true;
            }
            /**
             * 根节点不需要延迟加载的情况下,子节点也不需要延迟加载那么就不延迟加载
             */
            return false;
        }
        
    }
    /**
     * 得到bean元素下的所有的构造方法参数的元素constructor-arg
     */
    @SuppressWarnings("unchecked")
    @Override
    public List<Element> getConstructorArgsElements(Element element) {
        /**
         * 得到该元素的所有子元素
         */
        List<Element> children = element.elements();
        /**
         * 定义一个保存所需要的元素的ArrayList集合
         */
        List<Element> result = new ArrayList<Element>();
        /**
         * 遍历所有子元素,若果是constructor-arg元素直接加入到定义的ArrayList
         * 集合中
         */
        for (Element e : children) {
            if ("constructor-arg".equals(e.getName())) {
                result.add(e);
            }
        }
        /**
         * 返回所有的constructor-arg元素的集合
         */
        return result;
    }
    /**
     * 得到元素的name属性值
     */
    @Override
    public String getAttribute(Element element, String name) {
        String value = element.attributeValue(name);
        return value;
    }
    /**
     * 判断元素(bean)是否为单例的
     */
    @Override
    public boolean isSingleton(Element element) {
        /**
         * 如果元素的singleton属性为true(忽略大小写),那么返回true,
         * 如果是其他的字符串或者是空则返回false
         */
        Boolean singleton = new Boolean(this.getAttribute(element, "singleton"));
        return singleton;
    }
    /**
     * 得到某个元素(bean)下的所有property元素
     */
    @SuppressWarnings("unchecked")
    @Override
    public List<Element> getPropertyElements(Element element) {
        /**
         * 得到该元素的所有子元素
         */
        List<Element> children = element.elements();
        /**
         * 定义一个保存所需要的元素的ArrayList集合
         */
        List<Element> result = new ArrayList<Element>();
    
        /**
         * 遍历所有子元素,若果是property元素直接加入到定义的ArrayList
         * 集合中
         */
        for (Element e : children) {
            if("property".equals(e.getName())) {
                result.add(e);
            }
        }
        /**
         * 返回所有的Property元素的集合
         */
        return result;
    }
    /**
     * 得到某个元素(bean)的传入了自动装配类型值的对象
     */
    @Override
    public Autowire getAutowire(Element element) {
        /**
         * 得到某个元素(bean)的自动装配的类型值
         */
        String type = this.getAttribute(element, "autowire");
        /**
         * 得到该元素的父元素(beans)的默认的自动装配类型值
         */
        String parentType = this.getAttribute(element.getParent(), "default-autowire");
        if ("no".equals(parentType)) {
            /**
             * 如果根节点不需要自动装配,子节点需要以name自动装配那么返回一个以name自动装配的
             * ByNameAutowire对象
             */
            if ("byName".equals(type)) {
                return new ByNameAutowire(type);
            }
            /**
             * 如果父节点和子节点都不需要自动装配那么就返回一个表示不需要自动装配的NoAutowire对象
             */
            return new NoAutowire(type);
        } else if ("byName".equals(parentType)) {
            /**
             * 如果根节点需要自动装配而子节点不需要自动装配那么返回一个代表不需要自动装配的NoAutowire
             * 对象
             */
            if ("no".equals(type)) {
                return new NoAutowire(type);
            }
            /**
             * 如果根节点需要自动装配子节点也需要自动装配那么返回一个代表需要以name自动装配的
             *  ByNameAutowire对象
             */
            return new ByNameAutowire(type);
        }
        /**
         * 其他情况返回一个不需要自动装配的对象
         */
        return new NoAutowire(type);
    }
    /**
     * 得到所有的构造方法参数元素中的参数值,也就是ref或value元素
     */
    @SuppressWarnings("unchecked")
    @Override
    public List<LeafElement> getConstructorValue(Element element) {
        /**
         * 调用本类中的getConstructorElements方法取得全部的constructor-arg元素
         */
        List<Element> cons = this.getConstructorArgsElements(element);
        /**
         * 定义一个保存所有需要元素的ArrayList
         */
        List<LeafElement> result = new ArrayList<LeafElement>();
        /**
         * 遍历所有的construct-arg元素
         */
        for (Element e : cons) {
            /**
             * 获得constructor-arg下的ref元素或者value元素的其中一个,dtd定义两个元素
             * 只能有其中一个
             */
            List<Element> eles = e.elements();
            /**
             * 调用本类定义的getLeafElement方法获得构造参数元素下的ref或者value元素,封装成
             * RefLeafElement或ValueLeafElement
             */
            LeafElement leafElement = this.getLeafElement(eles.get(0));
            /**
             * 将封装好的RefLeafElement或ValueLeafElement元素加入到ArrayList中
             */
            result.add(leafElement);
        }
        /**
         * 返回NodeList的集合,里面装的是RefLeafElement或ValueLeafElement元素
         */
        return result;
    }

    @SuppressWarnings("unchecked")
    @Override
    public List<PropertyElement> getPropertyValue(Element element) {
        /**
         * 得到某一个元素下的所有property元素
         */
        List<Element> properties = this.getPropertyElements(element);
        /**
         * 定义一个ArrayList的集合准备保存所需要的Property元素
         */
        List<PropertyElement> result = new ArrayList<PropertyElement>();
        /**
         * 遍历所有的Property元素
         */
        for (Element e : properties) {
            /**
             * 获得property下的ref元素或者value元素或者collection中的一个,因为三个元素是互斥的只能存在一个
             */
            List<Element> eles = e.elements();
            /**
             * 得到List中的第一个ref元素或者是value元素
             */
            LeafElement leafElement = getLeafElement(eles.get(0));
            /**
             * 得到property的name属性的值
             */
            String propertyNameAtt = this.getAttribute(e, "name");
            /**
             * 将数据值和property元素的name属性封装成PropertyElement对象
             */
            PropertyElement pe = new PropertyElement(propertyNameAtt, leafElement);
            /**
             * 将该PreopertyElement元素加入到ArrayList中
             */
            result.add(pe);
        }
        /**
         * 返回PropertyElement元素的集合
         */
        return result;
    }
    /**
     * 该方法是根据传过来的Element对象将其封装成RefNodeElement或ValueNodeElement元素
     * 的对象
     * @param nodeElement
     * @return
     */
    private LeafElement getLeafElement(Element leafElement) {
        /**
         * 获得传过来的Element元素的名字
         */
        String name = leafElement.getName();
        /**
         * 如果是value元素
         */
        if ("value".equals(name)) {
            
            /**
             *调用本类定义的方法getValueOfValueElement根据value的type类型返回一个
             *Object数组形式的value值,在构造成为一个ValueElement对象返回
             */
            return new ValueElement(this.getValueOfValueElement(leafElement));
        }
        /**
         * 如果是ref元素
         */
        else if("ref".equals(name)) {
            /**
             * 返回一个将ref元素的bean属性的值传入的RefNodeElement对象
             */
            return new RefElement(this.getAttribute(leafElement, "bean"));
        }
        /**
         * 如果是collection元素
         */
        else if("collection".equals(name)) {
            /**
             * 调用本类的方法getCollectionElement得到一个CollectionElement元素返回
             */
            return this.getCollectionElement(leafElement);
        }
        /**
         * 如果不是这两种元素则返回null
         */
        return null;
    }
    /**
     * 这是一个ValueElement的值的Object数组
     * @param leafElement
     * @return
     */
    private Object getValueOfValueElement(Element leafElement) {
        /**
         * 得到该value元素的type属性的值
         */
        String typeName = leafElement.attributeValue("type");
        /**
         * 得到该value元素的值(即value标签之间的那个值)
         */
        String data = leafElement.getText();
        /**
         * 调用本类的方法返回一个ValueElement的值的数组形式
         */
        return IocUtil.getValue(typeName, data);
    }
    /**
     * 这是根据传过来的一个leafElement元素构造一个CollectionElement元素返回
     * @param leafElement
     * @return
     */
    @SuppressWarnings("unchecked")
    private CollectionElement getCollectionElement(Element leafElement) {
        /**
         * 定义一个保存所需的LeafElement元素的集合
         */
        List<LeafElement> temp = new ArrayList<LeafElement>();
        /**
         * 先得到该Collection元素的type属性值
         */
        String typeName = leafElement.attributeValue("type");
        /**
         * 根据type类型new一个CollectionElement
         */
        CollectionElement ce = new CollectionElement(typeName);
        /**
         * 得到该collection元素的所有子元素
         */
        List<Element> elements = leafElement.elements();
        /**
         * 遍历所有的子元素
         */
        for(Element e:elements) {
            /**
             * 得到Collection下子元素的元素名字
             */
            String tempName = e.getName();
            /**
             * 如果是value元素则调用对应方法得到该元素的值,并根据该值new一个ValueElement并保存到temp集合中
             */
            if("value".equals(tempName)) {
                temp.add(new ValueElement(this.getValueOfValueElement(e)));
            }
            /**
             * 如果是ref元素则调用对应的方法得到该元素的对应的值,并创建一个RefElement元素加到temp中
             */
            else if("ref".equals(tempName)) {
                temp.add(new RefElement(this.getAttribute(e, "bean")));
            }
        }
        /**
         * 将所得到的ValueElement或Refelement元素加到CollectionElement的集合中去
         */
        ce.setList(temp);
        /**
         * 返回构造好的CollectionElement
         */
        return ce;
    }
    

}
Copy the code

The IocUtil class involved in the above code is contained in the com.tetear. Ioc.util package as follows

package com.tear.ioc.util; /** * This is a helper class */ public class IocUtil {/** * Return the type if it is one of several basic data types in Java, Note that integer. type gets its class object * if it is not the base type then returns its class object using getClass () * @param obj * @return */ public static class <? > getClass(Object obj) { if (obj instanceof Integer) { return Integer.TYPE; } else if (obj instanceof Boolean) { return Boolean.TYPE; } else if (obj instanceof Long) { return Long.TYPE; } else if (obj instanceof Short) { return Short.TYPE; } else if (obj instanceof Double) { return Double.TYPE; } else if (obj instanceof Float) { return Float.TYPE; } else if (obj instanceof Character) { return Character.TYPE; } else if (obj instanceof Byte) { return Byte.TYPE; } return obj.getClass(); } /** * Check whether the type of className is a base type. Java.lang. Integer, for example, converts data * to the corresponding type. This method is called by methods in this class, @param className * @param data * @return */ public static Object GetValue (String className, String data) {/** * if (isType(className, String data); /** * if (isType(className, String data); "Integer")) { return Integer.parseInt(data); } else if (isType(className, "Boolean")) { return Boolean.valueOf(data); } else if (isType(className, "Long")) { return Long.valueOf(data); } else if (isType(className, "Short")) { return Short.valueOf(data); } else if (isType(className, "Double")) { return Double.valueOf(data); } else if (isType(className, "Float")) { return Float.valueOf(data); } else if (isType(className, "Character")) {** * return data.charat (0); } else if (isType(className, "Byte")) { return Byte.valueOf(data); } else {/** * if it is not a wrapper class for the eight basic data types, then it is a custom class. }} / * * * the method is to determine whether in the name of the class contains the corresponding methods of type string, such as the className: Java. Lang. * in the Integer contains an Integer so it returns true, does not contain false, * @param className * @param type * @return */ private static Boolean isType(String className, String type) { if (className.lastIndexOf(type) ! = -1) return true; return false; }}Copy the code

The BeanElementParserImpl class also includes the CollectionElement, which is an XML fragment like list or set that represents the CollectionElement

<bean id="test3" class="com.xx.Test3" >
        <property name="list">
            <collection type="list">
                <value type="java.lang.String">zhangsan</value>
                <value type="java.lang.String">12</value>
            </collection>
        </property>
        <property name="set">
            <collection type="set">
                <value type="java.lang.String">lisi</value>
                <value type="java.lang.String">34</value>
            </collection>
        </property>
        <property name="refTest">
            <collection type="list">
                <ref bean="test1"></ref>
                <ref bean="test2"></ref>
            </collection>
        </property>
    </bean>
Copy the code

The CollectionElement actually contains multiple value or ref elements. The CollectionElement looks like this

package com.tear.ioc.bean.xml.element; import java.util.ArrayList; import java.util.List; /** *; /** *; A set element that contains multiple leaf elements does not need to implement LeafElement per ref or value *, but here we implement LeafElement * in order to make CollectionElement and LeafElement * processed in the same way @author rongdi */ public class CollectionElement implements LeafElement { private String type; private List<LeafElement> list; public void setList(List<LeafElement> list) { this.list = list; } public void add(LeafElement leafElement) { this.list.add(leafElement); } @Override public String getType() { return this.type; } public CollectionElement(String type) { this.type = type; } public List<LeafElement> getList() { return list; } @Override public Object[] getValue() { List<Object> value = new ArrayList<Object>(); for(LeafElement le:this.getList()) { value.add(le.getValue()); } return value.toArray(); }}Copy the code

The annotations in the BeanElementParserImpl class are already written clearly, The only thing worth noting is getLeafElement(Element leafElement) else If (“collection”.equals(name)); if(“collection”.equals(name)); PropertyElement and constructors can have CollectionElement or ValueElement and RefElement. See the getConstructorValue method and getPropertyValue method in the BeanElementParserImpl class for details, and take a closer look to see the benefits of this.

Use test cases to test the test under the package build com. Tear. Ioc.. XML element. The loader and com. Tear. Ioc.. XML element. The parser

The codes are as follows

package com.tear.ioc.xml.element.loader;

import static org.junit.Assert.assertNotNull;

import java.util.Iterator;

import org.dom4j.Document;
import org.dom4j.Element;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import com.tear.ioc.bean.xml.document.XmlDocumentHolder;
import com.tear.ioc.bean.xml.element.loader.ElementLoader;
import com.tear.ioc.bean.xml.element.loader.ElementLoaderImpl;

public class ElementLoaderImplTest {
    XmlDocumentHolder xmlHolder;
    ElementLoader elementLoader;
    @Before
    public void setUp() throws Exception {
        xmlHolder = new XmlDocumentHolder();
        elementLoader = new ElementLoaderImpl();
        
    }

    @After
    public void tearDown() throws Exception {
        xmlHolder = null;
        elementLoader = null;
    }

    @Test
    public void testAddElements() {
        String filePath = "test/resources/element/ElementLoaderImpl.xml";
        Document document = xmlHolder.getDocument(filePath);
        assertNotNull(document);
        elementLoader.addBeanElements(document);
        Element e = elementLoader.getBeanElement("test1");
        assertNotNull(e);
        for(Iterator iter = elementLoader.getBeanElements().iterator();iter.hasNext();){
            System.out.println(iter.next());
        }
    }
}
Copy the code
package com.tear.ioc.xml.element.parser; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; import java.util.List; import org.dom4j.Document; import org.dom4j.Element; import org.junit.After; import org.junit.Before; import org.junit.Test; import com.tear.ioc.bean.xml.autowire.Autowire; import com.tear.ioc.bean.xml.document.XmlDocumentHolder; import com.tear.ioc.bean.xml.element.LeafElement; import com.tear.ioc.bean.xml.element.PropertyElement; import com.tear.ioc.bean.xml.element.RefElement; import com.tear.ioc.bean.xml.element.ValueElement; import com.tear.ioc.bean.xml.element.loader.ElementLoader; import com.tear.ioc.bean.xml.element.loader.ElementLoaderImpl; import com.tear.ioc.bean.xml.element.parser.BeanElementParser; import com.tear.ioc.bean.xml.element.parser.BeanElementParserImpl; public class ElementParserImplTest { private XmlDocumentHolder xmlHolder; private ElementLoader elementLoader; private BeanElementParser parser; @Before public void setUp() throws Exception { xmlHolder = new XmlDocumentHolder(); elementLoader = new ElementLoaderImpl(); String filePath = "test/resources/element/elementParserImpl.xml"; Document doc = xmlHolder.getDocument(filePath); elementLoader.addBeanElements(doc); parser = new BeanElementParserImpl(); } @After public void tearDown() throws Exception { xmlHolder = null; elementLoader = null; } @ Test public void testIsLazy () {/ / the first Element Element e = elementLoader. GetBeanElement (" test1-1 "); boolean result = parser.isLazy(e); assertTrue(result); . / / the second element is e = elementLoader getBeanElement (" test1-2 "); result = parser.isLazy(e); assertFalse(result); . / / the third element e = elementLoader getBeanElement (" test1-3 "); result = parser.isLazy(e); assertFalse(result); } @Test public void testGetConstructorElements() { Element e = elementLoader.getBeanElement("test2"); List<Element> constructorElements = parser.getConstructorArgsElements(e); assertEquals(constructorElements.size(), 2); } @Test public void testGetAttribute() { Element e = elementLoader.getBeanElement("test3"); String value = parser.getAttribute(e, "class"); assertEquals(value, "com.tear.Test5"); } @Test public void testIsSingleton() { Element e = elementLoader.getBeanElement("test4-1"); boolean result = parser.isSingleton(e); assertFalse(result); e = elementLoader.getBeanElement("test4-2"); result = parser.isSingleton(e); assertTrue(result); } @Test public void testGetPropertyElements() { Element e = elementLoader.getBeanElement("test6"); List<Element> elements = parser.getPropertyElements(e); assertEquals(elements.size(), 2); } @Test public void testGetAutowire() { Element e = elementLoader.getBeanElement("test10-1"); assertEquals(parser.getAttribute(e, "id"), "test10-1"); Autowire result = parser.getAutowire(e); assertEquals(result.getType(), "byName"); e = elementLoader.getBeanElement("test10-2"); result = parser.getAutowire(e); assertEquals(result.getType(), "no"); e = elementLoader.getBeanElement("test10-3"); result = parser.getAutowire(e); assertEquals(result.getType(), "no"); } @Test public void testGetConstructorValue() { Element e = elementLoader.getBeanElement("test11"); assertEquals(parser.getAttribute(e, "id"), "test11"); List<LeafElement> result = parser.getConstructorValue(e); assertEquals(result.size(), 2); ValueElement ve1 = (ValueElement)result.get(0); System.out.println(ve1.getValue()); assertEquals((String)ve1.getValue(),"tear"); RefElement re = (RefElement)result.get(1); assertEquals((String)re.getValue(), "test11"); } @Test public void testGetPropertyValue() { Element e = elementLoader.getBeanElement("test12"); List<PropertyElement> eles = parser.getPropertyValue(e); assertEquals(eles.size(), 4); System.out.println(eles.get(0).getLeafElement().getValue()); assertEquals(eles.get(0).getName(), "property1"); assertEquals(eles.get(0).getLeafElement().getValue(), "tear"); assertEquals(eles.get(0).getLeafElement().getType(), "value"); System.out.println(eles.get(3).getLeafElement()); System.out.println(eles.get(3).getLeafElement().getType()); Object[] obj = (Object[])eles.get(3).getLeafElement().getValue(); System.out.println(obj[0]); System.out.println(obj[1]); }}Copy the code

The XML file used for the test is placed under the resources. Element package of test. The elementLoaderImpl

<? The XML version = "1.0" encoding = "utf-8"? > <! DOCTYPE beans PUBLIC "-//RONGDI//DTD BEAN//CN" "http://www.cnblogs.com/rongdi/beans.dtd"> <beans> <bean id="test1" class="test1"></bean> <bean id="test2" class="test2"></bean> <bean id="test3" class="test3"></bean> </beans>Copy the code

The elementParserimpl.xml file is as follows

<? The XML version = "1.0" encoding = "utf-8"? > <! DOCTYPE beans PUBLIC "-//RONGDI//DTD BEAN//CN" "http://www.cnblogs.com/rongdi/beans.dtd"> <beans> <! -- isLazy--> <bean id="test1-1" class="com.tear.Test1" lazy-init="true"></bean> <bean id="test1-2" class="com.tear.Test2" lazy-init="default"></bean> <bean id="test1-3" class="com.tear.Test3" lazy-init="false"></bean> <! -- getConstructorElements--> <bean id="test2" class="com.tear.Test4"> <constructor-arg> <value type="java.lang.String">tear</value> </constructor-arg> <constructor-arg> <value type="java.lang.String">1989229</value>  </constructor-arg> </bean> <! -- getAttribute --> <bean id="test3" class="com.tear.Test5"></bean> <! -- isSingleton --> <bean id="test4-1" class="com.tear.Test6" singleton="false"></bean> <bean id="test4-2" class="com.tear.Test7"></bean> <! -- getConstructorArgs --> <bean id="test5" class="com.tear.Test8"> <constructor-arg> <value type="java.lang.String">wstear</value> </constructor-arg> <constructor-arg> <value type="java.lang.String">1989229</value> </constructor-arg> </bean> <! -- getPropertyElements--> <bean id="test6" class="com.tear.Test9"> <property name="test1"> <ref bean="test1"/> </property> <property name="test2"> <ref bean="test2"/> </property> </bean> <! -- getPropertyValues --> <bean id="test7" class="com.tear.Test10"> <property name="test1"> <value type="java.lang.String">wstear</value> </property> <property name="test2"> <value type="java.lang.String">1989229</value> </property> </bean> <! -- getPropertyRef --> <bean id="test8" class="com.tear.Test11"> <property name="test1"> <ref bean="test1"/> </property> <property name="test2"> <ref bean="test2"/> </property> </bean> <! -- getConstructorRef--> <bean id="test9" class="com.tear.Test12"> <constructor-arg> <ref bean="test1"/> </constructor-arg> <constructor-arg> <ref bean="test2"/> </constructor-arg> </bean> <! -- isAutowire --> <bean id="test10-1" class="com.tear.Test13" autowire="byName"> </bean> <bean id="test10-2" class="com.tear.Test14" autowire="no"> </bean> <bean id="test10-3" class="com.tear.Test15" autowire="default"> </bean> <bean id="test11" class="com.tear.Test11"> <constructor-arg> <value type="java.lang.String">tear</value> </constructor-arg> <constructor-arg> <ref bean="test11"/> </constructor-arg> </bean> <! -- getPropertyValue --> <bean id="test12" class="com.tear.Test17"> <property name="property1"> <value type="java.lang.String">tear</value> </property> <property name="property2"> <ref bean="test13"/> </property> <property name="property3"> <value type="java.lang.Integer">22</value> </property> <property name="property4"> <collection type="list"> <value type="java.lang.Integer">1212</value> <value type="java.lang.String">tear</value> </collection> </property> </bean> <bean class="com.tear.Test18" id="test13"></bean> </beans>Copy the code

We have since finished parsing all the business-relevant elements in the Document. Convenient for the next layer to deal with.

See you next time. If you have any questions, please leave a message directly. I will reply as soon as I see it