java注解
java注解基本概念
定义:注解(Annotation),也叫做元数据,是一种代码级别的说明。从jdk1.5之后引入的一个特性,与类,接口,枚举是在同一个层次。它可以声明在包,类,字段,方法,局部变量,方法参数等的前面,用来对这些被注解标注的元素进行说明,注释。
java注解分类
-
编写文档: 通过代码里面的注解标示生成doc文档。比如swagger
-
代码分析: 通过代码里面的注解标示对代码进行分析。[使用反射]
-
编译检查: 通过代码里标识的注解让编译器能够实现基本的编译检查。比如@override
我们自定义注解主要是进行代码分析。
jdk中预定义的注解
- @Override : 检测被该注解标注的方法是否是继承自父类的。
- @Deprecated : 该注解标注的内容,表示已经过时。未删除,但是不推荐使用,仅仅为了保持向下兼容性。
- @SuppressWarnings : 压制对该方法的警告。
jdk中四种用于定义新注解的元注解
注解名称 | 相关说明 |
---|---|
@Target | 表示该注解可以用在什么位置。 ElementType的取值有:
TYPE: 表示可以注解在类上。
METHOD:表示可以作用在方法上。 FIELD: 表示可以作用在成员变量上。 PARAMETER: 表示可以作用在方法参数上。 LOCAL_VARIABLE; 表示可以作用在局部变量上。 |
@Retention |
表示需要在什么级别保存该注解信息。
SOURCE: 注解将在编译器丢弃。 CLASS: 注解在class文件中可用,但是会被JVM丢弃。 RUNTIME: VM将在运行时保留注释,因此可以通过反射机制读取注解的信息。 自定义注解一般用 RUNTIME。 |
@Documented |
将该注解包含在javadoc中。
|
@Inherited |
允许子类继承父类中的注解。
|
java注解的本质
- 注解的格式:
public @interface 注解名称{
...
}
- 注解的本质:
#上面定义的注解,实际上会被转换成一个集成了 java.lang.annotation.Annotation 接口的接口。
public interface MyAnno extends java.lang.annotation.Annotaion {
}
- 注解的属性:
#注解的属性,就是接口中定义的抽象方法。
java注解的参数说明
- 注解元素可用的类型
1.、所有基本类型(int, float, boolean).
2.、String
3.、枚举enum
4、 自定义类Class
5、 注解类型Annotation,注解可以作为元素的类型,也就是说注解可以嵌套。
- 注解的默认值: 注解的元素不能没有不确定的值。所以说元素要么在注解时提供元素的值,要么就必须制定默认值。
@Target( ElementType.METHOD )
@Retention( RetentionPolicy.RUNTIME )
public @interface Test {
#注解的属性,对应于接口中定义的方法。且方法后面可以通过default来提供默认值。
public int id() defalut -1;
public String description() default '';
}
java注解的自定义
- 关于类上的注解
#1.定义作用在类上的注解:
import java.lang.annotation.*;
//只作用在类上
@Target( ElementType.TYPE )
//运行时期有效
@Retention( RetentionPolicy.RUNTIME )
@Documented
@Inherited
public @interface ClassAnnotation {
public String value() default "";
}
#2.在类上标注@ClassAnnotaion,且在启动时处理该注解。
# 凡是有@ClassAnnotaion注解的类,都进行对象生成,并且设置id名称。
@ClassAnnotation("test1Controller")
public class Test1Controller {
private Integer a = 10;
public Integer getA() {
return a;
}
public static void main(String[] args) throws Exception {
HashMap map = new HashMap();
Class clz = Test1Controller.class;
Annotation clzList[] = clz.getAnnotations();
for ( int i=0; i<clzList.length; i++ ){
Annotation item = clzList[i];
if ( item.annotationType().toString().equals("interface com.mz.controller.ClassAnnotation") ){
//发现是@classAnnotation,那么就进行对象创建
ClassAnnotation classAnnotation = (ClassAnnotation) item;
//获取要生成的对象的id值
String name = classAnnotation.value();
System.out.println(classAnnotation.value());
//生成该类对象
Test1Controller test1Controller = (Test1Controller)Class.forName("com.mz.controller.Test1Controller").newInstance();
System.out.println(test1Controller.getA());
//获取注解中的value属性
map.put(name, test1Controller);
}
}
}
}
- 关于方法上的注解
#1.定义作用在方法上的注解
import java.lang.annotation.*;
@Target( ElementType.METHOD )
@Retention( RetentionPolicy.RUNTIME )
@Documented
@Inherited
public @interface MethodAnnotation {
/**
* 被@MethodAnnotation注解标注的方法,会被放在一个映射中。
* 然后可以通过key去调用这个对象,以及方法。
* */
public String value() default "";
}
#2.注解标注在方法上,并且放到一个映射中。
@ClassAnnotation("test1Controller")
public class Test1Controller {
private Integer a = 10;
public Integer getA() {
return a;
}
@MethodAnnotation("/test")
public void test() throws Exception {
System.out.println("这就是一个测试");
}
public static void main(String[] args) throws Exception {
HashMap map = new HashMap();
Class clz = Test1Controller.class;
Annotation clzList[] = clz.getAnnotations();
for ( int i=0; i<clzList.length; i++ ){
Annotation item = clzList[i];
if ( item.annotationType().toString().equals("interface com.mz.controller.ClassAnnotation") ){
//发现是@classAnnotation,那么就进行对象创建
ClassAnnotation classAnnotation = (ClassAnnotation) item;
//获取要生成的对象的id值
String name = classAnnotation.value();
System.out.println(classAnnotation.value());
//生成该类对象
Test1Controller test1Controller = (Test1Controller)Class.forName("com.mz.controller.Test1Controller").newInstance();
System.out.println(test1Controller.getA());
//获取注解中的value属性
map.put(name, test1Controller);
/*
* 如果该类的方法上存在@MethodAnnation注解,那么外界如果访问该字段,那么就
*
* */
Method method[] = clz.getMethods();
for ( int j =0 ; j<method.length; j++ ){
if (method[j].getName() == "test"){
Annotation annotation = method[j].getAnnotation(MethodAnnotation.class);
method[j].invoke(test1Controller);
System.out.println(annotation.annotationType());
if ( annotation.annotationType().toString().equals("interface com.mz.controller.MethodAnnotation") ){
//此时将对象,方法名,方法参数等记录作为value放到map中,将annotation中的值当做key进行存放。
MethodAnnotation methodAnnotation = (MethodAnnotation) annotation;
System.out.println(methodAnnotation.value());
}
}
}
}
}
}
}
- 关于方法参数上的注解
#1.方法参数上的注解定义
package com.mz.controller;
import java.lang.annotation.*;
@Target(ElementType.PARAMETER)
@Retention(RetentionPolicy.RUNTIME )
@Documented
@Inherited
public @interface ParameterAnnotation {
public String value() default "";
}
#2.在方法参数上进行注解标注,然后获取该方法参数上的注解,并进行处理
package com.mz.controller;
import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.lang.reflect.Parameter;
import java.util.HashMap;
/**
这是一个简单的测试类.
<p>这是一个简单的测试类,里面含有三个模块,一个是用于ui测试 {@code string},一个用于单元测试 @{code Test1Controller},还一个暂未完成. </p>
@author mengze
@date 2019-10-12
@since 1.5
@version 1.0
*/
@ClassAnnotation("test1Controller")
public class Test1Controller {
private Integer a = 10;
public Integer getA() {
return a;
}
@MethodAnnotation("/test")
public void test( @ParameterAnnotation() Integer a ) throws Exception {
System.out.println("这就是一个测试");
}
public static void main(String[] args) throws Exception {
HashMap map = new HashMap();
Class clz = Test1Controller.class;
Annotation clzList[] = clz.getAnnotations();
for ( int i=0; i<clzList.length; i++ ){
Annotation item = clzList[i];
if ( item.annotationType().toString().equals("interface com.mz.controller.ClassAnnotation") ){
//发现是@classAnnotation,那么就进行对象创建
ClassAnnotation classAnnotation = (ClassAnnotation) item;
//获取要生成的对象的id值
String name = classAnnotation.value();
System.out.println(classAnnotation.value());
//生成该类对象
Test1Controller test1Controller = (Test1Controller)Class.forName("com.mz.controller.Test1Controller").newInstance();
System.out.println(test1Controller.getA());
//获取注解中的value属性
map.put(name, test1Controller);
/*
* 如果该类的方法上存在@MethodAnnation注解,那么外界如果访问该字段,那么就
*
* */
Method method[] = clz.getMethods();
for ( int j =0 ; j<method.length; j++ ){
Method temp = method[j];
if (method[j].getName() == "test"){
Annotation annotation = method[j].getAnnotation(MethodAnnotation.class);
// method[j].invoke(test1Controller);
System.out.println(annotation.annotationType());
if ( annotation.annotationType().toString().equals("interface com.mz.controller.MethodAnnotation") ){
//此时将对象,方法名,方法参数等记录作为value放到map中,将annotation中的值当做key进行存放。
MethodAnnotation methodAnnotation = (MethodAnnotation) annotation;
System.out.println(methodAnnotation.value());
}
Parameter parameter[] = method[j].getParameters();
for ( Parameter pTemp : parameter ){
//获取方法上的参数,然后判断该参数上是否有注解;
//如果方法的参数上有注解,表明参数是何种方式接受,或者说这个参数需要接受一个什么值
System.out.println(pTemp.getName());
Annotation annotation1 = pTemp.getAnnotation(ParameterAnnotation.class);
System.out.println(annotation1);
}
}
}
}
}
}
}
- 关于成员变量上的注解
#1. 定义使用在成员变量上的注解
package com.mz.controller;
import java.lang.annotation.*;
@Target(ElementType.PARAMETER)
@Retention(RetentionPolicy.RUNTIME )
@Documented
@Inherited
public @interface ParameterAnnotation {
public String value() default "";
}
#2. 使用@MemberAnnotation注解标注成员属性,并且处理
@ClassAnnotation("test1Controller")
public class Test1Controller {
@MemberAnnotation("20")
private Integer a = 0;
public Integer getA() {
return a;
}
public static void main(String[] args) throws Exception {
Class clz = Test1Controller.class;
Annotation annotation = clz.getAnnotation(ClassAnnotation.class);
//类上面有@ClassAnnotation
if ( annotation != null ){
//因为类上有指定的注解,那么生成该类的对象.
Test1Controller test1Controller = Test1Controller.class.newInstance();
Field field[] = clz.getDeclaredFields();
for (Field fItem : field ){
MemberAnnotation memberAnnotation = fItem.getAnnotation(MemberAnnotation.class);
//成员属性上存在该注解
if ( memberAnnotation != null ){
fItem.set(test1Controller, new Integer(memberAnnotation.value() ));
System.out.println(test1Controller.getA());
}
}
}
}
}
java注解常使用场景
todo 未完待续,太晚熬不住了。