JavaのPropertyDescriptorをアプリケーションとソースコード解析

JavaのPropertyDescriptorをアプリケーションとソースコード解析

1.概要

PropertyDescriptorは、導出方法の一対(ゲッター/セッター)によって、メモリのJava Beanプロパティを記述する。我々は、Beanプロパティの動作を読み書きすることができ、それによってゲッター/セッターを提供することができるのPropertyDescriptor。

2.キーインターフェイスと内部属性

public PropertyDescriptor(String name, Class<?> beanClass) throws IntrospectionException  
public PropertyDescriptor(String name, Class<?> beanClass, String getMethodName, String setMethodName) throws IntrospectionException public PropertyDescriptor(String name, Method readMethod, Method writeMethod) throws IntrospectionException public Class<?> getPropertyType() public Method getReadMethod() public Method getWriteMethod() public void setReadMethod(Method readMethod) throws IntrospectionException public void setWriteMethod(Method writeMethod) public boolean equals(Object o) 

次のようにPropertyDescriptorを関連する内部属性は次のとおりです。 
クラスのプロパティタイプ; //プロパティの種類<?> 
メソッド、getMethod; //ゲッター 
メソッド、のsetMethod; //セッター 
も親クラスFeatureDescriptor関数から継承されたプロパティのプログラムの名前を指定するために使用されます

3.簡単なアプリケーション

前Personクラスは次のよう:

package com.cwind.property;  

public class Person { private String name ; private int age ; public Person(){ this.name = ""; this.age = 0; } public Person(String name, int age) { super(); this.name = name; this. age = age; } public String getName() { return name; } public void setName(String name) { this. name = name; } public int getAge() { return age; } public void setAge(int age) { this. age = age; } public String getNameInUpperCase(){ return this .name .toUpperCase(); } public void setNameToLowerCase(String name){ this.name = name.toLowerCase(); } } 

小文字のsetメソッドに標準ゲッターとセッターの名前と年齢二つの特性に加えて、このクラスだけでなく、getメソッドの名前に増資と名前を取得します。 
テストクラスでは、この方法は、最初の2つのオブジェクトを取得します。

Class personClass = Class.forName("com.cwind.property.Person");  
Method read = personClass.getMethod("getNameInUpperCase", null);  
Method write = personClass.getMethod("setNameToLowerCase", String.class );  //然后可以通过两种方式构造PropertyDescriptor PropertyDescriptor prop1 = new PropertyDescriptor( "name", Person.class );  //使用其标准getter和setter PropertyDescriptor prop2 = new PropertyDescriptor( "name", read, write);  //使用read和write两个方法对象所自定义的getter和setter  //下面构建一个Person对象 Person person = new Person("Kobe" , 36); System. out.println(prop1.getReadMethod().invoke(person, null));  // --实际调用Person.getName(), result: Kobe System. out.println(prop2.getReadMethod().invoke(person, null));  // --实际调用Person.getNameInUpperCase(), result: KOBE prop1.getWriteMethod().invoke(person, "James");  // --实际调用Person.setName(), person.name被设置为James prop2.getWriteMethod().invoke(person, "James");  // --实际调用Person.setNameToLowerCase(), person.name被设置为james 

4.ソースコード解析

コンストラクタ1:

