利用註解完成變量自動初始化

利用註解完成對成員變量的自動初始化。應用場景,某應用分爲不少個模塊,爲了簡化後續開發人員配置新模塊的工做,使項目維護更爲容易,運用註解來對模塊進行初始化。簡單修改後能夠成爲相似ButterKnife的工具。java

區別在於ButterKnife的註解類型是@Retention(RetentionPolicy.SOURCE)的,即源代碼編譯階段發揮做用的註解,編譯完後就丟棄了。而我用的是@Retention(RetentionPolicy.RUNTIME),也是書上用到的,即運行時的再生效的註解,使用反射來完成註解所要達成的目標,有必定的性能損耗。函數

ModuleEntry

先來看ModuleEntry類,每一個該類對象表示一個模塊。工具

public class ModuleEntry {
    int id;
    String name;
    String des;
    public ModuleEntry(int id, String name, String des) {
        this.id = id;
        this.name = name;
        this.des = des;
    }
}

Module註解

@Target(ElementType.FIELD)
@Retention(RetentionPolicy.SOURCE)
public @interface Module {
    int id();
     //String value();//注意註解中名爲value的元素,若是應用該註解時,value元素是惟一須要賦值的元素,那麼只需在括號內給出value元素所需的值便可
    String moduleName() default "";
    String moduleDes() default "";
}

ModuleSet 註解

用以標識包含ModuleEntry的對象的類,咱們將對這個類中的帶有Module註解的元素進行自動初始化。性能

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface ModuleSet {
    String value();//其實這裏的value沒有什麼意義,是爲了表示一下value元素的特殊,這點稍後會看到
}

Main函數

先看main函數,我最終想要實現的效果應該是其中的ModuleEntry對象都能根據註解本身初始化。this

class Activity{}
@ModuleSet("Main")
class MainActivity extends Activity{
    @Module(id = 0,
            moduleName = "模塊管理",
            moduleDes = "對模塊進行管理")
    ModuleEntry mManagerModule;

    @Module(id = 1,
            moduleName = "校園網",
            moduleDes = "校園網管理")
    ModuleEntry mSeunetModule;

    ModuleEntry mOtherModule;
  
    public MainActivity(){
        ModuleHelper.configureModule(this);
    }
}

public class Main{
    public static void main(String[] args){
        MainActivity mainActivity = new MainActivity();
        System.out.println(mainActivity.mManagerModule.des);
        //NullPointerException,由於mOtherModule沒有添加註解,不會被自動初始化
        //System.out.println(mainActivity.mOtherModule.des);
    }
}

而自動初始化是由ModuleHelper來完成的。code

ModuleHepler

public class ModuleHelper {
    public static void configureModule(Activity activity){
        //輸出傳入對象類型
        System.out.println(activity.getClass());
        //查看其是否添加了ModuleSet註解並獲取註解
        System.out.println(activity.getClass().isAnnotationPresent(ModuleSet.class));
        ModuleSet moduleSetAnnotation = activity.getClass().getAnnotation(ModuleSet.class);
        //必須添加了該註解的類才能使用這個方法,不然不作任何操做
        if (moduleSetAnnotation == null)return;
        
        //遍歷全部的域
        for (Field field : activity.getClass().getDeclaredFields()){
            Module module = field.getAnnotation(Module.class);

            //若是沒有模塊註解,或者其類型不是模塊實體,則跳過
            if(module == null || field.getType() != ModuleEntry.class)continue;
            //對全部的知足條件的Field,輸出模塊對應的名字和描述
            System.out.println(module.moduleName() + " " + module.moduleDes());
            System.out.println(field.getName());
            
            //生成模塊條目
            ModuleEntry moduleEntry = new ModuleEntry(module.id(),module.moduleName(),module.moduleDes());
            try {
                field.setAccessible(true);
                //使用set函數能夠爲當前的field實際表明的對象進行賦值,若是是static對象則能夠把第一個參數置爲null
                field.set(activity,moduleEntry);
                //使用get函數能夠得到這個對象
                //ModuleEntry moduleEntry0 = (ModuleEntry) field.get(activity);
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            }
        }
    }
}

/**Output
class com.note.MainActivity
true
模塊管理 對模塊進行管理
mManagerModule
校園網 校園網管理
mSeunetModule
對模塊進行管理
*/
相關文章
相關標籤/搜索