Java注解应用场景
程序员文章站
2022-07-12 11:27:25
...
注解有三种级别,注解的保留级别不同,对注解的使用场景自然不同,
源码级别: 1.APT 在编译期能够获取注解与注解声明的类,包括类中的 所有成员信息,一般用于生成额外的辅助类.
2.可以提供IDE语法检查,取代枚举的使用
字节码: 1.在编译出Class后,通过修改Class数据以实现修改代码逻辑目的。
2.对于是否需要修改的区分或者修改为不同逻辑的判断可以使用注解(这块还没用应用实例)
运行期: 在程序运行期间,通过反射技术动态获取注解与其元素,从而完成不同的逻辑判断 应用场景(自动注入一个View的findViewById操作)
下面介绍:源码级别提供IDE语法检查案例:
public enum Teacher {
LIGUOJING,ZHUPENG
}
@Target(ElementType.PARAMETER)
@Retention(RetentionPolicy.SOURCE)
@IntDef(value = {1,2})//提供语法检查需要传递的值
public @interface Teacher2 {
}
public class IdeTest {
/*
* 我们定义的test方法,只能传递 LIGUOJING 和 ZHUPENG其中一个,为了进行内存优化
* 我们现在不使用枚举,则定义方法为:
* */
private static final int LIGUOJING = 1;
private static final int ZHUPENG = 2;
// 然而此时,调用test2方法由于采用基本数据类型int,将无法进行类型限定。
// 此时使用@IntDef增加自定义注解:
public void test2(int t){
test3(LIGUOJING);
test3(ZHUPENG);
test3(3);//IDE 提供语法检查,3 不符合语法规范,但是编译运行还是没有问题
}
// test3方法提供了语法检查,传递的int值必须是@Teacher2里面定义的
public void test3(@Teacher2 int t){
}
public void test(Teacher teacher){
}
}
在程序运行期间,通过反射技术动态获取注解,并自动完成findViewById操作和成员变量的赋值
public class MainActivity extends AppCompatActivity {
@Inject(resId = R.id.tvText)
private TextView textView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
InjectUtils.injectViewId(this);
textView.setText("通过注解进行findViewById操作");
textView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Intent intent = new Intent(MainActivity.this, MainActivity2.class);
// 这些传递的值,需要在MainActivity2中,通过注解进行赋值操作
intent.putExtra("zhupeng", "失恋好了吗");
intent.putExtra("userId", 110);
intent.putExtra("user", new User("李国菁", 29));
intent.putExtra("userArray",new User[]{new User("李菁",31),new User("李国伟",22)});
startActivity(intent);
}
});
}
}
Inject 和 Autowired注解类代码
@Target(ElementType.FIELD)//作用在成员变量上
@Retention(RetentionPolicy.RUNTIME)// 保留在运行时期
public @interface Inject {
@IdRes int resId();// 其中IdRes 的意思是:必须指定这个int 值为 R.id.xx 类型
}
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface Autowired {
String value() default "";
}
Javabean类
public class User implements Parcelable {
private String name;
private int age;
public User(String name,int age){
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
protected User(Parcel in) {
name = in.readString();
age = in.readInt();
}
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(name);
dest.writeInt(age);
}
@Override
public int describeContents() {
return 0;
}
public static final Creator<User> CREATOR = new Creator<User>() {
@Override
public User createFromParcel(Parcel in) {
return new User(in);
}
@Override
public User[] newArray(int size) {
return new User[size];
}
};
@Override
public String toString() {
return "User{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
public class MainActivity2 extends AppCompatActivity {
@Inject(resId = R.id.tvText)
private TextView textView;
@Autowired(value = "zhupeng")
private String zhupeng;
@Autowired
private int userId;
@Autowired
private User user;
@Autowired
private User[] userArray;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main2);
InjectUtils.injectViewId(this);
InjectUtils.injectAutowired(this);
// InjectUtils.injectIntentValue(this); 这个方法只能赋值String 和int值
String str = "";
for (int i = 0; i <userArray.length ; i++) {
str+= userArray[i];
}
textView.setText(zhupeng + userId + user + "\n" + str);
}
}
InjectUtils 这块是重点内容,需要仔细查看
public class InjectUtils {
public static void injectViewId(Activity activity) {
if (activity == null) {
throw new RuntimeException("Activity is not null");
}
Class<? extends Activity> clazz = activity.getClass();
//获取所有的成员变量,包括 private类型的成员变量
Field[] allFields = clazz.getDeclaredFields();
for (Field field : allFields) {
// 判断该字段上面是否有注解
boolean isPresent = field.isAnnotationPresent(Inject.class);
if (isPresent) {
// 获取字段上的注解
Inject fieldAnnotation = field.getAnnotation(Inject.class);
int viewId = fieldAnnotation.resId();
View view = activity.findViewById(viewId);
// 修改 private 成员变量的值,必须加上下面这句,否则会有问题
field.setAccessible(true);
// 给这个字段进行赋值
try {
field.set(activity, view);
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
}
}
public static void injectIntentValue(Activity activity) {
if (activity == null) {
throw new RuntimeException("Activity is not null");
}
Class<? extends Activity> clazz = activity.getClass();
//获取所有的成员变量,包括 private类型的成员变量
Field[] allFields = clazz.getDeclaredFields();
for (Field field : allFields) {
// 判断该字段上面是否有注解
boolean isPresent = field.isAnnotationPresent(Autowired.class);
if (isPresent) {
// 获取字段上的注解
Autowired fieldAnnotation = field.getAnnotation(Autowired.class);
String key = TextUtils.isEmpty(fieldAnnotation.value()) ? field.getName() : fieldAnnotation.value();
try {
Object value = getValue(field.getType(), activity, key);
field.setAccessible(true);
field.set(activity, value);
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
}
}
public static Object getValue(Class clazz,Activity activity,String key){
System.out.println("clazz : " + clazz);
if (clazz == String.class){
return activity.getIntent().getStringExtra(key);
}else if (clazz == int.class){
return activity.getIntent().getIntExtra(key,0);
}
return new Object();
}
public static void injectAutowired(Activity activity) {
if (activity == null) {
return;
}
Intent intent = activity.getIntent();
if (intent == null) {
return;
}
// intent 传递参数,都是把参数封装在 bundle里面进行传输的
Bundle bundle = intent.getExtras();
if (bundle == null) {
return;
}
Class<? extends Activity> clazz = activity.getClass();
// 获取所有的成员变量
Field[] declaredFields = clazz.getDeclaredFields();
for (Field field : declaredFields) {
// 判断成员变量上有没有Autowired的注解
if (field.isAnnotationPresent(Autowired.class)) {
Autowired autowired = field.getAnnotation(Autowired.class);
String key = TextUtils.isEmpty(autowired.value()) ? field.getName() : autowired.value();
// 获取key 值对应的 value
Object obj = bundle.get(key);
field.setAccessible(true);
try {
/*
* 对于数组类型实现 Parcelable 接口的需要单独处理
* */
// 获取该字段的真正类型
Class<?> type = field.getType();
System.out.println("lgj type :" + type);
// 获取数组单个元素类型
Class<?> componentType = type.getComponentType();
// type 类型是数组,并且是 Parcelable 子类数组
if (type.isArray() && Parcelable.class.isAssignableFrom(componentType)){
Object[] objs = (Object[]) obj;
Object[] objects = Arrays.copyOf(objs, objs.length, (Class<? extends Object[]>) type);
obj = objects;
}
// 通过反射进行赋值运算
field.set(activity, obj);
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
}
}
}