Android-注解处理器
Android-Java注解处理器
基本概念
注解处理器(Annotation Processor)是javac的一个工具。它用来在编译时扫描和处理注解(Annotation)。你能够对自己定义注解,并注冊对应的注解处理器。到这里,我如果你已经知道什么是注解,而且知道怎么申明的一个注解。
假设你不熟悉注解,你能够在这官方文档中得到很多其它信息。
注解处理器在Java 5開始就有了,可是从Java 6(2006年12月公布)開始才有可用的API。
过了一些时间,Java世界才意识到注解处理器的强大作用,所以它到近期几年才流行起来。
一个注解的注解处理器,以Java代码(或者编译过的字节码)作为输入。生成文件(一般是.java文件)作为输出。这详细的含义什么呢?你能够生成Java代码。这些生成的Java代码是在生成的.java文件里,所以你不能改动已经存在的Java类。比如向已有的类中加入方法。这些生成的Java文件,会同其它普通的手动编写的Java源码一样被javac编译。
使用注解处理器
以下来讲述怎么在Android Studio中使用注解处理器,
在这里就须要介绍一个gradle插件android-apt了,
官方地址:
https://bitbucket.org/hvisser/android-apt
Android Studio原本是不支持注解处理器的, 可是用这个插件后, 我们就能够使用注解处理器了, 这个插件能够自己主动的帮你为生成的代码创建文件夹, 让生成的代码编译到APK里面去, 并且它还能够让终于编译出来的APK里面不包括注解处理器本身的代码, 由于这部分代码仅仅是编译的时候须要用来生成代码, 终于执行的时候是不须要的。
使用这个插件非常easy, 首先在你项目顶层的build.gradle文件里加入依赖项, 例如以下:
buildscript {
repositories {
jcenter()
}
dependencies {
classpath 'com.android.tools.build:gradle:1.5.0'
classpath 'com.neenbedankt.gradle.plugins:android-apt:1.8'
}
}
然后在app的build.gradle里面加入插件的引用以及须要依赖哪些库, 例如以下:
apply plugin: 'com.android.application'
apply plugin: 'com.neenbedankt.android-apt'
...
dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
testCompile 'junit:junit:4.12'
compile 'com.android.support:appcompat-v7:22.2.1'
compile 'la.dahuo:command:1.0.0'
apt 'la.dahuo:command-codegen:1.0.0'
}
注意上面的apt ‘la.dahuo:command-codegen:1.0.0’, 这里表示引用一个注解处理器的库, 这个库的代码终于不会进入编译出来的APK里面。
使用注解
以下就来介绍怎么使用注解生成代码, 上面出现的库la.dahuo:command,
la.dahuo:command-codegen就是我依据命令设计模式(Command Design Pattern)写的一个注解库, 它用来让我们方便的生成代码, 看下使用方法:
定义Command
@CommandDef("commandName")
public class MyCommand extends Command {
@Param
String paramStr;
@Param("paramIntName")
int paramInt;
@Override
public void execute() {
// do something with params
}
}
上面的代码通过@CommandDef(“commandName”)来标注MyCommand是一个Command类, 它相应的名字为commandName. 然后通过标注@Param来定义了两个參数, @Param不填值的话表示參数名和属性名一样, 也能够通过填入一个值来指定參数名
使用Command
Map<String, Object> params = new HashMap<>();
params.put("paramStr", "string");
params.put("paramIntName", 1);
Command.parse("commandName", params).execute();
分析
看完上面的使用方法, 你可能会认为就这么多代码就能够跑了吗?
不须要再加入什么代码了?
我的答案是: 确实能够跑, 不须要加入其它代码了。
有木有认为用起来非常方便?
我们以下来分析下这是怎么做到的。
首先标注处理器会依据@Param来获取Command的结构信息, 然后用来生成CommandFactory, 生成的代码在build/generated/source/apt以下, 生成的CommandFactory例如以下:
public class MyCommandFactory implements CommandFactory {
public Command newCommand(Map<String, Object> params) {
MyCommand command = new MyCommand();
command.paramStr = TypeConverter.toString(params.get("paramStr"));
command.paramInt = TypeConverter.toInt(params.get("paramIntName"));
return command;
}
}
有了CommandFactory, 我们就能够通过Mapparams来构造Command了.
那Command是怎么自己主动注冊的呢? 那我们就要看另外一个生成的类了.
public class CommandRegisters {
public static void register(Map<String, CommandFactory> map) {
map.put("myCommand", new MyCommandFactory());
}
}
它依据标注@CommandDef来获取了全部Command类的信息, 然后完毕全部Command的注冊.
有了上面自己主动生成的代码, 那么解析Command就非常easy了. 代码例如以下:
public static Command parse(String action, Map<String, Object> params) {
CommandFactory factory = CommandRepository.getInstance().getFactory(action);
if (factory != null) {
return factory.newCommand(params);
}
return EmptyCommand.INSTANCE;
}
CommandRepository类通过反射的方式调用CommandRegisters类的register方法来完毕全部Command的注冊. 这是我这个注解库唯一的一处使用反射的地方, Command的创建都通过CommandFactory来完毕, 性能非常高, 比那些通过大量反射来实现对象映射的库性能好非常多(比方GSON, 能够实现json转object), 并且也不须要依赖非常多代码, 依赖一个非常小的库
la.dahuo:command就够了, 才5K.
怎么创建注解处理器
注解处理器最核心的就是要有一个Processor, 它继承自AbstractProcessor,它长成这个样子:
package com.example;
public class MyProcessor extends AbstractProcessor {
@Override
public synchronized void init(ProcessingEnvironment env){ }
@Override
public boolean process(Set<?
extends TypeElement> annoations, RoundEnvironment env) { }
@Override
public Set<String> getSupportedAnnotationTypes() { }
@Override
public SourceVersion getSupportedSourceVersion() { }
}
init(ProcessingEnvironment env):每一个注解处理器都必须有个空的构造方法。
只是,有一个特殊的init方法,它会被注解处理器工具传入一个ProcessingEnvironment作为參数来调用。
ProcessingEnvironment提供了一些实用的工具类,如Elements。Types和Filter。
我们后面会用到它们。
process(Set<?
extends TypeElement> annotations, RoundEnvironment env):这种方法能够看做每一个处理器的main方法。你要在这里写下你的扫描。推断和处理注解的代码。并生成java文件。
通过传入的RoundEnvironment參数,你能够查询被某个特定注解注解的元素,我们稍后会看到。
getSupportedAnnotationTypes( ):这里你须要说明这个处理器须要针对哪些注解来注冊。注意返回类型是一个字符串的Set,包括了你要用这个处理器处理的注解类型的全名。
getSupportedSourceVersion( ):用于指定你使用的java版本号。通常你会返回SourceVersion.latestSupported( )。
接下来你须要知道的一件事就是注解处理器在它自己的JVM中执行。是的,你没看错。javac启动一个完整的Java虚拟机来给注解处理器执行。这对你意味着什么?你能够使用你在不论什么其它java应用中使用的东西,比方谷歌的guava!假设你愿意。你还能够使用依赖注入工具,如dagger或不论什么你想要使用的库。只是不要忘了。虽然这仅仅是个小的处理器,你依旧须要考虑高效的算法和设计模式,就像是你会为不论什么其它Java应用所做的那样。
注冊你的处理器
你或许会问自己:”我该如何把我的处理器注冊到javac?”。
你须要提供一个.jar文件。就像其它的jar文件一样,你要把编译后的处理器打包到那个文件。
并且你还须要把一个特别的放在META-INF/services下的叫做javax.annotation.processing.Processor的文件打包进你的.jar文件。
所以你的.jar文件内容看起来会像这个样子:
MyProcessor.jar
- com
- example
- MyProcessor.class
- META-INF
- services
- javax.annotation.processing.Processor
java.annotation.processing.Processor文件(打包到MyProcessor.jar中)的内容是用换行符隔开的处理器完整类名:
com.example.MyProcessor
com.foo.OtherProcessor
net.blabla.SpecialProcessor
这样, 一个注解处理器的框架就好了, 完毕代码后编译成jar文件, 然后像開始介绍的那样加入依赖就好了.
gitbub原地址:https://github.com/derron/command-lib#rd
Android-注解处理器的更多相关文章
- Android注解使用之通过annotationProcessor注解生成代码实现自己的ButterKnife框架
前言: Annotation注解在Android的开发中的使用越来越普遍,例如EventBus.ButterKnife.Dagger2等,之前使用注解的时候需要利用反射机制势必影响到运行效率及性能,直 ...
- Java注解处理器(转)
Java中的注解(Annotation)是一个很神奇的东西,特别现在有很多Android库都是使用注解的方式来实现的.一直想详细了解一下其中的原理.很有幸阅读到一篇详细解释编写注解处理器的文章.本文的 ...
- Java注解处理器使用详解
在这篇文章中,我将阐述怎样写一个注解处理器(Annotation Processor).在这篇教程中,首先,我将向您解释什么是注解器,你可以利用这个强大的工具做什么以及不能做什么:然后,我将一步一步实 ...
- Java注解处理器--编译时处理的注解
1. 一些基本概念 在开始之前,我们需要声明一件重要的事情是:我们不是在讨论在运行时通过反射机制运行处理的注解,而是在讨论在编译时处理的注解.注解处理器是 javac 自带的一个工具,用来在编译时期扫 ...
- Android 注解框架对比
Java的注解(Annotation)相当于一种标记,在程序中加入注解就等于为程序打上某种标记,标记可以加在包,类,属性,方法,本地变量上.然后你可以写一个注解处理器去解析处理这些注解(人称编译时注解 ...
- 仿照 ButterKnife 的 Android 注解实例
什么是注解 java.lang.annotation,接口 Annotation,在JDK5.0及以后版本引入. 注解处理器是 javac 的一个工具,它用来在编译时扫描和处理注解(Annotatio ...
- AS 注解处理器 APT Processor MD
Markdown版本笔记 我的GitHub首页 我的博客 我的微信 我的邮箱 MyAndroidBlogs baiqiantao baiqiantao bqt20094 baiqiantao@sina ...
- android注解处理技术APT
APT(Annotation Processing Tool)是java的注解处理技术,它对源代码文件进行检测找出其中的Annotation,根据注解和注解处理器和相应的apt自动生成代码. Anno ...
- Java注解处理器
Java注解处理器 2015/03/03 | 分类: 基础技术 | 0 条评论 | 标签: 注解 分享到:1 译文出处: race604.com 原文出处:Hannes Dorfmann Java ...
- Java注解解析-搭建自己的注解处理器(CLASS注解使用篇)
该文章是继Java注解解析-基础+运行时注解(RUNTIME)之后,使用注解处理器处理CLASS注解的文章.通过完整的Demo例子介绍整个注解处理器的搭建流程以及注意事项,你将知道如何去搭建自己的注解 ...
随机推荐
- 线程同步CriticalSection
孙鑫 第十五/十六课之四 线程同步CriticalSection 说明 在使用多线程时,一般很少有多个线程完全独立的工作.往往是多个线程同时操作一个全局变量来获取程序的运行结果.多个线程同时访问同一个 ...
- [BZOJ 2817] 波浪
Link: BZOJ 2817 传送门 Solution: 算是比较神的DP了吧, 首先这个绝对值处理起来很难受,肯定要想办法去掉 于是想到从小到大插入的方式,便不存在绝对值的问题了 插入一个数只有5 ...
- [BZOJ 1913] signaling 信号覆盖
Link:https://www.lydsy.com/JudgeOnline/problem.php?id=1913 TIP:(注意,这题只能输出6位才能过,7位都不行wtf?) Algorithm: ...
- 【递推】【卡特兰数】CODEVS 3134 Circle
新GET了一种卡特兰数的应用…… 在一个圆上,有2*K个不同的结点,我们以这些点为端点,连K条线段,使得每个结点都恰好用一次.在满足这些线段将圆分成最少部分的前提下,请计算有多少种连线的方法. 不会证 ...
- linux-磁盘目录使用情况-df/du
1. df -h 查看磁盘使用情况 2. du -h --max-depth=1 查看各文件夹大小 3. sudo du -k --max-depth=1 | sort -k 1 -n -r ...
- (转)Android Eclipse 代码混淆
为了防止自己的劳动成果被别人窃取,混淆代码能有效防止被反编译 1. 大家也许都注意到新建一个工程会看到项目下边有这样proguard-project.txt一个文件,这个对混淆代码很重要,如果你不小心 ...
- 推荐一些不错的开源免费易上手的web前端框架
1. bui 2.Semantic UI 3.oniui
- 使用Spring Cloud Sleuth和Zipkin进行分布式链路跟踪
原文:http://www.cnblogs.com/ityouknow/p/8403388.html 随着业务发展,系统拆分导致系统调用链路愈发复杂一个前端请求可能最终需要调用很多次后端服务才能完成, ...
- Android Studio使用过程中Java类突然报红,但项目可运行解决方案
1.点击File->Invalidate Caches / Restart... 2.重启Gradle,清除缓存 3.Clean Project
- 科研不是比赛,而是一种对未知和完美的自我追求——跟邢波(Eric Xing)面对面聊科研
编者按:6月26日,2014年国际机器学习大会(ICML)在北京国际会议中心完美落幕.作为机器学习领域两大顶尖年会之一,这是 ICML大会30多年来首次来到中国和远东,在国内的机器学习界震动不小.身为 ...