public PropertyDescriptor(String name, Class<?> beanClass)  
        throws IntrospectionException {  
        setName(name);     //设置属性编程名,本例中即'name'  
        if (name.length() == 0){ throw new IntrospectionException("empty property name"); // 编程名为空则抛出异常 } String caps = Character.toUpperCase(name.charAt(0)) + name.substring(1); // 标准getter应为getName()或isName(), 先将首字母大写 findMethods(beanClass, "is" + caps, "get" + caps, "set" + caps); // 参数依次为:类类型,可能的getter函数名1,可能的getter函数名2,setter函数名 if (getMethod == null){ // findMethods()设置PropertyDescriptor的getMethod和setMethod属性 throw new IntrospectionException( "Cannot find a is" + caps + " or get" + caps + " method"); } if (setMethod == null){ throw new IntrospectionException( "Cannot find a " + caps + " method" ); } propertyType = checkMethods(getMethod, setMethod); // checkMethods()函数用来检测getMethod得到的类型与setMethod的参数类型是否匹配,若匹配则置propertyType为该类型 } 

コンストラクタ2: 
公共のPropertyDescriptor(文字列名、クラス

private void findMethods(Class beanClass, String getMethodName1, String getMethodName2, String setMethodName) throws IntrospectionException { try { // 首先查找getMethodName1指定的getter (isXXX) if (getMethodName1 != null) { try { getMethod = beanClass.getMethod(getMethodName1, new Class[0]); } catch (NoSuchMethodException e) {} } // 若失败,则查找getMethodName2指定的getter (getXXX) if (getMethod == null && getMethodName2 != null) { try { getMethod = beanClass.getMethod(getMethodName2, new Class[0]); } catch (NoSuchMethodException e) {} } if (setMethodName != null) { if (getMethod != null) { // 如果得到了getMethod,则通过其返回值类型决定setMethod的参数类型 Class propertyType = getMethod.getReturnType(); if (propertyType == Void.TYPE) { // 若getter的返回值为Void类型则抛出异常 String msg = "The property's read method has return type 'void'"; throw new IntrospectionException(msg); } Class[] setArgs = new Class[] { propertyType }; try { setMethod = beanClass.getMethod(setMethodName, setArgs); // 通过函数名和参数类型获得setMethod } catch (NoSuchMethodException e) {} } else if (getMethodName1 == null && getMethodName2 == null) { // getMethodName1和2均为空,则此属性为只写属性,此时遍历bean中的函数,返回第一个名称与setMethodName一致且返回类型为Void的单参数函数 Method[] methods = beanClass.getMethods(); for (int i = 0; i < methods.length; i++) { if (methods[i].getName().equals(setMethodName) && methods[i].getParameterTypes().length == 1 && methods[i].getReturnType() == Void.TYPE) { setMethod = methods[i]; break; } } } } } catch (SecurityException e) { String msg = "SecurityException thrown on attempt to access methods."; // 作者在纠结要不要修改异常类型 throw new IntrospectionException(msg); } } 

checkMethods方法

private Class<?> checkMethods(Method readMethod, Method writeMethod) throws IntrospectionException {  
        Class<?> newPropertyType = propertyType;  
         // 合法的read方法应该无参同时带有一个非空的返回值类型  
        if (readMethod != null) { if (readMethod.getParameterTypes().length > 0) { throw new IntrospectionException("read method has unexpected parameters"); } newPropertyType = readMethod.getReturnType(); if (newPropertyType == Void.TYPE) { throw new IntrospectionException("read method return type is void"); } } // 合法的write方法应该包含一个类型相同的参数 if (writeMethod != null) { if (writeMethod.getParameterTypes().length != 1) { // 参数不能超过一个 String msg = "write method does not have exactly one parameter" ; throw new IntrospectionException(msg); } if (readMethod == null) { // 若无read方法,属性类型就应为writeMethod的参数类型 newPropertyType = writeMethod.getParameterTypes()[0]; } else { // 检查read方法的返回值类型是否与write方法的参数类型相匹配 if (newPropertyType != null && !newPropertyType.isAssignableFrom( writeMethod.getParameterTypes()[0])) { throw new IntrospectionException("read and write method are not compatible"); } } } return newPropertyType; } 

同じ2つのPropertyDescriptor場合、最後に述べた1 PropertyDescriptor.equals()のみ属性タイプ、フラグ、リードおよび方法のPropertyEditorClassを書き込みは等しいと見なされ

return samePropertyType  
                && sameFlags  
                && sameReadMethod  
                && sameWriteMethod  
                && samePropertyEditorClass;  

:より転載http://cwind.iteye.com/blog/2028208?utm_source=tuicool 

参考:http://blog.csdn.net/z69183787/article/details/8443777

おすすめ

転載: www.cnblogs.com/lqh969696/p/11136479.html