利用注解完成对成员变量的自动初始化。应用场景,某应用分为很多个模块,为了简化后续开发人员配置新模块的工作,使项目维护更为容易,运用注解来对模块进行初始化。简单修改后可以成为类似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
对模块进行管理
*/
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。