转载

利用注解完成变量自动初始化

利用注解完成对成员变量的自动初始化。应用场景,某应用分为很多个模块,为了简化后续开发人员配置新模块的工作,使项目维护更为容易,运用注解来对模块进行初始化。简单修改后可以成为类似 ButterKnife 的工具。

区别在于 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 对象都能根据注解自己初始化。

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 来完成的。

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 对模块进行管理 */
原文  https://segmentfault.com/a/1190000005988391
正文到此结束
Loading...