1. 程式人生 > >【Annotation】使用自定義註解實現依賴注入

【Annotation】使用自定義註解實現依賴注入

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

/**
 * 演示類
 * @author student
 */
public class Demo {
	// 物件字串陣列
	private static String[] classNames = { "test_accocation.UserUI", "test_accocation.UserDaoImpl" };
	// 用於儲存字串解析的物件
	private static Map map = new HashMap<>();

	public static void main(String[] args) throws Exception {
		init();
		UserUI ui = (UserUI)getBean("ui");
		ui.login();
	}

	/**
	 * 初始化函式 用於將根據字串建立的物件解析後放入Map中
	 * 
	 * @throws Exception
	 */
	private static void init() throws Exception {
		// 遍歷陣列
		for (String className : classNames) {
			// 使用Class類通過字串表示的類名獲取對應類檔案
			Class clazz = Class.forName(className);
			// 使用類檔案新建物件
			Object obj = clazz.newInstance();
			// 物件存入Map[鍵:註解屬性值,值:該註解屬性值所標註的類物件]
			// ------|<強制轉換以獲得旗下方法>|<----獲取此類的註解---->|<---獲取註解型別:類註解---->|<-獲取屬性值->|<值>|
			map.put(((MyTypeAnnotation) clazz.getAnnotation(MyTypeAnnotation.class)).strType(), obj);
		}
		for (String key : map.keySet()) {
			System.out.println(key + "\t" + map.get(key));
		}

	}

	/**
	 * 使用反射與遞迴獲取物件
	 * 
	 * @param name
	 * @return obj
	 * @throws Exception
	 * @throws NoSuchMethodException
	 */
	private static Object getBean(String key) throws Exception {
		Object obj = null;
		// 依據傳入的字串型別鍵得到物件值
		obj = map.get(key);
		// 匹配判斷
		if (obj != null) {
			// 獲取物件的類
			Class clazz = obj.getClass();
			// 使用反射獲取該類所有欄位
			Field[] fs = clazz.getDeclaredFields();
			// !第一次迭代終止處!
			// 遍歷這些欄位
			for (Field f : fs) {
				// 獲取欄位註解物件
				MyFieldAnnotation myFieldAnn = f.getAnnotation(MyFieldAnnotation.class);
				// 判斷物件是否為空
				if (myFieldAnn != null) {
					// 獲得註解屬性,字串處理得到對應類set方法名
					// -----------------|<-字首->|<-------------獲取首字母並大寫---------------->|<----獲取無首字母字串------>|
					String methodName = "set" + f.getName().substring(0, 1).toUpperCase() + f.getName().substring(1);
					// 獲得set方法:
					// -------------|<--反射獲取方法-->|<--方法名-->|<---引數型別--->|
					Method method = clazz.getMethod(methodName, f.getType());
					//<--呼叫方法-->|<方法物件>|<強轉目標型別.強制轉換>|<-----遞迴:getBean("dao")----->|
					method.invoke(obj,    f.getType().cast(getBean(myFieldAnn.strField())));
				}

			}
		}
		return obj;
	}
}