天天看點

Java類反射的應用

剛剛寫了一篇類反射的筆記:一個相當詳細的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--已被銷毀

證明類反射應用成功了