刚刚写了一篇类反射的笔记:一个相当详细的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--已被销毁
证明类反射应用成功了