반성의 자바 기초
반성은 무엇입니까
우선, 우리는 반성이 무엇인지 알 필요가있다. 즉, 내 자신의 이해가에 따라 원칙적으로 캡슐화 반영 자바 빈즈를 운영하는 것이 더 편리
자바 빈즈는 특별한 형식의 클래스 사양입니다 :
- 자바 빈즈 클래스는 키워드에게 공문 클래스를 사용하여 공용 클래스해야합니다.
- 자바 빈즈 클래스는 공공 인수가없는 생성자로 선언해야합니다.
- 자바 빈즈 클래스 인스턴스 변수는 모든 인스턴스 변수는 private 키워드를 사용하여 선언, 즉, 개인해야합니다.
- 우리는 자바 빈즈 클래스의 인스턴스 변수에 대한 공공 게터 / 세터 메소드를 제공해야합니다. (게터 / 세터 메소드에서는, 데이터 보안을 보장하기 위해, 정당성 등 일부 액세스 제어, 데이터 유효성 검사를 할 수 있습니다.)
자바 빈즈 클래스의 인스턴스는 이름 지정 규칙 속성 :
- 속성 이름 앞에 두 글자는 소문자 : 첫 번째 편지는 다음 getName /에서는 setName에 대한 게터 / setter 메소드는 재산이라는 이름으로 부품 / 세트를 얻을, 그것의 게터 / 세터 메소드로 사용되는 속성 이름을 대문자로.
- 게터 / 세터 방법으로서 직접 사용될 속성 이름 / 얻을 후방, 즉, 동일한 속성 이름 케이스 세트 : 제 대문자 속성 이름. uName의 이름 속성, getuName / setuName과의 게터 / 세터 메소드로.
- 속성 이름이 대문자 전 : 속성 이름을 직접 게터 / 세터 방법으로 사용 설정 / 후면 부분, 같은 속성 이름 케이스를 얻을. IDCODE이라는 속성, getIDcode / setIDcode과의 게터 / 세터 메소드로.
- 프로퍼티 이름은 대문자 : 게터 / 세터 방법 얻을 설정 / 후방으로 직접 사용되는 속성 명, 동일한 속성 이름 케이스. UCODE이라는 속성, getUcode / setUcode과의 게터 / 세터 메소드로. 그러나이 경우는, 속성을 찾을 수 없습니다 응용 프로그램에서 오류가 발생합니다 .
자기 반성을 사용하는 방법
내성적 기본 클래스 (인터페이스)이다 : Introspector
(S) BeanInfo
(인터페이스), PropertyDescriptor
(S) java.bean 패키지 세있는.
Introspector
내성적 입구 획득하는 데 사용되는 유틸리티 클래스입니다 BeanInfo
자바 빈즈의 정보를.
시험 콩 : 학생
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);
빈 메시지를 취득 후에는 기술자의 모든 속성을 얻을 수 있습니다 :
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)]
여기에, 학생의 특성 만이 있지만, 세 개의 개체 설명, 이유는
개체 그래서 모든 클래스 getClass () 메소드가, 모든 클래스는 Object에서 상속하기 때문에, Class 형 개체 자체의 객체를 얻을 수 getClass () 메소드를 선언합니다. 자기 반성을 사용하지만 클래스가 아닌 클래스 필드 (키워드 클래스, 클래스 이름이 아닙니다)가 아니라 setClass () 메소드, 그래서 일반적으로 프로그래밍 "클래스"를 필터링 할 필요가 속성
참조
해결 방법 :
사용 getBeanInfo(Class<?> beanClass)
오버로드 방법 :
static BeanInfo getBeanInfo(Class<?> beanClass, Class<?> stopClass)
:의 BeanInfo 얻을 브레이크 포인트 지정된 클래스,
예 :
BeanInfo beanInfo1 = Introspector.getBeanInfo(Student.class, Object.class);
이 경우 그 속성은 기술자는 두 학생 및 필터링 얻을 수있는 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();
반성 데모에 두 개의 서블릿을 넣어 :
데모 1
프론트 페이지 :
<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();
문자열을 프론트 데스크에서 얻은 데이터를하고 있습니다, 그럼 어떻게 현장에서 자바 빈즈의 기본 유형에 성찰에 데이터를 캡슐화 기술을 사용 하는가?
데모 1
학생 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
: 당신은 대부분의 시간을 당신이 아파치 도구를 사용할 수 있도록 직접, 몇 가지 복잡한있다 성찰 볼 수있다 org.apache.commons.beanutils.BeanUtils
, (사용 가져올 필요 commons-beanutils-1.9.2.jar
하고 commons-logging-1.1.1.jar
두 개의 패키지) 받는다는 좌표 이것이다 :
<dependency>
<groupId>commons-beanutils</groupId>
<artifactId>commons-beanutils</artifactId>
<version>1.9.3</version>
</dependency>
이 도구 클래스는 채우기 () 메소드가 있습니다 static populate(Object bean, Map<String,String[]> properties)
에 String의 키의지도와 (자바 빈즈 패키지를 완료하기 위해 일치하는 속성 이름 또는 및 게터 / 세터 방법은 관련이 이름은, 적어도 스프링의 JdbcTemplate은이다 ) 속성 이름을 수정하지만 여전히 패키지를 완료 할 수 있습니다 게터 / 세터 메소드를 수정하지 않습니다
그런 다음 캡슐화는 코드의 라인을 완료 할 수 있습니다 :
BeanUtils.populate(new Student,request.getParameterMap());