Everything is difficult at the beginning , The first chapter has already started , After that, things are relatively simple . Last time I defined what the framework needs dtd That's the rule xml How to write in , What are the elements . And we also let dtd and xml Tied together , send dtd Yes xml Check the format of , And in DocumentHolder It provides the basis for xml File path access xml Of documents Document object . This time we should focus on document Get the tag we need from the object Element Element .

Step by step , We have it. document object , Let's start from document Target , By the way, this framework project adopts the idea of layering , Layer by layer , For ioc If you don't have a cold, you can also refer to this idea . We are xml Create... Under the package element.loader package , Because at this stage we don't know what we really need xml So we're going to provide a generic loader layer , Specially will xml All tags in the file are loaded into memory and saved in a good format , And according to the method provided to get all the element sets, it is convenient for the next layer to use , According to our definition of dtd Documents we know ,xml There are only two elements in the file beans and bean Elements , Let's focus on bean Elements , And each bean The element must have id Elements , We should also provide evidence id obtain bean Element method . So what should we do next document How about these two methods provided by parameters , Every time we start from document Start traversing down , So the way I give you is to add another way to load all the elements , basis document Will all element Object is loaded into memory. Using key value pairs will id and Element Save the object . Defining interfaces ElementLoader as follows

package com.tear.ioc.bean.xml.element.loader;
import java.util.Collection;
import org.dom4j.Document;
import org.dom4j.Element; /**
* Load a Document All of the objects Element Provide preservation
* @author rongdi
*/
public interface ElementLoader {
/**
* Add a Document All of the objects Element
*
* @param document
*/
public void addBeanElements(Document document); /**
* According to the id get Element object
*
* @param id
* @return
*/
public Element getBeanElement(String id); /**
* Return all Element
*
* @return
*/
public Collection<Element> getBeanElements();
}

From the method name above, we can see that we don't have a root element beans, If you need to deal with beans, The guys can offer similar methods themselves , Here we're ignoring .

Implementation class ElementLoaderImpl 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 {
/**
* Define a Map To save one Document Object (beans) All of them Element object
* Map Of key Corresponding bean Elemental id attribute , and Map Of value Corresponding bean Elements
*/
Map<String,Element> beanElements = new HashMap<String,Element>();
/**
* Will a Document All of the objects Element Add to save Element Object's Map in
* @param document
*/
@Override
public void addBeanElements(Document document) {
/**
* First get the root node beans To get bean node
*/
@SuppressWarnings("unchecked")
List<Element> elementList = document.getRootElement().elements();
/**
* Loop all the elements of id Attributes and elements are added to one by one Map in
*/
for(Element e:elementList) {
/**
* Get the elements of id attribute
*/
String id = e.attributeValue("id");
/**
* take id Attribute is added with the element to Map in
*/
this.beanElements.put(id, e);
}
} @Override
public Element getBeanElement(String id) {
/**
* according to id From saving all the elements Map Take out the corresponding element in
*/
return beanElements.get(id);
} @Override
public Collection<Element> getBeanElements() {
/**
* Get the... That holds all the elements Map All in value Set , It's a collection of all the elements
*/
return beanElements.values();
} }

At this level, we can base on document Object gets all the tags Element A collection of objects , It can also be based on id Get a single Element, So let's go to the next level , It can be based on Element Object to parse bean An attribute of an element or bean The child element of the element . newly build element.parser package , stay parser Defining interfaces 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 parsing load element The interface of , Provide a range of methods
* @author rongdi
*
*/
public interface BeanElementParser {
/**
* Judge a bean Whether the element needs to be loaded late
* @param element
* @return
*/
public boolean isLazy(Element beanElement); /**
* To obtain a bean Under the element constructor-arg( Constructor parameter ) The child tag of
* @param element
* @return
*/
public List<Element> getConstructorArgsElements(Element bean); /**
* The element attribute is name The attribute value
* @param element
* @param name
* @return
*/
public String getAttribute(Element element, String name); /**
* Judge a bean Whether the element is configured as singleton
* @param element
* @return
*/
public boolean isSingleton(Element bean); /**
* To obtain a bean All under the element property Elements
* @param element
* @return
*/
public List<Element> getPropertyElements(Element bean); /**
* Return to one bean Element corresponding Autowire object
* @param element
* @return
*/
public Autowire getAutowire(Element bean); /**
* obtain bean All under the element constructor-arg Value ( Include value and ref)
* @param element
* @return
*/
public List<LeafElement> getConstructorValue(Element bean); /**
* obtain bean All under the element property The value of the element ( Include value and ref)
* @param element
* @return
*/
List<PropertyElement> getPropertyValue(Element bean);
}

