Java注解拾遗

注解简介:     

        注解Annotation是jdk1.5的新增功能,在现在的日常开发中,几乎离不开注解,写篇短文,来做个拾遗。

注解作用:

        Annotation(注解)的作用是修饰包、类、构造方法、方法、成员变量等。

      注解语法及定义形式:

  @interface关键字定义
  注解包含成员,成员以无参数的方法的形式被声明。其方法名和返回值定义了该成员的名字和类型。
  成员赋值是通过@Annotation(name=value)的形式
  注解需要标明注解的生命周期,注解的修饰目标等信息,这些信息是通过元注解实现。

  举例:

       

@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)
public @interface Target {
    /**
     * Returns an array of the kinds of elements an annotation type
     * can be applied to.
     * @return an array of the kinds of elements an annotation type
     * can be applied to
     */
    ElementType[] value();
}

       元注解@Retention,成员value的值为RetentionPolicy.RUNTIME、
       元注解@Target,成员value是个数组,用{}形式赋值,值为ElementType.ANNOTATION_TYPE
       成员名称为value,类型为ElementType[]

注解分类:

内置标准注解:

    @Override:用于修饰此方法覆盖了父类的方法
     @Deprecated:用于修饰已经过时的方法
     @SuppressWarnnings:用于通知java编译器禁止特定的编译警告

元注解:

    @Target:说明Annotation所修饰的对象范围
    @Retention:说明Annotation的生命周期
    @Documented :Documented是一个标记注解,主要是用于javadoc
    @Inherited :Inherited也是一个标记注解,假如一个标记了Inherited的注解修饰一个类,那么继承于此类的子类,同样继承该注解
          这样虽然完成了继承,但是注解本身是不允许继承的。

普通注解:

    自定义的完成特定任务的注解

注解生命周期:

    注解的生命周期是由元注解Retention修饰的
    看下Retention的源码
    

@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)
public @interface Retention {
/**
* Returns the retention policy.
* @return the retention policy
*/
RetentionPolicy value();
}

public enum RetentionPolicy {
/**
* Annotations are to be discarded by the compiler.
*/
SOURCE,

/**
* Annotations are to be recorded in the class file by the compiler
* but need not be retained by the VM at run time. This is the default
* behavior.
*/
CLASS,

/**
* Annotations are to be recorded in the class file by the compiler and
* retained by the VM at run time, so they may be read reflectively.
*
* @see java.lang.reflect.AnnotatedElement
*/
RUNTIME
}

SOURCE: 注解只保留在源文件,当Java文件编译成class文件的时候,注解被遗弃
CLASS: 注解被保留到class文件,jvm加载class文件时候被遗弃。这是默认的生命周期
RUNTIME: 注解不仅被保存到class文件中,jvm加载class文件之后,仍然存在,保存到class对象中,可以通过反射来获取

注解的修饰目标:

  注解的修饰目标是由元注解Target修饰的

@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)
public @interface Target {
/**
* Returns an array of the kinds of elements an annotation type
* can be applied to.
* @return an array of the kinds of elements an annotation type
* can be applied to
*/
ElementType[] value();
}

public enum ElementType {
/** Class, interface (including annotation type), or enum declaration */
TYPE,

/** Field declaration (includes enum constants) */
FIELD,

/** Method declaration */
METHOD,

/** Formal parameter declaration */
PARAMETER,

/** Constructor declaration */
CONSTRUCTOR,

/** Local variable declaration */
LOCAL_VARIABLE,

/** Annotation type declaration */
ANNOTATION_TYPE,

/** Package declaration */
PACKAGE,

/**
* Type parameter declaration
*
* @since 1.8
*/
TYPE_PARAMETER,

/**
* Use of a type
*
* @since 1.8
*/
TYPE_USE
}

TYPE:指的是在类,接口(包括注解)或者enum上使用的注解
FIELD:指的在field属性,也包括enum常量使用的注解
METHOD:指的是在方法声明上使用的注解
PARAMETER:指的是在参数上使用的注解
CONSTRUCTOR: 指的是在构造器使用的注解
LOCAL_VARIABLE:指的是在局部变量上使用的注解
ANNOTATION_TYPE:指的是在注解上使用的元注解
PACKAGE:指的是在包上使用的注解

自定义注解:

  自定义注解是利用注解方面很重要的一个方面,这次把项目里的一个自定义的注解分析下
代码如下:

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface LogMethod {
}

@Slf4j
public class LogMethodInterceptor implements MethodInterceptor {
@Override
public Object invoke(MethodInvocation methodInvocation) throws Throwable {
String className = String.valueOf(methodInvocation.getMethod().getDeclaringClass());
String methodName = methodInvocation.getMethod().getName();
Object[] arguments = methodInvocation.getArguments();
log.info("Before:" + className + "." + methodName + "()");
log.info("Arguments:" + JsonTools.toJsonString(arguments));
long start = System.currentTimeMillis();
Object resultObj = methodInvocation.proceed();
long end = System.currentTimeMillis();
log.info("After:result is " + JsonTools.toJsonString(resultObj) + ",the execute time is " + (end - start) + " ms");

return resultObj;
}
}

具体配置:

<bean id="logMethodInterceptor" class="com.*LogMethodInterceptor"/>
<aop:config proxy-target-class="true">
<aop:pointcut id="logMethodPointcut"
expression="execution(* com*service.impl.*.*(..)) and @annotation(com.*annotation.LogMethod)"/>
<aop:advisor advice-ref="logMethodInterceptor" pointcut-ref="logMethodPointcut"/>
</aop:config>

LogMethod 定义了一个 生命周期为RUNTIME 作用在METHOD上的注解
LogMethodInterceptor 注解的处理器
利用Spring的AOP完整在方法的出入口分别打印参数的相关日志

原文地址:https://www.cnblogs.com/daily-note/p/7810604.html