大家來學javaBean
javaBean是什麼?
javabean和java Applet相似,是一個非常簡單的遵循某種嚴格協議的java類。編寫javabean就是編寫一個java的類,所以只要會寫類就能編寫一個bean,這個類創建的一個對象稱作一個bean。爲了能讓使用這個bean的應用程序構建工具(如:JSP引擎)知道這個bean的屬性和方法,javabean是有一定上位固定寫法的java類,只需要在類的方法命名上遵守一下規則,這個java類就是一個javabean。
1.如果類的成員變量的名字是xxx,那麼爲了更改或獲取成員變量的值,即更改或獲取屬性,在類中可以使用兩個方法:
getXxx(),用來獲取屬性xxx。
setXxx(),用來修改屬性xxx.。
2. 對於boolean類型的成員變量,即布爾邏輯類型的屬性,允
許使用"is"代替上面的"get"。
3. 類中訪問屬性的方法都必須是public的,屬性一般是private的。
4. 類中如果有構造方法,那麼這個構造方法也是public的並且是無參數的。
提到javabean就不得不說一下內省了
內省(introSpector)是java語言對javabean類屬性、事件的一種缺省(默認)的處理方法。
例如:類A中有屬性name,那麼我們就可以通過getName,setName來得到其值或者設置新的值。通過getName/setName來訪問name屬性,這就是默認的原則。
java中提供了一套API用來訪問某個屬性的getter/setter方法,通過這些API可以使你不需要了解這個規則,這些API存放於包java.beans中。
查看API發現java.beans存在於java.lang包下,屬於默認導入的。
javabean就是一種規範,當一個類滿足這個規範,這個類就能被其他特定的類調用。一個類被當做javabean使用時,JavaBean的屬性是根據方法名推斷出來的,因爲他的屬性全部是私有的外界是無法看到的。去掉set前綴,然後取剩下部分,如果剩下部分的第二個字母是小寫的,則把剩餘部分的首字母改成小寫。
這個過程與spring的設置注入正好相反的,依賴注入是根據一個屬性拼寫相應的get方法。
說到內省,當然也要談一下反射了。
JAVA反射機制是通過解析類的內部結構,獲得這個類的所有屬性和方法,並且可以操作這些屬性和調用這些方法。反射技術除了可以使我們開發通用的功能外,還可以讓程序在運行時動態的加載並使用最開始不存在的新類。
Java內省是假定一個類符合JavaBean的規範, 使用反射技術解析Java類,把類中的字段和該字段的setter/getter方法關聯起來.Java內省主要用來方便的把數據封裝到對象中。
下面通過一個小例子來對比一下反射與內省。
現在得到了一個存儲了數據的Map對象,把這個Map對象中的數據封裝成Student對象
三種方式
1.直接調用Student對象的相應的setter方法
2.使用反射技術
3.使用內省技術
package com.shc.javabean2;
publicclass Student {
private Stringid;
private Stringname;
privateintage;
public StringgetId() {
returnid;
}
publicvoid setId(String id) {
this.id= id;
}
public StringgetName() {
returnname;
}
publicvoid setName(String name) {
this.name = name;
}
publicint getAge() {
returnage;
}
publicvoid setAge(intage) {
if (age < 0) {
age = 0;
}
this.age = age;
}
}
////////////////////////////////////////////////////////////////////////
package com.shc.javabean2;
import java.beans.BeanInfo;
import java.beans.Introspector;
importjava.beans.PropertyDescriptor;
import java.lang.reflect.Field;
importjava.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;
//測試反射與內省
//封裝數據到Student對象中
public class Test {
public static void main(String[] args) throws Exception {
Map<String, Object> map = new HashMap<String,Object>();
map.put("id", "110");
map.put("name", "海超");
map.put("age", 18);
// 創建對象
Student student = new Student();
//1.直接創建方式
System.out.println("(直接方式)封裝數據之前:" + student);
packagingStudent(student, map);
System.out.println("(直接方式)封裝數據之後:" + student);
//2.使用反射把數據封裝到對象中
Student student1 = new Student();
System.out.println("(反射方式)封裝數據之前:" + student1);
packagingObject(student1, map);
System.out.println("(反射方式)封裝數據之後:" + student1);
//3.使用內省方式把數據封裝到對象中
Student student2 = new Student();
System.out.println("(內省方式)封裝數據之前:" + student2);
packagingObjectUseIntrospector(student2, map);
System.out.println("(內省方式)封裝數據之後:" + student2);
}
//1.直接方式封裝數據到對象中
public static void packagingStudent(Student student,Map<String, Object> map) {
student.setId((String) map.get("id"));
student.setName((String) map.get("name"));
student.setAge((Integer) map.get("age"));
}
//2.使用反射把數據封裝到對象中
public static void packagingObject(Object obj,Map<String, Object> map)
throws Exception {
Class<? extends Object> clazz = obj.getClass();
Field[] fields = clazz.getDeclaredFields();
for (Field field : fields) {
String fieldName = field.getName();
// 間接得到setter方法的參數的類型
Class<?> paramType = field.getType();
String methodName = "set" + fieldName.substring(0,1).toUpperCase()
+ fieldName.substring(1);
Method setMethod = clazz.getDeclaredMethod(methodName,paramType);
setMethod.invoke(obj, map.get(fieldName));
}
}
//3.使用內省封裝數據到對象中
public static void packagingObjectUseIntrospector(Object obj,
Map<String, Object> map) throws Exception{
/*BeanInfo是一個符合JavaBean規範的Java類的描述信息,
可以通過BeanInfo的對象獲得所有的字段的描述器PropertyDescriptor
(即包含字段信息和該字段的setter/getter方法)*/
BeanInfo beanInfo = Introspector.getBeanInfo(obj.getClass());
/*BeanInfo的對象通過:
BeanInfo beanInfo = Introspector.getBeanInfo(clazz);
方式獲得*/
// 獲得所有字段的屬性描述器
PropertyDescriptor[] propertyDescriptors = beanInfo
.getPropertyDescriptors();
for (PropertyDescriptor propertyDescriptor : propertyDescriptors){
// 獲得屬性的名稱,用來從map對象中取得屬性值的
String fieldName = propertyDescriptor.getName();
// 獲得set方法
Method setMethod = propertyDescriptor.getWriteMethod();
if (setMethod != null) {
//Java內省依賴JavaBean設計思想和Java反射
setMethod.invoke(obj, map.get(fieldName));
}
}
}
}
總結:
我們平時做的項目比較小,都是直接用javabean調用set/get方法,這時候用不上內省與反射。
反射和內省大多時候是在框架中體現的,我們一般用的是面向對象編程的,即:我們寫的代碼都能找到對應的類或者接口,找到具體的方法寫出對應的代碼。但是在面向抽象編程的時候,即:我們所寫的代碼完全抽象,如:我們寫的框架所要面向的類或方法目前並沒有,而是以後別人用我們的框架寫出來的類。但是我們又怎麼去調用她們的類的set/get方法呢?這個時候就要用到反射和內省進行抽象編程。