It can be seen from the above that our processing source is from the upper level Document Turned into Element Object , This is the idea of stratification , Layer by layer , Layer by layer transmission . As can be seen from the above, we have customized some bean Elements , among LeafElement The element is an interface , We define two common properties for all the elements we need type and value, That is, any tag element, whether it's value still ref The most important attributes are these two, such as 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>

ValueElement and RefElement The code is as follows

package com.tear.ioc.bean.xml.element;
/**
* This represents ref The node element of the label , Realized LeafElement Interface
* @author rongdi
*/
public class RefElement implements LeafElement {
/**
* Define a member variable to hold ref Elemental value value , That is, the value between the start tag and the end tag
*/
private Object value;
/**
* Use the construction method to construct ref Elemental value The value is passed to the member variable to save
* @param value
*/
public RefElement(Object value) {
this.value = value;
}
/**
* Rewrite the interface getType Method , Return your own type , Because the type is ref So you can go back to ref
*/
@Override
public String getType() {
return "ref";
}
/**
* Rewriting self interface getValue Method , Returns the value It's worth it value Has been saved to a member variable by a construction method
* It's in , So just return the member variable directly
*/
@Override
public Object getValue() { return this.value;
} }
package com.tear.ioc.bean.xml.element;
/**
* This represents value The node element of the label , Realized LeafElement Interface
* @author rongdi
*/
public class ValueElement implements LeafElement {
/**
* Same as RefNodeElement Element should also provide a member variable to store the information between elements value value
*/
private Object value;
/**
* Use the construction method to construct value Elemental value The value is passed to the member variable to save
* @param value
*/
public ValueElement(Object value) {
this.value = value;
}
/**
* Rewrite the interface getType Method , Return your own type , Because the type is value So you can go back to value character string
*/
@Override
public String getType() { return "value";
}
/**
* Rewriting self interface getValue Method , Returns the value It's worth it value Has been saved to a member variable by a construction method
* It's in , So just return the member variable directly
*/
@Override
public Object getValue() { return this.value;
} }

as for PropertyElement According to the label above, he has a name attribute , There's also a sub element that either value Or ref The code is as follows

package com.tear.ioc.bean.xml.element;
/**
* This is a ref and value The upper element of the node element , This element may contain ref Or is it value Subelement
* @author rongdi
*
*/
public class PropertyElement {
/**
* For preservation property Elemental name Property value
*/
private String name;
/**
* For preservation Property Under the element ref Or is it value Subelement
*/
private LeafElement leafElement;
/**
* Take out property Elemental name Method of attribute value
* @return
*/
public String getName() {
return name;
}
/**
* Set up property Elemental name Method of attribute value
* @param name
*/
public void setName(String name) {
this.name = name;
}
/**
* Take out property The method of the child element below the element , Returns the interface type of the child element
* @return
*/
public LeafElement getLeafElement() {
return leafElement;
}
/**
* Set up property The method of the child element below the element
* @param nodeElement
*/
public void setLeafElement(LeafElement leafElement) {
this.leafElement = leafElement;
}
/**
* The construction method will property Elemental name The value and the following child elements are saved in the member variable
* @param name
* @param leafElement
*/
public PropertyElement(String name, LeafElement leafElement) {
this.name = name;
this.leafElement = leafElement;
}
}

