剛剛寫了一篇類反射的筆記:一個相當詳細的Java類反射筆記 ,然後現在再來把他實作一下
首先設定一下類反射的應用場景,現在我有一個接口
public interface Inte {
public abstract void init();
public abstract void servlet();
public abstract void destroy();
}
然後我前面已經有了一個實作類了,現在不想修改源代碼就能使用另一個實作類(這是項目開發的一大原則:開閉原則,也就是對增加開放,對修改關閉,可以百度一下),假設實作類1如下
public class Impl_1 implements Inte{
@Override
public void init() {
System.out.println("servlet_1--準備服務");
}
@Override
public void servlet() {
System.out.println("servlet_1--開始服務");
}
@Override
public void destroy() {
System.out.println("servlet_1--已被銷毀");
}
}
現在我需要改為使用實作類2
public class Impl_2 implements Inte{
@Override
public void init() {
System.out.println("servlet_2--準備服務");
}
@Override
public void servlet() {
System.out.println("servlet_2--開始服務");
}
@Override
public void destroy() {
System.out.println("servlet_2--已被銷毀");
}
}
那麼,現在需要的工具就是:dom4j-1.61.jar(這個版本倒是差不多的)、一個xxx.xml文檔、web-app_2_5xsd限制文檔對xml文檔進行限制。
我把限制文檔web-app_2_5xsd也搬上來了,可以不用看的,更不需要自己開發,需要使用的就是下面這一小部分
<web-app xmlns="http://www.example.org/web-app_2_5"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.example.org/web-app_2_5 web-app_2_5.xsd"
version="2.5">
<?xml version="1.0" encoding="UTF-8"?>
<!--
模拟servlet2.5規範,如果開發人員需要在xml使用目前Schema限制,必須包括指定命名空間。
格式如下:
<web-app xmlns="http://www.example.org/web-app_2_5"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.example.org/web-app_2_5 web-app_2_5.xsd"
version="2.5">
-->
<xsd:schema xmlns="http://www.w3.org/2001/XMLSchema"
targetNamespace="http://www.example.org/web-app_2_5"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:tns="http://www.example.org/web-app_2_5"
elementFormDefault="qualified">
<xsd:element name="web-app">
<xsd:complexType>
<xsd:choice minOccurs="0" maxOccurs="unbounded">
<xsd:element name="servlet">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="servlet-name"></xsd:element>
<xsd:element name="servlet-class"></xsd:element>
</xsd:sequence>
</xsd:complexType>
</xsd:element>
<xsd:element name="servlet-mapping">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="servlet-name"></xsd:element>
<xsd:element name="url-pattern" maxOccurs="unbounded"></xsd:element>
</xsd:sequence>
</xsd:complexType>
</xsd:element>
<xsd:element name="welcome-file-list">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="welcome-file" maxOccurs="unbounded"></xsd:element>
</xsd:sequence>
</xsd:complexType>
</xsd:element>
</xsd:choice>
<xsd:attribute name="version" type="double" use="optional"></xsd:attribute>
</xsd:complexType>
</xsd:element>
</xsd:schema>
然後寫xml文檔,先将限制文檔擺上台,就是上面所講的那一小段代碼,然後按照限制寫
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://www.example.org/web-app_2_5" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.example.org/web-app_2_5 web-app_2_5.xsd"
version="2.5">
<!-- 實作類1的配置
<servlet>
<servlet-name>Impl_1</servlet-name>
<servlet-class>S00_web.xmlFoReflect.Impl_1</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>Impl_1</servlet-name>
<url-pattern>/impl_1</url-pattern>
</servlet-mapping>
-->
<!--
實作類2的配置
//隻需要修改xml文檔就可以使用另一個實作類而不需要修改代碼 -->
<servlet>
<servlet-name>Impl_2</servlet-name>
<servlet-class>S00_web.xmlFoReflect.Impl_2</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>Impl_2</servlet-name>
<url-pattern>/impl_2</url-pattern>
</servlet-mapping>
</web-app>
這就可以了,現在我們來測試一下
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;
import org.junit.Test;
public class TestReflex {
@Test
public void test1(){
try {
//1.建立解析器對象
SAXReader sReader = new SAXReader();
//2.使用解析器加載web.xml檔案得到document對象
Document doc = sReader.read("src/S00_web/xmlFoReflect/web.xml");
//3.擷取根元素節點
Element rootElement = doc.getRootElement();
//4.根據元素名稱擷取子元素節點
Element servletElement = rootElement.element("servlet");
//5.根據元素名稱擷取servlet-class的文本節點
String servletClass = servletElement.elementText("servlet-class");
//6.通過類全名擷取位元組碼檔案,類反射就在這裡
Class<?> clazz = Class.forName(servletClass);
//7.建立執行個體對象
Inte inte = (Inte) clazz.newInstance();
//8.調用執行個體對象裡面的方法
inte.init();
inte.servlet();
inte.destroy();
} catch (DocumentException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
}
OK,最後輸出的是
servlet_2--準備服務
servlet_2--開始服務
servlet_2--已被銷毀
證明類反射應用成功了