Java注解

   

     注解提供了一种结构化的,并且具有类型检查能力的新途径,从而使得我们能够为代码加入元数据,而不会导致代码杂乱且难以阅读。使用注解能够帮助我们编写累赘的部署描述文件以及其他生成的文件。

一、注解定义

(和接口挺像)

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface MyAnnotation {
    public String info() default "MyAnnotation info"; //default后的是默认值
}

@Target用来定义注解可用在什么地方,可选值有(同时使用多各值用逗号分隔):

    ElementType.Type            类型声明(类,接口,注解,枚举)
    ElementType.METHOD          方法声明;
    ElementType.FIELD           属性,包括枚举的值;
    ElementType.PARAMETER       参数(形参);
    ElementType.CONSTRUCTOR     构造器;
    ElementType.ANNOTATION_TYPE 注解定义;
    ElementType.PACKAGE         包;
    ElementType.LOCAL_VARIABLEnd;局部变量声明;
    ElementType.TYPE_PARAMETER; 类型参数声明;java 1.8引入
    ElementType.TYPE_USE;       类型使用;java 1.8引入

@Retention 定义在哪一个级别可用,值有:

    RetentionPolicy.SOURCE      注解只保留在源文件,当Java文件编译成class文件的时候,注解被遗弃
    RetentionPolicy.CLASS       注解被保留到class文件,但jvm加载class文件时候被遗弃,这是默认的生命周期
    RetentionPolicy.RUNTIME     注解不仅被保存到class文件中,jvm加载class文件之后,仍然存在

1、没有元素的注解称为标记注解。
2、注解可使用的元素类型有:所有的基本类型和String, Class,enum, Annotation。不允许使用其他自定义类型或包装类型。
3、注解不能继承。
4、元注解,即java内置的用来创建注解的注解:

    @Target     用来定义注解可用在什么地方
    @Retention 定义在哪一个级别可用
    @Documented 将此注解包含在javadoc中
    @Inherited  允许子类继承父类的注解

同时Java还内置了三种标准注解

    @Override           定义重写超类中的方法,如果拼写错了,或者方法签名对不上被覆盖的方法,编译器会报错
    @Depreceted         弃用,如果使用了带有此注解的元素,编译器会发出警告;
    @SuppressWarnings   关闭警告信息

 

二、注解处理器

大多数时候我们都需要定义自大的处理器来处理注解逻辑,如果注解没有相应的处理器,那么注解也就是个注释,没什么用。
主要利用反射机制,使用Class.getAnnotation(); Method.getAnnotation();等方法来获取对象上的注解,然后进行相应的操作;
如:

    void myAnnotationHandler(Object o){
        MyAnnotation anno = o.getClass().getAnnotation(MyAnnotation.class);
        if (anno != null)
            System.out.println(anno.info());
        else
            System.out.println("this object has no MyAnnotation");
    }

使用验证:

    @MyAnnotation
    public static class Myclass{}
    public static void main(String[] args) {
        Myclass c = new Myclass();
        myAnnotationHandler(c);
        myAnnotationHandler(1);
    }

结果:

MyAnnotation info
this object has no MyAnnotation

 

三、Spring注解处理器

现在更常用的Spring提供我们使用Aspect来实现AOP面向切面的注解处理器

@Aspect
@Component
public class AopAnnotationHandler {
    //要处理的切面,此处为要处理的注解MyAnnotation
    @Pointcut("@annotation(mypackage.springboot.MyAnnotation)")
    public void pointname(){ }

    //处理切面前的操作
    @Before("pointname()")
    public void beforeAno(JoinPoint joinPoint){
        System.out.println("befroe pointcut");
        Class<?> clazz = joinPoint.getTarget().getClass();
        System.out.println(clazz.getAnnotation(MyAnnotation.class).info());
    }
    //处理切面后的操作
    @After("pointname()")
    public void afterAno(JoinPoint joinPoint){
        try {
            System.out.println("after pointcut");
            //获取切面方法
            Method method = joinPoint.getTarget().getClass()
                    .getMethod(joinPoint.getSignature().getName(), ((MethodSignature)joinPoint.getSignature()).getParameterTypes());
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        }
    }
}

同时注意如果不加@Component注解需要配置<aop:aspectj-autoproxy proxy-target-class="true"/>
常用注解:

@Aspect         切面声明,标注在类、接口(包括注解类型)或枚举上,把当前类标识为一个切面供容器读取     
@Pointcut       切入点声明,即切入到哪些目标类的目标方法,Pointcut是植入Advice的触发条件。每个Pointcut的定义包括2部分,一是表达式,二是方法签名。方法签名必须是 public及void型。可以将Pointcut中的方法看作是一个被Advice引用的助记符,因为表达式不直观,因此我们可以通过方法签名的方式为 此表达式命名。因此Pointcut中的方法只需要方法签名,而不需要在方法体内编写实际代码。
@Before         前置通知, 在目标方法(切入点)执行之前执行。value 属性绑定通知的切入点表达式,可以关联切入点声明,也可以直接设置切入点表达式。注意:如果在此回调方法中抛出异常,则目标方法不会再执行,会继续执行后置通知 -> 异常通知
@Around         环绕增强,相当于MethodInterceptor,目标方法执行前后分别执行一些代码,发生异常的时候执行另外一些代码
@AfterReturning 后置增强,相当于AfterReturningAdvice,方法正常退出时执行
@AfterThrowing  异常抛出增强,相当于ThrowsAdvice
@After          final增强,不管是抛出异常或者正常退出都会执行

 

posted @ 2021-03-08 16:01  覆手为云p  阅读(184)  评论(0编辑  收藏  举报
停止精灵球