イントロスペクションのジャワの基礎
イントロスペクションとは何ですか
まず第一に、私たちは内省が何であるかを知っておく必要があります。それは、私自身の理解によるとされ、原則的にカプセル化されたJavaBeanを操作する方が便利反映
JavaBeanの特殊な形式のクラスの仕様は次のとおりです。
- JavaBeanクラスは、キーワードに公式声明クラスを使用して、パブリッククラスでなければなりません。
- JavaBeanクラスは、パブリックの引数なしのコンストラクタとして宣言する必要があります。
- JavaBeanクラスのインスタンス変数をプライベートでなければならない、つまり、すべてのインスタンス変数は、キーワードのプライベートを使用して宣言されています。
- 私たちは、JavaBeanのクラスインスタンス変数のパブリックgetter / setterメソッドを提供する必要があります。(getter / setterメソッドでは、データセキュリティ、正当性を確保するために、などいくつかのアクセス制御、データの検証を、行うことができます。)
命名規則のJavaBeanクラスのインスタンス属性:
- プロパティ名の前の2つの文字は小文字です:最初の文字は、その後のgetName /のsetNameのgetter / setterメソッドは、プロパティという名前の名前など一部/セットを取得、それはだgetter / setterメソッドとして使用されるプロパティ名を、大文字。
- ゲッター/セッターメソッドとして直接使用される属性名/取得後部、すなわち、同じ属性名のケースを設定します。第二の大文字は、属性名。uNameという名前のプロパティ、getuName / setuNameへのgetter / setterメソッドとして。
- プロパティ名2つの大文字の前に:属性名を直接getter / setterメソッドとして使用/設定後部、同じ属性名のケースを取得します。IDコードという名前のプロパティ、getIDcode / setIDcodeへのgetter / setterメソッドとして。
- プロパティ名は大文字:getter / setterメソッドの取得/設定後部として直接使用されるプロパティ名、その同じ属性名の場合。UCODEという名前のプロパティ、getUcode / setUcodeへのgetter / setterメソッドとして。しかし、この場合は、プロパティを見つけることができないアプリケーションでエラーが発生します。
イントロスペクションを使用する方法
内省主要なクラス(インタフェース)される:Introspector
(S)、 BeanInfo
(インタフェース)、PropertyDescriptor
(S)、java.beanパッケージ三あります。
Introspector
内省的な入り口は、取得するために使用されるユーティリティクラスでBeanInfo
のJavaBeanのある情報を。
テスト豆:学生
public class Student {
private String name;
private String address;
public Student() {
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", address='" + address + '\'' +
'}';
}
}
//static BeanInfo getBeanInfo(Class<?> beanClass):在 Java Bean 上进行内省,了解其所有属性、公开的方法和事件
BeanInfo beanInfo = Introspector.getBeanInfo(Student.class);
Beanにメッセージを取得した後、あなたは、ディスクリプタのすべての属性を取得することができます:
PropertyDescriptor[] p = beanInfo.getPropertyDescriptors();
トラバースは、それを印刷し、その結果を参照してください。
BeanInfo beanInfo = Introspector.getBeanInfo(Student.class);
PropertyDescriptor[] p = beanInfo.getPropertyDescriptors();
System.out.println(p.length);
for (PropertyDescriptor descriptor : p) {
System.out.println(descriptor);
}
//输出--------------
p.length = 3
java.beans.PropertyDescriptor[name=address; propertyType=class java.lang.String; readMethod=public java.lang.String nei_xing.Student.getAddress(); writeMethod=public void nei_xing.Student.setAddress(java.lang.String)]
//为了方便观察加了注释隔开
java.beans.PropertyDescriptor[name=class; propertyType=class java.lang.Class; readMethod=public final native java.lang.Class java.lang.Object.getClass()]
//
java.beans.PropertyDescriptor[name=name; propertyType=class java.lang.String; readMethod=public java.lang.String nei_xing.Student.getName(); writeMethod=public void nei_xing.Student.setName(java.lang.String)]
ここでは、学生の特性を2つだけが、3つのオブジェクト記述子、理由は次のとおりです。
すべてのクラスはObjectから継承するので、すべてのクラスははgetClass()メソッドを持っているので、オブジェクトは、Class型のオブジェクト自体のオブジェクトを取得するにはgetClass()メソッドを宣言します。イントロスペクションを使用している場合ではなく、クラスのクラスフィールド(キーワードクラス、クラス名ではない)ではなく、setClass()メソッドなので、一般的なプログラミング「クラス」をフィルタリングする必要がある属性の
リファレンス
溶液:
使用するgetBeanInfo(Class<?> beanClass)
オーバーロードされたメソッド:
static BeanInfo getBeanInfo(Class<?> beanClass, Class<?> stopClass)
:のBeanInfo得られるブレークポイント指定されたクラス、
例えば:
BeanInfo beanInfo1 = Introspector.getBeanInfo(Student.class, Object.class);
この場合には、その特性が2人のだけの学生を得ることができ、かつ除外記述子class
のプロパティを。
各属性記述子を取得した後、そのゲッター/セッターメソッドを取得して設定することができます。
Student stu = new Student();
BeanInfo beanInfo1 = Introspector.getBeanInfo(Student.class, Object.class);
PropertyDescriptor[] p1 = beanInfo1.getPropertyDescriptors();
System.out.println(p1.length);
for (PropertyDescriptor d : p1) {
String name = d.getName();
System.out.println("name = " + name);
Method getter = d.getReadMethod();//获取getter方法
Method setter = d.getWriteMethod();//获取setter方法
if ("name".equals(name)){
setter.invoke(stu, "张三");//使用反射调用该方法
}
if ("address".equals(name)){
setter.invoke(stu, "上海");
}
System.out.println(getter.invoke(stu));
}
出力:
2
name = address
上海
name = name
张三
上記のBeanInfoオブジェクトを除いて取得するプロパティ記述子も直接属性説明作成することができ、内省的な実装です。
PropertyDescriptor pd = new PropertyDescriptor("address", Student.class);
Method getter = pd.getReadMethod();
Method setter = pd.getWriteMethod();
イントロスペクションのデモに2つのサーブレットを置きます:
DEMO1
フロントページ:
<form action="/introspectorServlet" method="post">
姓名 <input type="text" name="name" /> <br/>
住址 <input type="text" name="address"/> <br/>
<input type="submit" value="提交"/>
</form>
IntrospectorServlet:
@WebServlet("/introspectorServlet")
public class IntrospectorServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//处理请求乱码
request.setCharacterEncoding("UTF-8");
//获取页面提交的所有的数据
/*
map集合的key是form表单标签的name属性值
map集合的value是浏览器输入框输入的值,以String类型的数组形式接收
举例:
住址 <input type="text" name="address"/> <br/>
key:address
value:{"上海"}
*/
Map<String, String[]> m = request.getParameterMap();
// System.out.println(m);
//创建封装属性的目标对象person
Person p = new Person();
try {
//调用方法
setProperty(p,m);
} catch (Exception e) {
e.printStackTrace();
}
System.out.println(p.getName());
System.out.println(p.getAddress());
}
private void setProperty(Object obj, Map<String, String[]> m) throws Exception {
// 将请求参数中 map的key 与传入对象属性名称 比较,如果一致,将参数的值赋值给对象属性
//使用内省类获取BeanInfo类的对象
BeanInfo beanInfo = Introspector.getBeanInfo(obj.getClass());
//获取所有的属性描述器
PropertyDescriptor[] propertyDescriptors = beanInfo.getPropertyDescriptors();
//遍历数组取出每一个属性描述器
for (PropertyDescriptor descriptor : propertyDescriptors) {
//获取Person类中的属性
String property_name = descriptor.getName();
//判断属性在map中是否存在对应值
if(m.containsKey(property_name)){
//包含
//获取对应的value值
String value = m.get(property_name)[0];
/*
Method getWriteMethod() 获得应该用于写入属性值的方法。
*/
Method setter = descriptor.getWriteMethod();
//将value 写到属性中
setter.invoke(obj, value);
}
}
}
}
使用してrequest.getParameterMap();
文字列をフロントから得られたデータをされ、その後、どのようにフィールド内のJavaBeanの基本的なタイプにイントロスペクションにデータをカプセル化するための技術を使用するには?
DEMO1
学生Beanクラス
public class Person {
private String name;
private String address;
private int age;
private double money;
public double getMoney() {
return money;
}
public void setMoney(double money) {
this.money = money;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", address='" + address + '\'' +
", age=" + age +
", money=" + money +
'}';
}
}
サーブレットのコード:
@WebServlet("/introspector2Servlet")
public class IntrospectorServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//处理中文乱码
request.setCharacterEncoding("UTF-8");
Person p = new Person();
//获取所有的数据
//key 标签 name属性值 value 输入的值
Map<String, String[]> map = request.getParameterMap();
try {
setProperty(p, map);
} catch (Exception e) {
e.printStackTrace();
}
System.out.println(p.getName());
System.out.println(p.getAddress());
System.out.println(p.getAge());
System.out.println(p.getMoney());
}
private void setProperty(Object obj, Map<String, String[]> map) throws Exception {
//内省
//获取所有的属性封装到BeanInfo对象中
BeanInfo beanInfo = Introspector.getBeanInfo(obj.getClass());
//获取所有的属性描述器
PropertyDescriptor[] propertyDescriptors = beanInfo.getPropertyDescriptors();
//遍历
for (PropertyDescriptor descriptor : propertyDescriptors) {
//获取属性名
String propertyName = descriptor.getName();
//判断集合中是否包含当前属性名
if (map.containsKey(propertyName)) {
//包含
//获取get方法
Method getterMethod = descriptor.getReadMethod();
//获取get方法返回值类型 String int double
String returnTypeName = getterMethod.getReturnType().getSimpleName();
//获取set方法
Method setterMethod = descriptor.getWriteMethod();
//获取mapvalue
String value = map.get(propertyName)[0];//"18"
//多分支语句
switch (returnTypeName) {
case "int":
int age = Integer.parseInt(value);
//执行set方法
setterMethod.invoke(obj, age);
break;
case "double":
double v = Double.parseDouble(value);
//执行set方法
setterMethod.invoke(obj, v);
break;
case "float":
float v1 = Float.parseFloat(value);
//执行set方法
setterMethod.invoke(obj, v1);
break;
case "long":
long v2 = Long.parseLong(value);
//执行set方法
setterMethod.invoke(obj, v2);
break;
case "boolean":
boolean v3 = Boolean.parseBoolean(value);
//执行set方法
setterMethod.invoke(obj, v3);
break;
default:
//执行set方法
setterMethod.invoke(obj, value);
break;
}
}
}
}
}
々BeanUtilsツール
あなたが直接あなたがApacheのツールを使用することができますほとんどの時間ので、いくつかの複雑ながあるイントロスペクションを参照することができますorg.apache.commons.beanutils.BeanUtils
、 (使用してインポートする必要性commons-beanutils-1.9.2.jar
とcommons-logging-1.1.1.jar
の2つのパッケージが)、この座標Mavenのです。
<dependency>
<groupId>commons-beanutils</groupId>
<artifactId>commons-beanutils</artifactId>
<version>1.9.3</version>
</dependency>
このツールクラスは移入()メソッドがありますstatic populate(Object bean, Map<String,String[]> properties)
、と文字列であるキーの地図とのJavaBeanがパッケージを完了するために一貫している(または、名前getter / setterメソッドが関連している属性名を、少なくとも春JdbcTemplateは、あります、)プロパティ名を変更したが、まだパッケージを完了することができますゲッター/セッターメソッドを変更しません。
その後、カプセル化は、コードの行を完了することができます。
BeanUtils.populate(new Student,request.getParameterMap());