The interface involves Autowire, Here we are xml Create a new one in autowire Then create a new interface Autowire

package com.tear.ioc.bean.xml.autowire;
/**
* This is the interface for automatic assembly
* @author rongdi
*/
public interface Autowire {
/**
* Returns the value of the type in the class that needs to be automatically assembled
* @return
*/
public String getType();
}

There may be a lot of questions here ,autowire As bean An attribute of represents automatic assembly , Why is it defined as an interface , In fact, there are many kinds of automatic assembly , common spring There is byName and byType, In order to embody the idea of object-oriented, it can be defined as interfaces and subclasses , Or it can be directly defined as enumeration to distinguish , I've chosen interfaces and subclasses here to facilitate processing , Subclasses are as follows

package com.tear.ioc.bean.xml.autowire;
/**
* Class automatically assembled by name , Interface for automatic assembly
* @author rongdi
*
*/
public class ByNameAutowire implements Autowire {
/**
* Use a construction method to save the type value of the incoming auto assembly
*/
private String type;
public ByNameAutowire(String type) {
this.type = type;
}
/**
* Return the input that needs to be automatically assembled value value
*/
public String getType() {
return type;
}
}
package com.tear.ioc.bean.xml.autowire;
/**
* This class represents a class that does not automatically assemble
* @author rongdi
*
*/
public class NoAutowire implements Autowire { @SuppressWarnings("unused")
private String type;
public NoAutowire(String type) {
this.type = type;
}
/**
* Go straight back to no, Indicates that automatic assembly is not required
*/
public String getType() {
return "no";
} }

. Someone might find out xml This kind of fragment can appear in the element

<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>

