在写java时,注解随处可见。
python 的 类似注解的方式比较简单
def log(prefix):
def log_decorator(f):
def wrapper(*args, **kw):
print '[%s] %s()...' % (prefix, f.__name__)
return f(*args, **kw)
return wrapper
return log_decorator
@log('INFO')
def test():
pass
print test()
打印出来的结果:
[INFO] test()...
None
java怎样自定义注解?
一个简单的注解
不需要依赖其它的jar,直接开干,
有三个文件,
一个是定义annotatoin,
一个是使用annotation,
一个测试类
定义annotaoin,就一个接口,
@Retention(RetentionPolicy.RUNTIME)
@Target( {ElementType.TYPE }) //类可用
public @interface OneAnnotation {
String name();
}
定义了一个OneAnnotation后,要有个类来使用一下
@OneAnnotation(name="userAnnotation")
public class UserAnnotation {
}
测试类,找到使用的类,打印一下他的annotation.
public class OneTest {
@Test
public void test(){
UserAnnotation u = new UserAnnotation();
Annotation[] annotations = u.getClass().getAnnotations();
for (int i = 0; i <annotations.length ; i++) {
Annotation tmpa = annotations[i];
if(tmpa instanceof OneAnnotation){
System.out.println(((OneAnnotation) tmpa).name()); //打印,结果为userAnnotation
}
}
}
}
上面是加到类上,那怎么加到方法上?属性上?….
这个控制是在 @Target 这个 定义注解的注解上的。
@Target( { ElementType.METHOD, ElementType.TYPE }) ,表示加到方法和类都行,具体的请看后面的 附
注解处理器是什么,能做啥?
注解处理器是运行它自己的虚拟机JVM中。是的,你没有看错,javac启动一个完整Java虚拟机来运行注解处理器。这对你意味着什么?你可以使用任何你在其他java应用中使用的的东西。使用guava。如果你愿意,你可以使用依赖注入工具,例如dagger或者其他你想要的类库。1
对注解处理器了解不多,这里把一个简单例子复述一遍
需要两个工程,一个用来做成jar(这里用别名A),另一个工程(这里用别名B)用来使用这个jar
这里有效果有点特殊,不是在运行的时候看效果的,而是在编译的时候看效果。把jar生成后,B引用这个jar,编译B工程的时候,会有自定义内容显示出来
我用maven 做jar 工程,里面有三个文件,
PrintMe.java,定义annotation
@Retention(RetentionPolicy.SOURCE)
public @interface PrintMe {
}
MyProcessor.java,注解处理器,这里会打印一些内容
@SupportedAnnotationTypes({"com.yp.annotation.PrintMe"})
public class MyProcessor extends AbstractProcessor {
public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment env) {
System.out.println("这是annotation的process啊!!!!!!");
return true;
}
@Override
public synchronized void init(ProcessingEnvironment processingEnv) {
System.out.println("这是annotation的init啊!!!!!!");
super.init(processingEnv);
}
@Override
public SourceVersion getSupportedSourceVersion() {
return SourceVersion.latestSupported();
}
}
javax.annotation.processing.Processor文件,这不是类,就是一个文件,里面的内容就一行
com.yp.annotation.MyProcessor
上面的工程打成jar包扔到测试工程B,
B工程没什么要求,就一个能运行的程序即可。
随便一个地方加上 @PrintMe,比如
@PrintMe
public class DJsonUtils {
//...
}
说明:如果用了maven,在pom.xml 引入本地jar,即上面生成的。
<dependency>
<groupId>com.yp</groupId>
<artifactId>annotation</artifactId>
<version>1.0-SNAPSHOT</version>
<scope>system</scope>
<systemPath>${project.basedir}/lib/annotation-1.0-SNAPSHOT.jar</systemPath>
</dependency>
编译的时候,会打印下面的情况
[INFO] ------------------------------------------------------------------------
[INFO] Building lang 1.5
[INFO] ------------------------------------------------------------------------
[WARNING] The artifact commons-email:commons-email:jar:1.1 has been relocated to org.apache.commons:commons-email:jar:1.1
[INFO]
[INFO] --- maven-resources-plugin:2.5:resources (default-resources) @ lang ---
[debug] execute contextualize
[INFO] Using 'UTF-8' encoding to copy filtered resources.
[INFO] Copying 3 resources
[INFO]
[INFO] --- maven-compiler-plugin:2.3.2:compile (default-compile) @ lang ---
[INFO] Compiling 9 source files to E:\codeplace\idea-own\d-common-lang\target\classes
这是annotation的init啊!!!!!!
这是annotation的process啊!!!!!!
这是annotation的process啊!!!!!!
process中的方法能做些什么?
//TODO
process能不能在运行过程中使用呢?比如,打印出一个方法的运行时间? 2
//TODO
附annotation 的annotation 相关参数
注解 | Are |
@Target | 定义注解的作用目标 |
@Retention | 定义注解的保留策略。RetentionPolicy.SOURCE:注解仅存在于源码中,在class字节码文件中不包含;RetentionPolicy.CLASS:默认的保留策略,注解会在class字节码文件中存在,但运行时无法获得;RetentionPolicy.RUNTIME:注解会在class字节码文件中存在,在运行时可以通过反射获取到。 |
@Document | 说明该注解将被包含在javadoc中 |
@Inherited | 说明子类可以继承父类中的该注解 |
Target类型 | 说明 |
ElementType.TYPE | 定义注解的作用目标 |
ElementType.FIELD | 字段、枚举的常量 |
ElementType.METHOD | 方法 |
ElementType.PARAMETER | 方法参数 |
ElementType.CONSTRUCTOR | 方法参数 |
ElementType.CONSTRUCTOR | 构造函数 |
ElementType.LOCAL_VARIABLE | 局部变量 |
ElementType.ANNOTATION_TYPE | 注解 |
ElementType.PACKAGE | 包 |