利用註解和反射將map轉化成bean

一、java註解

java註解相關的類放在 java.lang.annotation 包下,其主要內容包含4個元註解和其中兩個元註解的枚舉類值,相對比較簡單,從jdk問答即可瞭解

4個元註解:

Documented:指示某一類型的註釋將通過 javadoc 和類似的默認工具進行文檔化。應使用此類型來註釋這些類型的聲明:其註釋會影響由其客戶端註釋的元素的使用。如果類型聲明是用 Documented 來註釋的,則其註釋將成爲註釋元素的公共 API 的一部分。


Inherited:指示註釋類型被自動繼承。如果在註釋類型聲明中存在 Inherited 元註釋,並且用戶在某一類聲明中查詢該註釋類型,同時該類聲明中沒有此類型的註釋,則將在該類的超類中自動查詢該註釋類型。此過程會重複進行,直到找到此類型的註釋或到達了該類層次結構的頂層 (Object) 爲止。如果沒有超類具有該類型的註釋,則查詢將指示當前類沒有這樣的註釋。


注意,如果使用註釋類型註釋類以外的任何事物,此元註釋類型都是無效的。還要注意,此元註釋僅促成從超類繼承註釋;對已實現接口的註釋無效。 


Retention:指示註釋類型的註釋要保留多久。如果註釋類型聲明中不存在 Retention 註釋,則保留策略默認爲 RetentionPolicy.CLASS

只有元註釋類型直接用於註釋時,Target 元註釋纔有效。如果元註釋類型用作另一種註釋類型的成員,則無效。

RetentionPolicy.SOURCE ---------------------------------註解將被編譯器丟棄 

RetentionPolicy.CLASS -----------------------------------註解在class文件中可用,但會被VM丟棄 

RetentionPolicy.RUNTIME VM-------將在運行期也保留註釋,因此可以通過反射機制讀取註解的信息。 


Target: 指示註釋類型所適用的程序元素的種類。如果註釋類型聲明中不存在 Target 元註釋,則聲明的類型可以用在任一程序元素上。如果存在這樣的元註釋,則編譯器強制實施指定的使用限制

ElemenetType.CONSTRUCTOR----------------------------構造器聲明 

ElemenetType.FIELD --------------------------------------域聲明(包括 enum 實例) 

ElemenetType.LOCAL_VARIABLE------------------------- 局部變量聲明 

ElemenetType.METHOD ----------------------------------方法聲明 

ElemenetType.PACKAGE --------------------------------- 包聲明 

ElemenetType.PARAMETER ------------------------------參數聲明 

ElemenetType.TYPE--------------------------------------- 類,接口(包括註解類型)或enum聲明


二、註解例子 

該例子有3個文件:註解類Annotation_1、使用註解類UseAnnotation、解析註解類ParseAnnotation

