Java 내성(Introspector) 깊이 있는 이해

13015 단어 Java내성Introspector
Java 내성(Introspector) 깊이 있는 이해
몇 가지 개념:
인트로스펙터(Introspector)는 자바 언어가 자바빈 클래스의 속성, 이벤트에 대한 부족한 처리 방법이다.
JavaBean은 특수한 종류로 주로 데이터 정보를 전달하는데 이 종류의 방법은 주로 개인 필드에 접근하는 데 사용되고 방법 이름은 특정한 명명 규칙에 부합된다.두 모듈 간에 정보를 전달하는 경우 값(Value Object) 또는 VO(Value Object)라고 하는 JavaBean에 정보를 봉인할 수 있습니다.방법이 비교적 적다.이 정보는 클래스의 개인 변수에 저장되며, set (), get () 를 통해 얻을 수 있습니다.
예를 들어 클래스 UserInfo:

package com.peidasoft.Introspector;

public class UserInfo {
  
  private long userId;
  private String userName;
  private int age;
  private String emailAddress;
  
  public long getUserId() {
    return userId;
  }
  public void setUserId(long userId) {
    this.userId = userId;
  }
  public String getUserName() {
    return userName;
  }
  public void setUserName(String userName) {
    this.userName = userName;
  }
  public int getAge() {
    return age;
  }
  public void setAge(int age) {
    this.age = age;
  }
  public String getEmailAddress() {
    return emailAddress;
  }
  public void setEmailAddress(String emailAddress) {
    this.emailAddress = emailAddress;
  }
  
}

클래스 User Info에 속성 userName이 있습니다. getUserName, setUserName을 통해 값을 얻거나 새 값을 설정할 수 있습니다.getUserName/setUserName을 통해 userName 속성에 접근하는 것이 기본 규칙입니다.Java JDK에는 어떤 속성에 접근하는 데 사용할 API를 제공하는 getter/setter 방법이 있습니다. 이것이 바로 내성입니다.
JDK 기본 라이브러리:
PropertyDescriptor 클래스:
PropertyDescriptor 클래스는 JavaBean 클래스가 스토리지를 통해 속성을 내보냅니다.주요 방법:
      1. getPropertyType(), 속성의 Class 객체 얻기;
      2. getReadMethod(), 속성 값을 읽는 방법 얻기;getWriteMethod(), 속성 값을 쓰는 방법 얻기;
      3. hashCode(), 대상의 해시 값 얻기;
      4. setReadMethod(Method readMethod), 속성 값을 읽는 방법을 설정합니다.
      5. setWriteMethod(Method writeMethod), 속성 값을 쓰는 방법을 설정합니다.
인스턴스 코드는 다음과 같습니다.

package com.peidasoft.Introspector;

import java.beans.BeanInfo;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.lang.reflect.Method;

public class BeanInfoUtil { 
 
  public static void setProperty(UserInfo userInfo,String userName)throws Exception{
    PropertyDescriptor propDesc=new PropertyDescriptor(userName,UserInfo.class);
    Method methodSetUserName=propDesc.getWriteMethod();
    methodSetUserName.invoke(userInfo, "wong");
    System.out.println("set userName:"+userInfo.getUserName());
  }
 
  public static void getProperty(UserInfo userInfo,String userName)throws Exception{
    PropertyDescriptor proDescriptor =new PropertyDescriptor(userName,UserInfo.class);
    Method methodGetUserName=proDescriptor.getReadMethod();
    Object objUserName=methodGetUserName.invoke(userInfo);
    System.out.println("get userName:"+objUserName.toString());
  }
} 

Introspector 클래스:
JavaBean의 속성을 패키지하여 작업합니다.프로그램에서 하나의 종류를 자바빈으로 간주하면 인트로스펙터를 호출하는 것이다.getBeanInfo() 방법으로 얻은 BeanInfo 대상은 이 종류를 자바빈으로 간주한 결과 정보, 즉 속성의 정보를 봉인했다.
getPropertyDescriptors (), 속성에 대한 설명을 얻을 수 있으며, BeanInfo를 훑어보는 방법으로 클래스의 속성을 찾고 설정할 수 있습니다.구체적인 코드는 다음과 같습니다.

package com.peidasoft.Introspector;

import java.beans.BeanInfo;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.lang.reflect.Method;


public class BeanInfoUtil {
    
