AndroidAOP之路三 注解处理解释器IOC

前言: IOC在Android上会造成性能损耗,不推荐使用,只作为了解。详细了解可以看看文末提供的鸿洋的IOC的教程。

一、提取Annotation信息

当开发者使用了Annotation修饰了类、方法、Field等成员之后,这些Annotation不会自己生效,必须由开发者提供相应的代码来提取并处理Annotation信息。

JDK主要提供了两个类,来完成Annotation的提取:

  • java.lang.annotation.Annotation接口:这个接口是所有Annotation类型的父接口。

  • java.lang.reflect.AnnotatedElement接口:该接口代表程序中可以被注解的程序元素。

1.1 Annotation接口

这个接口比较少用,这个接口里面有四个方法:

package java.lang.annotation;

public interface Annotation {

    boolean equals(Object obj);

    int hashCode();

    String toString();

    //返回该注解的Class,元素使用了多个注解的时候,可以进行输出判断
    Class<? extends Annotation> annotationType();
}

1.2 AnnotatedElement接口

该接口最常用的方法是isAnnotationPresent()、getAnnotation(Class annotationClass):

package java.lang.reflect;

import java.lang.annotation.Annotation;

public interface AnnotatedElement {

    //判断此元素上是否存在指定类型的注解,如果存在则返回true,否则返回false
    default boolean isAnnotationPresent(Class<? extends Annotation> annotationClass) {
         return getAnnotation(annotationClass) != null;
    }

    //返回此元素上存在的指定类型的注解,如果该类型的注解不存在,则返回null
    <T extends Annotation> T getAnnotation(Class<T> annotationClass);

    //返回此元素上存在的所有注解。
    Annotation[] getAnnotations();

    //返回此元素上存在的所有注解。不包括继承
    Annotation[] getDeclaredAnnotations();

    default <T extends Annotation> Annotation getDeclaredAnnotation(Class<T> annotationClass) {
        return AnnotatedElements.getDeclaredAnnotation(this, annotationClass);
    }

    default <T extends Annotation> T[] getDeclaredAnnotationsByType(Class<T> annotationClass) {
        return AnnotatedElements.getDeclaredAnnotationsByType(this, annotationClass);
    }

    default <T extends Annotation> T[] getAnnotationsByType(Class<T> annotationClass) {
        return AnnotatedElements.getAnnotationsByType(this, annotationClass);
    }

}

二、栗子One

简单获取方法

2.1 定义注解MyTag


@Target(ElementType.METHOD) //修饰方法
@Retention(RetentionPolicy.RUNTIME)  //运行时可以获取
public @interface MyTag {

}

2.2 定义解析器

public class MyTagParser {

    public static void process(Object clazz) {

        try {
            for (Method method : clazz.getClass().getMethods()) {
                if (method.isAnnotationPresent(MyTag.class)) {
                    //获取到了,输出
                    Log.e("tag","被mytag注解修饰的方法:" + method.getName());
                } else {
                    Log.e("tag","没有被mytag注解修饰的方法:" + method.getName());
                }
            }
        } catch (Exception en) {
            en.printStackTrace();
        }
    }

}

2.3 启动Activity

public class MainActivity extends Activity{

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        //调用解析器
        MyTagParser.process(this);

    }

    @MyTag
    public void testYes(){

    }

    public void testNo(){

    }

}

2.4 结果

运行就会看到输出,表示已经获取到了对应的实例

......
02-18 15:23:41.622 12446-12446/? E/tag: 没有被mytag注解修饰的方法:stopServiceAsUser
02-18 15:23:41.622 12446-12446/? E/tag: 没有被mytag注解修饰的方法:takeKeyEvents
02-18 15:23:41.622 12446-12446/? E/tag: 没有被mytag注解修饰的方法:testNo
02-18 15:23:41.622 12446-12446/? E/tag: 被mytag注解修饰的方法:testYes
02-18 15:23:41.632 12446-12446/? E/tag: 没有被mytag注解修饰的方法:toString
02-18 15:23:41.632 12446-12446/? E/tag: 没有被mytag注解修饰的方法:triggerSearch
02-18 15:23:41.632 12446-12446/? E/tag: 没有被mytag注解修饰的方法:unbindService
.......

三、栗子Two

取到方法里面的值

3.1 定义注解

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface MyTag {
    String name() default "天平";
    int age();
}

3.2 定义解析器

public class MyTagParser {

    public static void parser(Object o){
        Class clazz = o.getClass();

        for(Method method:clazz.getMethods()){
            if(method.isAnnotationPresent(MyTag.class)){
                MyTag myTag = method.getAnnotation(MyTag.class);
                Log.e("tag","方法名:"+method.getName()+"的注解值为"+myTag.name()+","+myTag.age());
            }
        }

    }

}

3.3 定义activity

public class MainActivity extends Activity{

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        MyTagParser.parser(this);


    }

    @MyTag(age = 20)
    public void testYes(){

    }



}

3.3 结果

将会输出以下内容,name和age都可以获取到。

02-18 16:11:53.493 25662-25662/? E/tag: 方法名:testYes的注解值为天平,20

继续学习了解

推荐鸿洋大牛的教程

Android 进阶 教你打造 Android 中的 IOC 框架 【ViewInject】 (上)

Android 进阶 教你打造 Android 中的 IOC 框架 【ViewInject】 (下)

Android 框架炼成 教你如何写组件间通信框架EventBus

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

KeepStudya

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值