package com.annotation;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Target({ElementType.TYPE, ElementType.METHOD, ElementType.CONSTRUCTOR, ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
public @interface Annotation_1 {

	String name();
	
	int id() default 0;
	
	Class gid();
	
}
package com.annotation;

import java.lang.reflect.Method;

@Annotation_1(name="useAnnotation", id=1, gid=Long.class)
public class UseAnnotation {

	@Annotation_1(name="a", gid=Integer.class)
	public int a;
	
	@Annotation_1(name="constractor_method", gid=Method.class)
	public UseAnnotation(){
		
	}
	
	@Annotation_1(name="getA", id=2, gid=Method.class)
	public int getA(){
		return this.a;
	}
	
	@Annotation_1(name="setA", id=2, gid=Method.class)
	public void setA(int a){
		this.a = a;
	}
}
package com.annotation;

import java.lang.annotation.Annotation;
import java.lang.reflect.AccessibleObject;
import java.lang.reflect.Field;
import java.lang.reflect.Method;

public class ParseAnnotation {

	/**
	 * 解析類的註解
	 * @throws ClassNotFoundException 
	 */
	public void parseClass() throws ClassNotFoundException{
//		Class clazz = Class.forName("com.annotation.UseAnnotation");
		Annotation[] as = UseAnnotation.class.getAnnotations();
		for(Annotation a: as){
			Annotation_1 a1 = (Annotation_1)a;
			System.out.println("CLASS: name=" + a1.name() + ", id=" + a1.id() + ", gid=" + a1.gid());
		}
	}
	
	/**
	 * 解析方法的註解
	 */
	public void parseMethod(){
		Method[] methods = UseAnnotation.class.getMethods();
		this.parse(methods);
	}
	
	/**
	 * 解析成員變量的註解 
	 */
	public void parseField(){
		Field[] fields = UseAnnotation.class.getFields();
		this.parse(fields);
	}
	
	private <T extends AccessibleObject> void parse(T[] ts){
		for(T t: ts){
			Annotation annotation = t.getAnnotation(Annotation_1.class);
			if(annotation == null){
				System.out.println(t.getClass().getName() + " do not have Annotation_1");
			}else{
				Annotation_1 a1 = (Annotation_1)annotation;
				System.out.println(t.getClass().getName() + ": name=" + a1.name() + 
						", id=" + a1.id() + ", gid=" + a1.gid());
			}
		}
	}
	
	public static void main(String[] args) throws ClassNotFoundException {
		ParseAnnotation pa = new ParseAnnotation();
		pa.parseClass();
		pa.parseMethod();
		pa.parseField();
	}
	
	
	
}


三、利用註解和反射將map轉化成bean

該例子使用註解和反射的技術將map類型轉化成對應的bean

主要包含4個類:註解類PojoAnnotation、bean類User、轉換工具類PojoMappingUtil、測試類PojoTest

package com.annotation.userdemo;

import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;

@Retention(RetentionPolicy.RUNTIME)
public @interface PojoAnnotation {
	String name();
}
package com.annotation.userdemo;

public class User {

	@PojoAnnotation(name="NAME")
	private String name;
	
	@PojoAnnotation(name="AGE")
	private Integer age;
	
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public Integer getAge() {
		return age;
	}
	public void setAge(Integer age) {
		this.age = age;
	}
	@Override
	public String toString() {
		return "User [name=" + name + ", age=" + age + "]";
	}
	
	
}
package com.annotation.userdemo;

import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Map;

public class PojoMappingUtil {

	/**
	 * 將map中key與註解一致的值放到對應成員變量中
	 */
	public static <T> T parsePoje(Map<String, Object> map, Class<T> clazz) throws InstantiationException, IllegalAccessException, NoSuchMethodException, SecurityException, IllegalArgumentException, InvocationTargetException{
		T t = clazz.newInstance();
		Field[] fields = clazz.getDeclaredFields();
		for(Field field : fields){
			PojoAnnotation pojoAnnotation = field.getAnnotation(PojoAnnotation.class);
			if(pojoAnnotation != null){
				Object o = map.get(pojoAnnotation.name());
				if(o != null){
					String fieldName = field.getName();
					Method method = clazz.getMethod("set" + fieldName.substring(0, 1).toUpperCase() + fieldName.substring(1), o.getClass());
					method.invoke(t, o);
				}
			}
		}
		return t;
	}
	
}
package com.annotation.userdemo;

import java.lang.reflect.InvocationTargetException;
import java.util.HashMap;
import java.util.Map;

public class PojoTest {

	public static void main(String[] args) throws InstantiationException, IllegalAccessException, NoSuchMethodException, SecurityException, IllegalArgumentException, InvocationTargetException {
		
		Map<String, Object> map = new HashMap<String , Object>();
		map.put("NAME", "小明");
		map.put("AGE", 10);
		User user = PojoMappingUtil.parsePoje(map, User.class);
		System.out.println(user);
		
	}

}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章