Java 내성(Introspector) 깊이 있는 이해
13015 단어 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')는 데이터 형식이 일치하지 않아 속성에 값을 부여할 수 없습니다.읽어주셔서 감사합니다. 여러분에게 도움이 되었으면 좋겠습니다. 본 사이트에 대한 지지에 감사드립니다!
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
JPA + QueryDSL 계층형 댓글, 대댓글 구현(2)이번엔 전편에 이어서 계층형 댓글, 대댓글을 다시 리팩토링해볼 예정이다. 이전 게시글에서는 계층형 댓글, 대댓글을 구현은 되었지만 N+1 문제가 있었다. 이번에는 그 N+1 문제를 해결해 볼 것이다. 위의 로직은 이...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.