  public static void setPropertyByIntrospector(UserInfo userInfo,String userName)throws Exception{
    BeanInfo beanInfo=Introspector.getBeanInfo(UserInfo.class);
    PropertyDescriptor[] proDescrtptors=beanInfo.getPropertyDescriptors();
    if(proDescrtptors!=null&&proDescrtptors.length>0){
      for(PropertyDescriptor propDesc:proDescrtptors){
        if(propDesc.getName().equals(userName)){
          Method methodSetUserName=propDesc.getWriteMethod();
          methodSetUserName.invoke(userInfo, "alan");
          System.out.println("set userName:"+userInfo.getUserName());
          break;
        }
      }
    }
  }
  
  public static void getPropertyByIntrospector(UserInfo userInfo,String userName)throws Exception{
    BeanInfo beanInfo=Introspector.getBeanInfo(UserInfo.class);
    PropertyDescriptor[] proDescrtptors=beanInfo.getPropertyDescriptors();
    if(proDescrtptors!=null&&proDescrtptors.length>0){
      for(PropertyDescriptor propDesc:proDescrtptors){
        if(propDesc.getName().equals(userName)){
          Method methodGetUserName=propDesc.getReadMethod();
          Object objUserName=methodGetUserName.invoke(userInfo);
          System.out.println("get userName:"+objUserName.toString());
          break;
        }
      }
    }
  }
  
}

이 두 종류의 비교를 통해 알 수 있듯이 모두PropertyDescriptor를 받아야 하는데 방식이 다르다. 전자는 창설 대상을 통해 직접 얻고 후자는 두루 겪어야 하기 때문에PropertyDescriptor 클래스를 사용하는 것이 더욱 편리하다.
인스턴스 사용:

package com.peidasoft.Introspector;

public class BeanInfoTest {

  /**
   * @param args
   */
  public static void main(String[] args) {
    UserInfo userInfo=new UserInfo();
    userInfo.setUserName("peida");
    try {
      BeanInfoUtil.getProperty(userInfo, "userName");
      
      BeanInfoUtil.setProperty(userInfo, "userName");
      
      BeanInfoUtil.getProperty(userInfo, "userName");
      
      BeanInfoUtil.setPropertyByIntrospector(userInfo, "userName");      
      
      BeanInfoUtil.getPropertyByIntrospector(userInfo, "userName");
      
      BeanInfoUtil.setProperty(userInfo, "age");
      
    } catch (Exception e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
    }

  }

}

출력:

get userName:peida
set userName:wong
get userName:wong
set userName:alan
get userName:alan
java.lang.IllegalArgumentException: argument type mismatch
  at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
  at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
  at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
  at java.lang.reflect.Method.invoke(Method.java:597)
  at com.peidasoft.Introspector.BeanInfoUtil.setProperty(BeanInfoUtil.java:14)
  at com.peidasoft.Introspector.BeanInfoTest.main(BeanInfoTest.java:22) 
설명: BeanInfoUtil.setProperty(userInfo, "age");오류는 age 속성이 int 데이터 형식이고 setProperty 방법에서 기본적으로age 속성에 부여된 값은 String 형식입니다.따라서argument typemismatch 매개 변수 형식이 일치하지 않는 오류가 발생합니다.
BeanUtils 키트:
위에서 보듯이 내성 조작이 매우 번거롭기 때문에 아파치는 간단하고 사용하기 쉬운 API로 Bean의 속성인 BeanUtils 도구 패키지를 개발했다.
BeanUtils 키트: 다운로드:http://commons.apache.org/beanutils/주의: 응용할 때 logging 패키지가 하나 더 필요합니다.http://commons.apache.org/logging/
BeanUtils 키트를 사용하여 위의 테스트 코드를 완료합니다.

package com.peidasoft.Beanutil;

import java.lang.reflect.InvocationTargetException;

import org.apache.commons.beanutils.BeanUtils;
import org.apache.commons.beanutils.PropertyUtils;

import com.peidasoft.Introspector.UserInfo;

public class BeanUtilTest {
  public static void main(String[] args) {
    UserInfo userInfo=new UserInfo();
     try {
      BeanUtils.setProperty(userInfo, "userName", "peida");
      
      System.out.println("set userName:"+userInfo.getUserName());
      
      System.out.println("get userName:"+BeanUtils.getProperty(userInfo, "userName"));
      
      BeanUtils.setProperty(userInfo, "age", 18);
      System.out.println("set age:"+userInfo.getAge());
      
      System.out.println("get age:"+BeanUtils.getProperty(userInfo, "age"));
       
      System.out.println("get userName type:"+BeanUtils.getProperty(userInfo, "userName").getClass().getName());
      System.out.println("get age type:"+BeanUtils.getProperty(userInfo, "age").getClass().getName());
      
      PropertyUtils.setProperty(userInfo, "age", 8);
      System.out.println(PropertyUtils.getProperty(userInfo, "age"));
      
      System.out.println(PropertyUtils.getProperty(userInfo, "age").getClass().getName());
         
      PropertyUtils.setProperty(userInfo, "age", "8");  
    } 
     catch (IllegalAccessException e) {
      e.printStackTrace();
    } 
     catch (InvocationTargetException e) {
      e.printStackTrace();
    }
    catch (NoSuchMethodException e) {
      e.printStackTrace();
    }
  }
}

