注解这东西虽然在jdk1.5就加进来了,但他的存在还是因为使用Afinal框架的view注入才知道的。一直觉得注入特神奇,加了一句就可以把对应view生成了。

下面我们来认识一下注解这个东西

一、注解相关知识

注解相当于一种标记,在javac编译器,开发工具和其他程序可以用反射来了解你的类及各种元素上有无何种标记,看你有什么标记,就去干相应的事。标记可以加在包,类,字段,方法,方法的参数以及局部变量上。

1、元注解:作用是负责注解其他注解。Java5.0定义了4个标准的meta-annotation类型,它们被用来提供对其它 annotation类型作说明

@Target:用于描述注解的使用范围(即:被描述的注解可以用在什么地方)

ElementType参数有:

1)CONSTRUCTOR:用于描述构造器

2)FIELD:用于描述域

3)LOCAL_VARIABLE:用于描述局部变量
4)METHOD:用于描述方法

5)PACKAGE:用于描述包

6)PARAMETER:用于描述参数

7)TYPE:用于描述类、接口(包括注解类型) 或enum声明

@Retention:用于描述注解的生命周期(即:被描述的注解在什么范围内有效)
RetentionPoicy参数有:

1.SOURCE:在源文件中有效(即源文件保留)

2.CLASS:在class文件中有效(即class保留)

3.RUNTIME:在运行时有效(即运行时保留)

@Documented 表明这个注解被javadoc工具记录,默认是不被javadoc注解的. 即声明注解@Documented,则注解类型信息会被生成在文档中

@Inherited指明被注解的类会自动继承,即:注解类中的所有属性与方法会被子类继承

二、自定义注解

语法:public @interface 注解名 {定义体}

注解方法参数要求: 
1)只能用public或默认(default)这两个访问权修饰
2)参数成员只能用基本类型byte,short,char,int,long,float,double,boolean八种基本数据类型和 String,Enum,Class,annotations等数据类型,以及这一些类型的数组.

3)如果只有一个参数成员,最好把参数名称设为"value"

4)注解元素必须有确定的值。可以在定义注解的默认值中指定,或在使用注解时指定。如:String onClick() default "";

代码如下:

定义注解

 @Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface FindViewByIdAnnotation { int id() default 0;
String onClick() default ""; }

使用注解

 @FindContentViewAnnotation(R.layout.activity_annotation)
public class AnnotationActivity extends Activity { @FindViewByIdAnnotation(id = R.id.tvShow, onClick = "onClickShow")
private TextView tvShow; @FindViewByIdAnnotation(id = R.id.tvHello, onClick = "onClickHello")
private TextView tvHello; @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
FindViewUtil.initView(this);
} public void onClickShow() {
Toast.makeText(getApplicationContext(), "show Mr-Mo", Toast.LENGTH_SHORT).show();
}
public void onClickHello() {
Toast.makeText(getApplicationContext(), "hello Mr-Mo", Toast.LENGTH_SHORT).show();
}
}

三、注解处理器