Why is it not mentioned in the interface constructor-arg This element , In fact, this element has no attributes of its own , It's just a child element , We getConstructorArgsElements You can go directly to get the following value perhaps ref Element is OK . Since then BeanElementParser The interface involves bean We're all done . 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 {
/**
* Judge an element (bean) Do you need to delay loading
*/
@Override
public boolean isLazy(Element beanElement) {
/**
* Get the... Of the element lazy-init attribute
*/
String elementLazy = this.getAttribute(beanElement, "lazy-init");
/**
* Get the upper element of the element (beans)
*/
Element parentElement = beanElement.getParent();
/**
* Get the upper element of the element (beans) Of default-lazy-init attribute
*/
Boolean parentElementLazy = new Boolean(this.getAttribute(parentElement, "default-lazy-init"));
if (parentElementLazy) {
/**
* When the root element needs to be loaded late , Child node (bean) You don't need to delay so don't delay loading
*/
if ("false".equals(elementLazy)) {
return false;
}
/**
* If the child node needs to delay loading, delay loading
*/
return true;
} else {
/**
* When the root node does not need to delay loading , If the child node needs to delay loading, delay loading
*/
if ("true".equals(elementLazy)) {
return true;
}
/**
* When the root node does not need to delay loading , The child node does not need to delay loading, so it does not need to delay loading
*/
return false;
} }
/**
* obtain bean All the elements that construct method parameters under the element constructor-arg
*/
@SuppressWarnings("unchecked")
@Override
public List<Element> getConstructorArgsElements(Element element) {
/**
* Get all the child elements of that element
*/
List<Element> children = element.elements();
/**
* Define a... That holds the required elements ArrayList aggregate
*/
List<Element> result = new ArrayList<Element>();
/**
* Traverse all child elements , If it is constructor-arg Elements are added directly to the defined ArrayList
* Collection
*/
for (Element e : children) {
if ("constructor-arg".equals(e.getName())) {
result.add(e);
}
}
/**
* Return all constructor-arg A collection of elements
*/
return result;
}
/**
* Get the elements of name Property value
*/
@Override
public String getAttribute(Element element, String name) {
String value = element.attributeValue(name);
return value;
}
/**
* Element of judgement (bean) Whether it is singleton or not
*/
@Override
public boolean isSingleton(Element element) {
/**
* If the element's singleton The attribute is true( Ignore case ), Then the return true,
* If it is another string or empty, it returns false
*/
Boolean singleton = new Boolean(this.getAttribute(element, "singleton"));
return singleton;
}
/**
* Get an element (bean) All under property Elements
*/
@SuppressWarnings("unchecked")
@Override
public List<Element> getPropertyElements(Element element) {
/**
* Get all the child elements of that element
*/
List<Element> children = element.elements();
/**
* Define a... That holds the required elements ArrayList aggregate
*/
List<Element> result = new ArrayList<Element>(); /**
* Traverse all child elements , If it is property Elements are added directly to the defined ArrayList
* Collection
*/
for (Element e : children) {
if("property".equals(e.getName())) {
result.add(e);
}
}
/**
* Return all Property A collection of elements
*/
return result;
}
/**
* Get an element (bean) The object with the autoassemble type value passed in
*/
@Override
public Autowire getAutowire(Element element) {
/**
* Get an element (bean) The type value of automatic assembly for
*/
String type = this.getAttribute(element, "autowire");
/**
* Get the parent element of the element (beans) The default auto assembly type value for
*/
String parentType = this.getAttribute(element.getParent(), "default-autowire");
if ("no".equals(parentType)) {
/**
* If the root node does not need automatic assembly , The child node needs to be name Automatic assembly then returns a with name Self assembling
* ByNameAutowire object
*/
if ("byName".equals(type)) {
return new ByNameAutowire(type);
}
/**
* If both the parent node and the child node do not need to be automatically assembled, then a NoAutowire object
*/
return new NoAutowire(type);
} else if ("byName".equals(parentType)) {
/**
* If the root node needs automatic assembly and the child node does not need automatic assembly, then a NoAutowire
* object
*/
if ("no".equals(type)) {
return new NoAutowire(type);
}
/**
* If the root node needs to be automatically assembled and the child node needs to be automatically assembled, then a representation needs to be returned with name Self assembling
* ByNameAutowire object
*/
return new ByNameAutowire(type);
}
/**
* Other cases return an object that does not need automatic assembly
*/
return new NoAutowire(type);
}
/**
* Get the parameter values of all the construction method parameter elements , That is to say ref or value Elements
*/
@SuppressWarnings("unchecked")
@Override
public List<LeafElement> getConstructorValue(Element element) {
/**
* Call... In this class getConstructorElements Method to get all of constructor-arg Elements
*/
List<Element> cons = this.getConstructorArgsElements(element);
/**
* Define a... That holds all the required elements ArrayList
*/
List<LeafElement> result = new ArrayList<LeafElement>();
/**
* Traverse all construct-arg Elements
*/
for (Element e : cons) {
/**
* get constructor-arg Under the ref Element or value One of the elements ,dtd Define two elements
* There can only be one of them
*/
List<Element> eles = e.elements();
/**
* Call... Defined by this class getLeafElement Method to get the ref perhaps value Elements , Encapsulated into
* RefLeafElement or ValueLeafElement
*/
LeafElement leafElement = this.getLeafElement(eles.get(0));
/**
* Will be packaged RefLeafElement or ValueLeafElement Elements are added to ArrayList in
*/
result.add(leafElement);
}
/**
* return NodeList Set , It's filled with RefLeafElement or ValueLeafElement Elements
*/
return result;
} @SuppressWarnings("unchecked")
@Override
public List<PropertyElement> getPropertyValue(Element element) {
/**
* Get all of them under an element property Elements
*/
List<Element> properties = this.getPropertyElements(element);
/**
* Define a ArrayList Is ready to save what you need Property Elements
*/
List<PropertyElement> result = new ArrayList<PropertyElement>();
/**
* Traverse all Property Elements
*/
for (Element e : properties) {
/**
* get property Under the ref Element or value Element or collection One of them , Because the three elements are mutually exclusive, there can only be one
*/
List<Element> eles = e.elements();
/**
* obtain List The first of ref Elements or value Elements
*/
LeafElement leafElement = getLeafElement(eles.get(0));
/**
* obtain property Of name The value of the property
*/
String propertyNameAtt = this.getAttribute(e, "name");
/**
* Combine the data value with property Elemental name Attributes are encapsulated as PropertyElement object
*/
PropertyElement pe = new PropertyElement(propertyNameAtt, leafElement);
/**
* Will be PreopertyElement Elements are added to ArrayList in
*/
result.add(pe);
}
/**
* return PropertyElement A collection of elements
*/
return result;
}
/**
* The method is based on Element Object encapsulates it as RefNodeElement or ValueNodeElement Elements
* The object of
* @param nodeElement
* @return
*/
private LeafElement getLeafElement(Element leafElement) {
/**
* Get what's coming Element The name of the element
*/
String name = leafElement.getName();
/**
* If it is value Elements
*/
if ("value".equals(name)) { /**
* Call the method defined in this class getValueOfValueElement according to value Of type Type returns a
*Object In array form value value , In the construction of a ValueElement Object returns
*/
return new ValueElement(this.getValueOfValueElement(leafElement));
}
/**
* If it is ref Elements
*/
else if("ref".equals(name)) {
/**
* Return to a ref Elemental bean The value of the RefNodeElement object
*/
return new RefElement(this.getAttribute(leafElement, "bean"));
}
/**
* If it is collection Elements
*/
else if("collection".equals(name)) {
/**
* Call the methods of this class getCollectionElement Get one CollectionElement Element returns
*/
return this.getCollectionElement(leafElement);
}
/**
* If not, returns null
*/
return null;
}
/**
* This is a ValueElement The value of the Object Array
* @param leafElement
* @return
*/
private Object getValueOfValueElement(Element leafElement) {
/**
* Get it value Elemental type The value of the property
*/
String typeName = leafElement.attributeValue("type");
/**
* Get it value The value of the element ( namely value The value between the tags )
*/
String data = leafElement.getText();
/**
* Call the method of this class to return a ValueElement The array form of the values of
*/
return IocUtil.getValue(typeName, data);
}
/**
* This is based on a message from leafElement The element constructs a CollectionElement Element returns
* @param leafElement
* @return
*/
@SuppressWarnings("unchecked")
private CollectionElement getCollectionElement(Element leafElement) {
/**
* Define what is needed to save LeafElement A collection of elements
*/
List<LeafElement> temp = new ArrayList<LeafElement>();
/**
* First get the Collection Elemental type Property value
*/
String typeName = leafElement.attributeValue("type");
/**
* according to type type new One CollectionElement
*/
CollectionElement ce = new CollectionElement(typeName);
/**
* Get it collection All child elements of the element
*/
List<Element> elements = leafElement.elements();
/**
* Traverse all the child elements
*/
for(Element e:elements) {
/**
* obtain Collection The element name of the subelement
*/
String tempName = e.getName();
/**
* If it is value Element, call the corresponding method to get the value of the element , And according to this value new One ValueElement And save to temp Collection
*/
if("value".equals(tempName)) {
temp.add(new ValueElement(this.getValueOfValueElement(e)));
}
/**
* If it is ref Element calls the corresponding method to get the corresponding value of the element , And create a RefElement Elements added to temp in
*/
else if("ref".equals(tempName)) {
temp.add(new RefElement(this.getAttribute(e, "bean")));
}
}
/**
* Take what you get ValueElement or Refelement Elements added to CollectionElement In the collection of
*/
ce.setList(temp);
/**
* Back to constructed CollectionElement
*/
return ce;
} }

