1.注解(Annotation)定义:
1.1 java注解是附加在代码中的一些元信息,用于一些工具在编译、运行时进行解析和使用,起到说明、配置的功能(注解不会也不能影响代码的实际逻辑,仅仅起到辅助性的作用)
1.2 注解为我们在代码中添加信息提供了一种形式化的方法,是我们可以在稍后某个时刻方便地使用这些数据(通过 解析注解 来使用这些数据),常见的作用有以下几种:
(1) 生成文档。这是最常见的,也是java 最早提供的注解。常用的有@see @param @return 等
(2) 跟踪代码依赖性,实现替代配置文件功能。比较常见的是spring 2.5 开始的基于注解配置。作用就是减少配置。现在的框架基本都使用了这种配置来减少配置文件的数量。
(3) 在编译时进行格式检查。如@Override 放在方法前,如果你这个方法并不是覆盖了超类方法,则编译时就能检查出。
1.3 Annotation:
注解的本质就是一个继承了 Annotation 接口的接口,Annotation工作原理:
JDK5.0中提供了注解的功能,允许开发者定义和使用自己的注解类型。该功能由一个定义注解类型的语法和描述一个注解声明的语法,读取注解的API,一个使用注解修饰的class文件和一个注解处理工具组成。
Annotation并不直接影响代码的语义,但是他可以被看做是程序的工具或者类库。它会反过来对正在运行的程序语义有所影响。java注解包含在 java.lang.annotation 包中。
注:注解的出现是在jdk1.5 但是在jdk1.5版本使用注解必须继续类的方法的重写,不能用于实现的接口中的方法实现,在jdk1.6环境下对于继续和实现都是用。
2.常用注解:
2.1 jdk1.5版本内置了三种标准的注解: |
2.2 包java.lang.annotation中包含所有定义自定义注解所需用到的原注解和接口。如接口 java.lang.annotation.Annotation 是所有注解继承的接口,并且是自动继承,不需要定义时指定,类似于所有类都自动继承Object。 该包同时定义了四个元注解分别是:设置注解的作用范围@Target、限定注解的使用@Retention、在帮助文档中加入注解@Documented、在注解中使用继承@Inherited,再次强调下元注解是Java API提供,是专门用来定义注解的注解,其作用分别如下: |
3.注解使用:
3.1 JDK中规定的读取我们在类中定义的注解的api:
//jdk1.5 增加了注解,肯定就增加了相关读取的api,在java.lang.reflect包中新增了AnnotatedElement接口,JDK源码如下:
public interface AnnotatedElement {
boolean isAnnotationPresent(Class<? extends Annotation> annotationClass); //isAnnotationPresent:判断是否标注了指定注解
<T extends Annotation> T getAnnotation(Class<T> annotationClass); //getAnnotation:获取指定注解,没有则返回null
Annotation[] getAnnotations(); //getAnnotations:获取所有注解,包括继承自基类的,没有则返回长度为0的数组
Annotation[] getDeclaredAnnotations(); //getDeclaredAnnotations:获取自身显式标明的所有注解,没有则返回长度为0的数组
}
3.2 自定义注解举例1:
package com.cn.yx.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**I.自定义注解:
* 使用@interface自定义注解时,自动继承了java.lang.annotation.Annotation接口,由编译程序自动完成其他细节。在定义注解时,不能继承其他的注解或接口。
* @interface用来声明一个注解,其中的每一个方法实际上是声明了一个配置参数。
* 方法的名称就是参数的名称,返回值类型就是参数的类型 (返回值类型只能是基本类型、Class、String、enum)
*/
public class AnnotationTest{
@Documented
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface MyAnnotation{
public String name(); //添加变量
public String password() default "1234"; //通过default来声明参数的默认值
String[] value() default "abc"; //数组变量(当注解中使用的属性名为value时,对其赋值时可以不指定属性的名称而直接写上属性值接口)
MyEnum value2() default MyEnum.Sunny; //多变量使用枚举
}
enum MyEnum{
Sunny,Rainy
}
}
/**II.使用自定义注解:
*
*/
public class AnnotationTest2 {
@MyAnnotation(value1={"a","b"})
@Deprecated
public void execute(){
System.out.println("method");
}
}
/**III.读取注解中的信息:
* java自定义注解和运行时靠反射获取注解。(使用反射读取RUNTIME保留策略的Annotation信息的例子)
*/
public static void main(String[] args) throws SecurityException, NoSuchMethodException, IllegalArgumentException, IllegalAccessException, InvocationTargetException {
AnnotationTest2 annotationTest2 = new AnnotationTest2();
//获取AnnotationTest2的Class实例
Class<AnnotationTest2> c = AnnotationTest2.class;
//获取需要处理的方法Method实例
Method method = c.getMethod("execute", new Class[]{});
//判断该方法是否包含MyAnnotation注解
if(method.isAnnotationPresent(MyAnnotation.class)){
//获取该方法的MyAnnotation注解实例
MyAnnotation myAnnotation = method.getAnnotation(MyAnnotation.class);
//执行该方法
method.invoke(annotationTest2, new Object[]{});
//获取myAnnotation
String[] value1 = myAnnotation.value1();
System.out.println(value1[0]);
}
//获取方法上的所有注解
Annotation[] annotations = method.getAnnotations();
for(Annotation annotation : annotations){
System.out.println(annotation);
}
}
/**运行结果:
* method
* a
* @com.cn.yx.annotation.AnnotationDefinition$MyAnnotation(password=1234, value1=[a, b], value2=Sunny, name=345)
* @java.lang.Deprecated()
*
* 注意:
* 1. 要用好注解,必须熟悉java 的反射机制,从上面的例子可以看出,注解的解析完全依赖于反射。
* 2. 不要滥用注解。平常我们编程过程很少接触和使用注解,只有做设计,且不想让设计有过多的配置时。
*/
3.3 自定义注解举例2:
/**I.自定义注解:
*
*/
public class AnnotationDefinition {
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface MyAnnotation {
int value(); //当注解中使用的属性名为value时,对其赋值时可以不指定属性的名称而直接写上属性值接口
}
}
package com.cn.yx.annotation;
import com.cn.yx.annotation.AnnotationDefinition.MyAnnotation;
/**II.定义一个类使用注解
*
*/
public class AnnotationUse {
@MyAnnotation(20)
private int value;
@Override
public String toString() {
return String.valueOf(value);
}
}
package com.cn.yx.annotation;
import java.lang.reflect.Field;
import com.cn.yx.annotation.AnnotationDefinition.MyAnnotation;
/**III.利用反射获取成员变量上面的注解的value并赋值给成员变量。
*
*/
public class AnnotationTest {
public static void main(String[] args) {
try {
Field field = AnnotationUse.class.getDeclaredField("value"); // 获取成员变量value
field.setAccessible(true); //将value设置成可访问的
if (field.isAnnotationPresent(MyAnnotation.class)) { //判断成员变量是否有注解
MyAnnotation myAnnotation = field.getAnnotation(MyAnnotation.class); //获取定义在成员变量中的注解MyAnnotation
int value = myAnnotation.value(); //获取定义在MyBean的MyAnnotation里面属性值
AnnotationUse myBean = new AnnotationUse();
field.setInt(myBean, value); //将注解的值20可以赋给成员变量value
System.out.println(myBean); //验证结果
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
//运行返回结果:20
4.其它常用注解:
4.1 @WebService
作用:当实现 Web Service 时,@WebService 注释标记 Java 类;实现 Web Service 接口时,标记服务端点接口(SEI)。(声明webservice服务)
要点:
实现 Web Service 的 Java 类必须指定 @WebService 或 @WebServiceProvider 注释。不能同时提供这两种注释。
此注释适用于客户机/服务器 SEI 或 JavaBeans 端点的服务器端点实现类。
如果注释通过 endpointInterface 属性引用了某个 SEI,那么还必须使用 @WebService 注释来注释该 SEI。
/**1.定义说明书的显示方法
* serviceName 对应 <service name="PojoService">
* portName 对应 <service>下的 <port name="PojoPort">
* name 对应 <portType name="PojoPortType">
* targetNamespace 对应 targetNamespace="http//:Pojo"
*/
@WebService(serviceName="PojoService", portName="PojoPort", name="PojoPortType", targetNamespace="http//:Pojo")
/**2.定义schemaLocation的显示
* operationName 接口的方法名
* exclude 用于阻止将某一继承方法公开为web服务,默认为false
*/
@WebMethod(operationName="queryPojo",exclude=true)
/**3.接口的返回值
*
*/
@WebResult(name="returnWord")
/**4.接口的参数
*
*/
@WebParam(name="cityName")
@WebService参考:
https://www.cnblogs.com/liuconglin/p/5657674.html
https://blog.csdn.net/cherry_11qianqian/article/details/81536727