注解如果不写注解处理器基本相当于注释。所以一般都会写一个注解处理器。FindViewUtil:

 public class FindViewUtil {

     private FindViewUtil() {
} public static void initView(Object object) {
initContentView(object);
initComponentView(object);
} /**
* 初始化setContentView资源布局
*
* @param object
*/
private static void initContentView(Object object) {
Class clazz = object.getClass();
FindContentViewAnnotation contentView = (FindContentViewAnnotation) clazz.getAnnotation(FindContentViewAnnotation.class);
if (contentView != null) {
try {
int resId = contentView.value();
// activity.setContentView(resId);
Method setContentViewMethod = clazz.getMethod("setContentView", int.class);
setContentViewMethod.invoke(object, resId); } catch (Exception e) {
e.printStackTrace();
}
}
} /**
* 初始化控件
*
* @param object
*/
private static void initComponentView(final Object object) {
try {
final Class clazz = object.getClass();
Field[] fields = clazz.getDeclaredFields();
for (Field field : fields) {
FindViewByIdAnnotation viewByIdAnnotation = field.getAnnotation(FindViewByIdAnnotation.class);
if (viewByIdAnnotation != null) {
int resId = viewByIdAnnotation.id();
final String onClick = viewByIdAnnotation.onClick();
Object view;
if (object instanceof Fragment) {
Method getViewMethod = clazz.getMethod("getView");
View rootView = (View) getViewMethod.invoke(object);
view = rootView.findViewById(resId);
} else {
Method findViewByIdMethod = clazz.getMethod("findViewById", int.class);
view = findViewByIdMethod.invoke(object, resId);
} field.setAccessible(true);
field.set(object, view); if (onClick != null && onClick.trim().length() > 0) {
Object objectField = field.get(object);
if (objectField instanceof View) {
final Method onClickMethod = clazz.getMethod(onClick);
View viewItem = (View) objectField;
viewItem.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
try {
onClickMethod.setAccessible(true);
onClickMethod.invoke(object);
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
}
}
}
} catch (Exception e) {
e.printStackTrace();
}
} }

到此就是自定义注解的全部步骤,以上代码可以完成view注入功能。

本文部分知识总结自:http://www.cnblogs.com/peida/archive/2013/04/24/3036689.html

代码下载地址:https://github.com/MrxMo/IOCView

Java注解(自定义注解、view注入)的更多相关文章

  1. Java实现自定义注解开发

    Java实现自定义注解开发 一直都对注解开发挺好奇的,最近终于有时间自己实践了一把,记录一下 万一后期会用到呢 哈哈哈 首先我们了解一下自定义注解的标准示例,注解类使用 @interface 关键字修 ...

  2. java/springboot自定义注解实现AOP

    java注解 即是注释了,百度解释:也叫元数据.一种代码级别的说明. 个人理解:就是内容可以被代码理解的注释,一般是一个类. 元数据 也叫元注解,是放在被定义的一个注解类的前面 ,是对注解一种限制. ...

  3. Java中自定义注解类,并加以运用

    在Java框架中,经常会使用注解,而且还可以省很多事,来了解下自定义注解. 注解是一种能被添加到java代码中的元数据,类.方法.变量.参数和包都可以用注解来修饰.注解对于它所修饰的代码并没有直接的影 ...

  4. Java Annotation自定义注解详解

    在开发过程中总能用到注解,但是从来没有自己定义过注解.最近赋闲在家,研究整理了一番,力求知其然知其所以然. 本文会尝试描述什么是注解,以及通过一个Demo来说明如何在程序中自定义注解.Demo没有实际 ...

  5. Java利用自定义注解、反射实现简单BaseDao

    在常见的ORM框架中,大都提供了使用注解方式来实现entity与数据库的映射,这里简单地使用自定义注解与反射来生成可执行的sql语句. 这是整体的目录结构,本来是为复习注解建立的项目^.^ 好的,首先 ...

  6. Java基于自定义注解的面向切面的实现

    目的:实现在任何想要切的地方添加一个注解就能实现面向切面编程 自定义注解类 @Target({ElementType.PARAMETER, ElementType.METHOD}) @Retentio ...

  7. [转] Java @interface 自定义注解

    [From] http://blog.csdn.net/afterlife_qiye/article/details/53748973 1. 注解的好处 注解可以替代配置文件完成对某些功能的描述,减少 ...

  8. java中自定义注解的应用

    要想深刻的理解注解,我们必须能实现自己的注解,然后应用自己的注解去实现特定的业务,使用注解可以更优雅的做到某些事情. 有这样一个场景,在需要文件导出时,我们需要将一个model中的一些重要字段导出到c ...

  9. Java如何自定义注解

    本文主要是记录所学,以供后续参考.注解是Java 1.5引入的,Java自定义注解是通过运行时靠反射获取注解,注解相当于是一种嵌入在程序中的元数据,可以使用注解解析工具或编译器对其进行解析,也可以指定 ...

  10. java 注解 + 自定义注解的使用

    java中元注解有四个: @Retention @Target @Document @Inherited:  @Retention:注解的保留位置 @Retention(RetentionPolicy ...

随机推荐

  1. PostgreSQL的注释嵌套的例子

    pgsql=# -- Multiline comments pgsql=# SELECT 'Multi' /* This comment extends across pgsql*# * number ...

  2. CodeForces 163B Lemmings 二分

    Lemmings 题目连接: http://codeforces.com/contest/163/problem/B Descriptionww.co As you know, lemmings li ...

  3. Codeforces Beta Round #29 (Div. 2, Codeforces format) C. Mail Stamps 离散化拓扑排序

    C. Mail Stamps Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://codeforces.com/problemset/problem ...

  4. android 下修改 hosts文件 及 out of memory的解决

    因为android模拟器host文件无法修改,导致无法通过域名使用http方法调用内网服务,因此从网上大量转载的一种方法,这种方法: 1. 通过emulator -avd avdName -parti ...

  5. IPC——信号

    Linux进程间通信——使用信号 一.什么是信号 用过Windows的我们都知道,当我们无法正常结束一个程序时,可以用任务管理器强制结束这个进程,但这其实是怎么实现的呢?同样的功能在Linux上是通过 ...

  6. linux 文件系统的管理 (硬盘) 工作原理

    一.系统在初始化时如何识别硬盘 1.系统初始时根据MBR的信息来识别硬盘,其中包括了一些执行文件就来载入系统,这些执行文件就是MBR里前面446bytes里的boot loader 程式,而后面的16 ...

  7. xy

    用C#實現Blob數據類型 PowerBuilder提供了Blob數據類型, 用來處理二進制數據(如:圖像,文件,二進制流,文本等等). 本質上, Blob是可變長的字節數組, 它提供了一系列全局函數 ...

  8. 虚拟文件系统VFS

    Linux的文件系统是由虚拟文件系统作为媒介搭建起来的,虚拟文件系统VFS(Virtual File System)是Linux内核层实现的一种架构,为用户空间提供统一的文件操作接口.它在内核内部为不 ...

  9. 20条IPTables防火墙规则用法!

    导读 管理网络流量是系统管理员必需处理的最棘手工作之一,我们必需规定连接系统的用户满足防火墙的传入和传出要求,以最大限度保证系统免受攻击.很多用户把 Linux 中的 IPTables 当成一个防火墙 ...

  10. Spring SqlRowSet example--转载

    原文地址:http://www.roseindia.net/tutorial/spring/spring3/jdbc/sqlrowset.html The 'SqlRowSet' is used to ...