실행 결과:

set userName:peida
get userName:peida
set age:18
get age:18
get userName type:java.lang.String
get age type:java.lang.String
8
java.lang.Integer
Exception in thread "main" java.lang.IllegalArgumentException: Cannot invoke com.peidasoft.Introspector.UserInfo.setAge 
on bean class 'class com.peidasoft.Introspector.UserInfo' - argument type mismatch - had objects of type "java.lang.String" 
but expected signature "int"
  at org.apache.commons.beanutils.PropertyUtilsBean.invokeMethod(PropertyUtilsBean.java:2235)
  at org.apache.commons.beanutils.PropertyUtilsBean.setSimpleProperty(PropertyUtilsBean.java:2151)
  at org.apache.commons.beanutils.PropertyUtilsBean.setNestedProperty(PropertyUtilsBean.java:1957)
  at org.apache.commons.beanutils.PropertyUtilsBean.setProperty(PropertyUtilsBean.java:2064)
  at org.apache.commons.beanutils.PropertyUtils.setProperty(PropertyUtils.java:858)
  at com.peidasoft.orm.Beanutil.BeanUtilTest.main(BeanUtilTest.java:38)
Caused by: java.lang.IllegalArgumentException: argument type mismatch
  at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
  at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
  at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
  at java.lang.reflect.Method.invoke(Method.java:597)
  at org.apache.commons.beanutils.PropertyUtilsBean.invokeMethod(PropertyUtilsBean.java:2170)
  ... 5 more
설명:
  1.속성의 값을 얻습니다(예: BeanUtils).getProperty(userInfo, "userName"), 문자열 반환
  2.속성의 값을 설정합니다(예: BeanUtils).setProperty(userInfo, "age", 8), 매개 변수는 문자열이나 기본 형식의 자동 포장입니다.속성을 설정하는 값은 문자열이고 얻은 값도 문자열이며 기본 형식이 아닙니다.   3.BeanUtils의 특징:
    1). 기본 데이터 형식의 속성에 대한 조작: WEB 개발, 사용에서 입력과 표시를 할 때 값은 문자열로 변환되지만 기본 연산은 기본 형식을 사용하며 이 형식의 동작은 BeanUtils가 자동으로 완성합니다.
    2). 인용 데이터 형식의 속성에 대한 조작: 우선 클래스에 대상이 있어야 하고null이 될 수 없습니다. 예를 들어private Datebirthday=new Date();동작은 전체 대상이 아니라 대상의 속성입니다. 예를 들어 BeanUtils.setProperty(userInfo,"birthday.time",111111);   

package com.peidasoft.Introspector;
import java.util.Date;

public class UserInfo {

  private Date birthday = new Date();
  
  public void setBirthday(Date birthday) {
    this.birthday = birthday;
  }
  public Date getBirthday() {
    return birthday;
  }   
}


package com.peidasoft.Beanutil;

import java.lang.reflect.InvocationTargetException;
import org.apache.commons.beanutils.BeanUtils;
import com.peidasoft.Introspector.UserInfo;

public class BeanUtilTest {
  public static void main(String[] args) {
    UserInfo userInfo=new UserInfo();
     try {
      BeanUtils.setProperty(userInfo, "birthday.time","111111"); 
      Object obj = BeanUtils.getProperty(userInfo, "birthday.time"); 
      System.out.println(obj);     
    } 
     catch (IllegalAccessException e) {
      e.printStackTrace();
    } 
     catch (InvocationTargetException e) {
      e.printStackTrace();
    }
    catch (NoSuchMethodException e) {
      e.printStackTrace();
    }
  }
}

  3.Property Utils 클래스와 Bean Utils는 달리 getProperty, setProperty 작업을 실행할 때 형식 변환이 없고 속성의 기존 형식이나 포장 클래스를 사용합니다.age 속성의 데이터 형식은 int이기 때문에 방법PropertyUtils.setProperty(userInfo,'age','8')는 데이터 형식이 일치하지 않아 속성에 값을 부여할 수 없습니다.
읽어주셔서 감사합니다. 여러분에게 도움이 되었으면 좋겠습니다. 본 사이트에 대한 지지에 감사드립니다!

좋은 웹페이지 즐겨찾기