一直听说反射机制非常强大,但是看了基本概念之后还是不知道如何使用,现在还没有学习Spring,所以了解不够深入,但是通过一个例子,稍微有些了解,以后再进行补充。
首先介绍反射机制,再举具体例子。
类对象概念
所有的类,都存在一个类对象,这个类对象用于提供类本身的信息,比如有几种构造方法,有多少属性,有哪些普通方法。
我们熟悉的对象之间的区别:
Person p1 = new Person(); p1.setAge(14);Person p2 = new Person(); p2.setAge(33);这两个都是Person对象,他们的区别下雨各种的属性(例如年龄)不同。
类之间的区别是:
Person和Item都是类,但是他们方法不同,属性不同。那么类对象就是用于描述这种类,都有什么属性,什么方法的。
获取类对象
三种方式:
1.Class.forName
2.Person.class
3.new Person().getClass()
在一个JVM中,一种类只会有一个类对象存在。通过第1,3种方式获取类对象,会导致静态属性被初始化,而且只会执行一次。
通过反射机制创建一个对象
//类对象
Class pClass = new Person().getClass();
//构造器对象
Constructor c = pClass.getConstructor();
//通过构造器实例化
Person p1 = (Person)c.newInstance();
p1.name = "fubin";
通过反射修改属性的值
//获取类Person的名字叫做name的字段
Field f1 = p1.getClass().getDeclaredField("name");
//修改此字段的值
f1.set(p1,"yulin");
System.out.print(p1.name);
pS: getField和getDeclaredField的区别:
二者都是用于获取字段。
getField只能获取public的,包括从父类继承来的字段。
getDeclaredField可以获取本类所有字段,包括private,但是不能获取继承来的字段。(只能获取private字段的值,不能访问,若要访问需使用setAccessible(true).
通过反射机制调用方法
Person p1 = new Person();
//获取名字较多setName,参数类型是String的方法
Method m = p1.getClass().getMethod("setName",String.class);
//对p1对象,调用这个方法
m.invoke(p1,"wang");
基本概念介绍完了发现,嗯还是不知道该怎么使用,那么下面简单举个Servlet的例子。假设某购物网站后台有一个分类管理部分,负责管理产品分类,有增加删除修改编辑查询5个功能,传统的Servlet方式是一个路径对应一个Servlet,则需要设计5个Servlet类,并一一在web.xml中配置:
AddCategoryServlet
DeleteCategoryServlet
EditCategoryServlet
UpdateCategoryServlet
ListCategoryServlet
而后台需要做分类,商品,属性,商品图片,用户,订单这6种管理,那么一共就需要30个Servlet.麻烦臃肿,不宜维护。
对此设计进行改进则只需要六个Servlet,即每个实体类对应一个Servlet,其内包含增加删除修改编辑查询5个功能函数。此处便是借助反射机制,根据传递过来的值假如是add,则调用对应categoryServlet中的方法add().
首先输入访问路径之后,使用过滤器Filter进行拦截,获取到需要的值例如是category 和add,那么我们知道应该跳转到分类中的增加功能。服务端应该跳转到CategoryServlet,并把add传递过取。
CategoryServlet中有add(),update() list() delete(),edit()等方法,其继承于BaseBackServlet类,其service方法会调用,在service中,借助反射技术,根据传递过来的值add调用其对应的方法add();这样就实现了当访问路径为admin_category_list的时候,调用categoryServlet.add()方法的效果。
//BaseBackServlet.java
/*借助反射调用对应方法*/
String method = (String)request.getAttribute("method");
Method m = this.getClass().getMethod(method,javax.servlet.http.HttpServletRequest.class,
javax.servlet.http.HttpServletResponse.class,Page.class);
String redirect = m.invoke(this,request,response,page).toString();
注释:取到从BackServletFilter中request.setAttribute()传递过来的值 add
根据这个值add,借助反射机制调用CategoryServlet类中的add()方法
这样就达到了CategoryServlet.add()方法被调用的效果
这样一个Servlet就能满足CRUD一系列业务要求。
//关于反射 https://www.sczyh30.com/posts/Java/java-reflection-1/