The code above refers to IocUtil Class. This class is placed in com.tear.ioc.util The contents of the package are as follows

package com.tear.ioc.util;
/**
* This is a help class
*/
public class IocUtil {
/**
* If the type is java Then return its type , Be careful Integer.type Is to get his class object
* If not the base type, use getClass() Back to its Class object
* @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();
}
/**
* Judge className Whether the type of is the base type . Such as java.lang.Integer, Yes, convert the data
* The method is called by the method in this class , The function is based on type The value of type will correspond to value Data conversion
* In correspondence with type Type value
* @param className
* @param data
* @return
*/
public static Object getValue(String className, String data) {
/**
* All of the following if and else if It's all about judging whether it's java Of 8 The wrapper type of the basic data type in
*/
if (isType(className, "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")) {
/**
* If it is Character Type takes the first character
*/
return data.charAt(0);
} else if (isType(className, "Byte")) {
return Byte.valueOf(data);
} else {
/**
* If not 8 A basic data type wrapper class is a custom class , Returns the value directly
*/
return data;
}
}
/**
* This method is to determine whether the class name contains the corresponding type String method , Such as judgment className:java.lang.Integer in
* Does it include Integer So back to true, If not, return false, This method is for the above method to call
* @param className
* @param type
* @return
*/
private static boolean isType(String className, String type) {
if (className.lastIndexOf(type) != -1)
return true;
return false;
}
}

