注解
Java注解又叫java标注,java提供了一套机制,使得我们可以对方法、类、参数、包、域以及变量等添加标准(即附上某些信息)。
Annotation定义的信息只能在程序运行时通过反射机制被访问。
Java SE5内置了三种标准注解:
@Override,表示当前的方法定义将覆盖超类中的方法。
@Deprecated,使用了注解为它的元素编译器将发出警告,因为注解@Deprecated是不赞成使用的代码,被弃用的代码。
@SuppressWarnings,关闭不当编译器警告信息。
Java SE5内置了三种标准注解:
@Override,表示当前的方法定义将覆盖超类中的方法。
@Deprecated,使用了注解为它的元素编译器将发出警告,因为注解@Deprecated是不赞成使用的代码,被弃用的代码。
@SuppressWarnings,关闭不当编译器警告信息。
自定义注解
1)使用@interface自定义注解
2)当我们使用@interface关键字定义一个注解时,该注解隐含地继承了java.lang.annotation.Annotation接口;
3)如果我们定义了一个接口,并且让该接口继承自Annotation,那么我们所定义的接口依然还是接口而不是注解;
4)Annotation本身是接口而不是注解。可以与Enum类比。
5)当注解中的属性名为value时,在对其赋值时可以不指定属性的名称,而直接写上属性值即可;
6)除了value以外的其他值都需要使用name=value这种赋值方式,即明确指定给谁赋值。
2)当我们使用@interface关键字定义一个注解时,该注解隐含地继承了java.lang.annotation.Annotation接口;
3)如果我们定义了一个接口,并且让该接口继承自Annotation,那么我们所定义的接口依然还是接口而不是注解;
4)Annotation本身是接口而不是注解。可以与Enum类比。
5)当注解中的属性名为value时,在对其赋值时可以不指定属性的名称,而直接写上属性值即可;
6)除了value以外的其他值都需要使用name=value这种赋值方式,即明确指定给谁赋值。
元注解
Java还提供了4中注解,专门负责新注解的创建,即定义注解的注解
@Target
target说明了annotation所修饰的对象范围:annotation可被用于packages、 types(类、接口、枚举、annotation类型)、类型成员(方法、构造方法、成员变量、枚举值)、方法参数和本地变量(如循环变量、catch 参数)。在annotation类型的声明中使用了target可更加明晰其修饰的目标。
CONSTRUCTOR:构造器的声明
FIELD:域声明(包括enum实例)
LOCAL_VARIABLE:局部变量声明
METHOD:方法声明
PACKAGE:包声明
PARAMETER:参数声明
TYPE:类、接口(包括注解类型)或enum声明
target说明了annotation所修饰的对象范围:annotation可被用于packages、 types(类、接口、枚举、annotation类型)、类型成员(方法、构造方法、成员变量、枚举值)、方法参数和本地变量(如循环变量、catch 参数)。在annotation类型的声明中使用了target可更加明晰其修饰的目标。
CONSTRUCTOR:构造器的声明
FIELD:域声明(包括enum实例)
LOCAL_VARIABLE:局部变量声明
METHOD:方法声明
PACKAGE:包声明
PARAMETER:参数声明
TYPE:类、接口(包括注解类型)或enum声明
@Target(ElementType.CONSTRUCTOR)
public @interface ConstructorAnnotation {
String value();
}
@Target(ElementType.METHOD)
public @interface MethonAnnotation {
String value();
}
//@MethonAnnotation("test") 会报错,该注解只能用于方法
public class TestAnnotation {
@ConstructorAnnotation("con")
public TestAnnotation(){
}
@MethonAnnotation("cmy")
public void test(){
System.out.println("--");
}
}
@Retention
表示需要在什么级别保存该注解信息。可选的RetentionPolicy参数包括:
@Retention(RetentionPolicy.SOURCE)
//注解仅存在于源码中,在class字节码文件中不包含
@Retention(RetentionPolicy.CLASS)
// 默认的保留策略,注解会在class字节码文件中存在,但运行时无法获得
@Retention(RetentionPolicy.RUNTIME)
// 注解会在class字节码文件中存在,在运行时可以通过反射获取到
指示注释类型的注释要保留多久。如果注释类型声明中不存在 Retention 注释,则保留策略默认为 RetentionPolicy.CLASS。
@Document
是一个标记注释,表示注释应该出现在类的javadoc中,因为在默认情况下注释时不包括在javadoc中的。所以如果花费了大量的时间定义一个注释类型,并想描述注释类型的作用,可以使用它。注意他与@Retention(RetentionPolicy.RUNTIME)配合使用,因为只有将注释保留在编译后的类文件中由虚拟机加载,然后javadoc才能将其抽取出来添加至javadoc中。
@Inherited
将注释同样继承至使用了该注释类型的方法中(表达有点问题,就是如果一个方法使用了的注释用了@inherited, 那么其子类的该方法同样继承了该注释
表示需要在什么级别保存该注解信息。可选的RetentionPolicy参数包括:
@Retention(RetentionPolicy.SOURCE)
//注解仅存在于源码中,在class字节码文件中不包含
@Retention(RetentionPolicy.CLASS)
// 默认的保留策略,注解会在class字节码文件中存在,但运行时无法获得
@Retention(RetentionPolicy.RUNTIME)
// 注解会在class字节码文件中存在,在运行时可以通过反射获取到
指示注释类型的注释要保留多久。如果注释类型声明中不存在 Retention 注释,则保留策略默认为 RetentionPolicy.CLASS。
@Document
是一个标记注释,表示注释应该出现在类的javadoc中,因为在默认情况下注释时不包括在javadoc中的。所以如果花费了大量的时间定义一个注释类型,并想描述注释类型的作用,可以使用它。注意他与@Retention(RetentionPolicy.RUNTIME)配合使用,因为只有将注释保留在编译后的类文件中由虚拟机加载,然后javadoc才能将其抽取出来添加至javadoc中。
@Inherited
将注释同样继承至使用了该注释类型的方法中(表达有点问题,就是如果一个方法使用了的注释用了@inherited, 那么其子类的该方法同样继承了该注释
注解实例
多value实例:
public enum EnumModel {
RED;
}
public @interface AnnotationModel {
String[] value1() default "hello";
EnumModel value2();
}
public class TestAnnotation {
@AnnotationModel(value1 = {"world", "ABCD"}, value2 = EnumModel.RED)
public void method(){
System.out.println("usage of annotation");
}
public static void main(String[] args){
TestAnnotation usage = new TestAnnotation();
usage.method();
}
}
用注解处理权限过滤问题实例
基本思路为:定义一个注解,给需要权限过滤的方法标上注解。定义一个拦截器,拦截请求的方法,并获取方法对应的注解进行判断。
自定义注解:
@Retention(RetentionPolicy.RUNTIME)//指定该注解是在运行期进行
@Target({ElementType.METHOD})//指定该注解要在方法上使用
public @interface PowerAuth {
<span style="white-space:pre"> </span>String value() default "";
}
根据方法名取得方法
public class ParsePowerAuth {
public static String parseAuthentication(Class<?> clazz, String methodName,Class<?>... parameterTypes) throws NoSuchMethodException {
//根据方法名,取得方法,如果有则返回
Method method = clazz.getMethod(methodName, parameterTypes);
if (null != method) {
PowerAuth powerAuth = method.getAnnotation(PowerAuth.class);
if (null != powerAuth) {//该方法名上存在权限注解
return powerAuth.value();
}
}
return null;
}
}
Struts中拦截器配置与实现
自定义注解
@Retention(RetentionPolicy.RUNTIME)//指定该注解是在运行期进行
@Target({ElementType.METHOD})//指定该注解要在方法上使用
public @interface PowerAuth {
String value() default "";
}
根据方法名取得方法
public class ParsePowerAuth {
public static String parseAuthentication(Class<?> clazz, String methodName,Class<?>... parameterTypes) throws NoSuchMethodException {
//根据方法名,取得方法,如果有则返回
Method method = clazz.getMethod(methodName, parameterTypes);
if (null != method) {
PowerAuth powerAuth = method.getAnnotation(PowerAuth.class);
if (null != powerAuth) {//该方法名上存在权限注解
return powerAuth.value();
}
}
return null;
}
}
Struts中拦截器配置与实现
<interceptors>
<!--权限截器-->
<interceptor name="powerInterceptor" class="com.comm.interceptors.PowerInterceptor" />
</interceptors>
public class PowerInterceptor extends AbstractInterceptor {
@Override
public String intercept(ActionInvocation actionInvocation) throws Exception {
//取得方法名 判断
ActionProxy proxy = actionInvocation.getProxy();
String methodName = proxy.getMethod();
Object action = proxy.getAction();
String powerAuthMethod =
ParsePowerAuth.parseAuthentication(action.getClass(),methodName, null);
}
}