美文网首页Android开发Android开发经验谈Android技术知识
如何实现自定义Java运行时注解功能

如何实现自定义Java运行时注解功能

作者: 皮球二二 | 来源:发表于2016-06-01 13:07 被阅读2196次

注解(Annotation),也叫元数据。一种代码级别的说明。它是JDK1.5及以后版本引入的一个特性,与类、接口、枚举是在同一个层次。它可以声明在包、类、字段、方法、局部变量、方法参数等的前面,用来对这些元素进行说明,注释。

基础知识

相信大家在Android开发过程中,对注解有一定程度的接触,比如我们在使用EventBus的时候,我们声明

@Subscribe(threadMode = ThreadMode.MainThread)

来接受通过EventBus发出来的数据,
还有ButterKnife,我们在使用OnClick添加点击事件或Bind绑定组件的时候,同样也有类似的写法

@Bind(R.id.index_image)
@OnClick({R.id.index_layout)

以至于什么@Override、@Deprecated、@SuppressWarnings这就不需要说了。
我们在写的时候,最大的感触就是:太方便了!!!直接加一个声明就Ok了。你是不是心动了,自己也写几个注解,是不是程序能够更加简洁一些了?先别急,看看注解的结构

@Retention(CLASS) 
@Target(FIELD)
public @interface Bind {  
/** View ID to which the field will be bound. */  
    int[] value();
}

其实一点概念都不知道的话,确实看到这个会懵逼。我们一个个来解释一下

  1. Retention 表示在什么级别保留此信息
    SOURCE:源码注解,注解仅存在代码中,注解会被编译器丢弃
    CLASS:编译时注解,注解会在class文件中保留,但会被VM丢弃
    RUNTIME:运行时注解,VM运行期间也会保留该注解,因此可以通过反射来获得该注解
  2. Target 表示作用域,可能的ElementType参数包括:
    CONSTRUCTOR:构造方法声明
    FIELD:字段声明
    LOCAL_VARIABLE:局部变量声明
    METHOD:方法声明
    PACKAGE:包声明
    PARAMETER:参数声明
    TYPE:类,接口或enum声明
  3. Inherited 容许子类继承
  4. Documented 生成javadoc时会包含注解

实战1---获取注解值

@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE, ElementType.METHOD})
public @interface MyAnnotation {    
    String value() default "defaultValue";    
    int age();
}

我们声明了一个运行时的注解,可以作用在类还有方法上,包含2个成员变量,其中value有一个默认值是defaultValue
来看看如何获取

@MyAnnotation(age = 10)
public class AnnotationDemo {    
    @MyAnnotation(value = "Hello", age = 100)    
    public static void main(String[] args) {        
        try {            
            Class class_=Class.forName("com.renyu.demo.AnnotationDemo");            
            Annotation myAnnotation=class_.getAnnotation(MyAnnotation.class);            
            if (myAnnotation !=null && myAnnotation instanceof MyAnnotation) {          
                System.out.println(((MyAnnotation) myAnnotation).value()+((MyAnnotation) myAnnotation).age());            
            }            
            for (Method method : class_.getDeclaredMethods()) {                
                MyAnnotation methodAnnotation=method.getAnnotation(MyAnnotation.class);                
                if (methodAnnotation!=null) {           
                    System.out.println(methodAnnotation.value()+methodAnnotation.age());                
                }            
            }        
        } catch (ClassNotFoundException e) {            
            e.printStackTrace();        
        }    
    }
}

果断打印出期望值

defaultValue10
Hello100

实战2---教你写一个简单的类似ButterKnife工具

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface onClick {    
    int[] value();
}

这边如出一辙

下面是简单的调度类,负责实际意义上的点击事件处理

public class InjectorProcessor {    
    public void process(final Object object) {        
        Class class_=object.getClass();        
        Method[] methods=class_.getDeclaredMethods();        
        for (final Method method : methods) {            
            onClick clickMethod=method.getAnnotation(onClick.class);            
            if (clickMethod!=null) {                
                if (object instanceof Activity) {                   
                    for (int id : clickMethod.value()) {                        
                        View view=((Activity) object).findViewById(id);                        
                        view.setOnClickListener(new View.OnClickListener() {                            
                            @Override                            
                            public void onClick(View v) {                                
                                try {                                    
                                    method.invoke(object);                                
                                } catch (IllegalAccessException e) {                                    
                                    e.printStackTrace();                                
                                } catch (InvocationTargetException e) {                                    
                                    e.printStackTrace();                                
                                }                            
                            }                        
                        });                    
                    }                
                }            
             }        
         }    
    }
}

最后使用就很简单了

public class MainActivity extends AppCompatActivity {    
    @Override    
    protected void onCreate(Bundle savedInstanceState) {        
        super.onCreate(savedInstanceState);        
        setContentView(R.layout.activity_main);        
        InjectorProcessor processor=new InjectorProcessor();        
        processor.process(MainActivity.this);    
    }    

    @onClick({R.id.textview})    
    public void click() {        
        Toast.makeText(this, "HHH", Toast.LENGTH_SHORT).show();    
    }
}

相关文章

  • Spring注解原理探索(三)

    之 Java如何识别注解 关键词:Java 反射java.lang.reflect 包,实现反射功能的工具类。注解...

  • 如何实现自定义Java运行时注解功能

    注解(Annotation),也叫元数据。一种代码级别的说明。它是JDK1.5及以后版本引入的一个特性,与类、接口...

  • Spring注解原理探索(一)

    之 Java元注解释义 Question 注解在Java中如何起作用? Spring是如何识别注解? 如何自定义注...

  • 注解原理

    Java内置的注解以及自定义一个注解大家都比较熟悉的了,现在来看看注解实现的原理,看看Java的体系下面是如何对注...

  • 注解原理

    Java内置的注解以及自定义一个注解大家都比较熟悉的了,现在来看看注解实现的原理,看看Java的体系下面是如何对注...

  • 注解原理

    Java内置的注解以及自定义一个注解大家都比较熟悉的了,现在来看看注解实现的原理,看看Java的体系下面是如何对注...

  • 你一直使用注解,但是你知道它的实现原理吗?

    Java内置的注解以及自定义一个注解大家都比较熟悉的了,现在来看看注解实现的原理,看看Java的体系下面是如何对注...

  • 注解学习笔记

    什么是注解注解分类注解作用分类 元注解 Java内置注解 自定义注解自定义注解实现及使用编译时注解注解处理器注解处...

  • java配置 [配置扫描]

    实现功能 java注解扫描 服务 测试

  • Java注解知识梳理—自定义注解处理器

    Java注解知识梳理—自定义注解处理器 前言 前面介绍了如何自定义注解以及Java中关于注解的一些元素作用,学会了...

网友评论

    本文标题:如何实现自定义Java运行时注解功能

    本文链接:https://www.haomeiwen.com/subject/qzrhdttx.html