BeanElementParserImpl Class also involves CollectionElement Elements , This element is the element that represents the set list perhaps set as follows xml fragment

<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>

CollectionElement The element actually contains multiple value perhaps ref Elements CollectionElement as follows

package com.tear.ioc.bean.xml.element;
import java.util.ArrayList;
import java.util.List; /**
* Here we're using the composite pattern , A set element itself contains multiple leaf elements ref perhaps value
* It doesn't have to be implemented LeafElement But here we are to make CollectionElement and LeafElement
* Handled in the same way, so we implemented LeafElement
* @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();
} }

about BeanElementParserImpl The comments in the class are very clear , As for the only thing worth noting is getLeafElement(Element leafElement) This method else if("collection".equals(name)) Here you can see why CollectionElement To use composite patterns to implement LeafElement It's for the convenience of unified processing .PropertyElement And construction methods CollectionElement Or is it ValueElement and RefElement If it can't be unified into LeafElement It's a lot of trouble to deal with it , Specific view BeanElementParserImpl Class getConstructorValue Methods and getPropertyValue Method , Take a closer look and you'll see the benefits of this .

Test with test cases test Create... Under the package com.tear.ioc.xml.element.loader and com.tear.ioc.xml.element.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());
}
}
}
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() { // First element
Element e = elementLoader.getBeanElement("test1-1");
boolean result = parser.isLazy(e);
assertTrue(result);
// The second element
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]); } }

The test uses xml Files in test Next resources.element It's a bag elementLoaderImpl.xml The contents of the document are as follows

<?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>

elementParserImpl.xml The documents are as follows

<?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>

Since then, we have completed the task of document Resolution of all business related elements in . Convenient for the next layer to deal with .

See you next time , If you have any questions, you can leave a message directly , I will reply as soon as I see it , See Baidu cloud address for detailed code :http://pan.baidu.com/s/1bncXTM3

Do it yourself IOC frame ( Two ) More articles about

  1. Do it yourself IOC frame ( One )

    Blog created 2 More than years , Never dare to write anything , I'm afraid the technology is not enough to mislead others .2 Today, more than years later, I am confident that I can make a modest contribution to those in need . This is my first time to write a blog , Let me introduce myself first . My online name is teardrop , A very sad name , In life ...

  2. Do it yourself IOC frame ( Four )

    It's finally the exciting moment , First of all, thank you for your reading , If you can comment more , More discussion is better , No communication makes me feel that the only thing I write is the title , The content is just a waste of time . In order to tear down next week can write a frame orm, I hope you guys can ...

  3. Do it yourself IOC frame ( 3、 ... and )

    The first day I wrote my blog, I had a lot of views 1000 More people , I was so inspired that I decided to stay up late and write another article . For the first two articles, it's just using dtd verification xml, And then parse xml, and IOC It's still a long way from the core , I believe many of my friends are not satisfied with it , this ...

  4. Do it yourself spring IOC Source code

    Preface : about spring IOC If you don't know the concept very well, you can read my last blog -- Easy to understand spring IOC( These two blogs are only published now due to my personal reasons , Shame! ). After understanding through this blog , I believe you will be right sp ...

  5. Open source written by Chinese people .net Ioc frame ——My.Ioc brief introduction

    My.Ioc It is an open source developed by the author IoC/DI frame , The download address is here . It has the following characteristics : Efficient In terms of means of realization ,My.Ioc By using generics . cache . Generate code dynamically . Delay registration . Try to use abstract classes instead of interfaces ...

  6. Do it yourself Spring frame --IOC、MVC

    For a Java Developer , I believe that no one does not know  Spring frame , And it's easy to say Spring Characteristics of -- IOC.MVC.AOP.ORM(batis). Now I'd like to briefly introduce my lightweight S ...

  7. Linux dts Device tree details ( Two ) Write the device tree dts

    Linux dts Device tree details ( One ) Basic knowledge of Linux dts Device tree details ( Two ) Write the device tree dts List of articles Preface Hardware structure Device tree dts file Preface After a brief understanding of the concept , We can start trying to write a ...

  8. OWIN Series of do it yourself middleware

    One . Preface 1. be based on OWIN Get rid of System.Web Bondage stands out , Lightweight + Cross platform , bring ASP.NET The application only needs to rely on this abstract interface , Don't worry about what's running Web The server . 2.OWIN.dll Introduce Using reverse editing ...

  9. IOC frame

    One . IOC The background of the theory We all know , In a software system designed with object-oriented method , Its underlying implementation is made up of N Made up of objects , All the objects work together , Finally realize the business logic of the system . chart 1: Coupled objects in a software system If we turn it on ...

Random recommendation

  1. iOS-Debug debugging

    Reprint :http://www.cnblogs.com/Leo_wl/p/4423922.html

  2. DP summary ——QPH

    Common optimizations A monotonous queue form dp[i]=min{f(k)} dp[i]=max{f(k)} requirement f(k) It's about k Function of k The scope and i of branch philosophy Maintain a monotonic increment ( reduce ) Queues , You can pop elements at both ends , One ...

  3. Answer readers' questions (8): relevant Java It's about learning

    Recently , I got an email from a graduate friend , The general contents are as follows : Japan ( My microblog :http://weibo.com/zhouzxi?topnav=1&wvr=5, Our chat number :245924426. huan ...

  4. @synthesize and @dynamic

    @synthesize Unless the developer has done , Otherwise, it will be generated automatically by the compiler getter/setter Method . When developers define save or fetch methods , Customization will block the automatic generation of this method . @dynamic Tell compiler , Do not automatically generate g ...

  5. vs2017 Development IOS(vs2017 xamarin Connect mac)

    These two days, I suddenly remember the soft Visual Studio 2017 It seems that it can be used C# Development IOS and Android application , So I tried the next generation process . Relative to IOS Come on ,Android The generation process of is relatively easy ...

  6. lumion Material system interior rendering 6.3

    The material system is for imported models , It doesn't work with the built-in model . Some of the built-in models can change properties . Click on “ texture of material ” Click on the wall , Come out of the material library . Give a material to the wall , Click save... When finished , You can save . Then add glass to the window . You can see the wall , ...

  7. centos Chinese virus

    Um. It's easy to get a virus ,,, And this is the second time .... Then the boss said let me   crontab -l  once Then I tried And then come out of this thing Under execution   crontab -r   This   And then crontab -l  Just ...

  8. javabean Why serialization is needed

    No matter what hibernate perhaps mybatis combination spring Development or something , In a system, persistent classes often need to be serialized , implements Serializable. I'm still curious , Why do this ? All I know is ...

  9. 【php】https request

    /** * Simulation submission parameters , Support https Submit It can be used for all kinds of api request * @param string $url : Address of submission * @param array $data :POST Array * @param ...

  10. Python - configParser Module learning

    configParser The module is used to manipulate the configuration file notes :Parser Chinese Translation “ analysis ” The meaning of . The format of the configuration file is similar to windows ini File similar , Can contain one or more sections (section), Each section can have multiple parameters ( key = ...