Spring自定义注解的创建过程(亲身经历的一道阿里巴巴面试题)

前几天投了一份阿里的java研发工程师简历,然后接到了阿里的一个电话面试,面试官就问了Spring自定义注解。好了进入正题,注解到底是什么?

1.什么是注解?

java中有许多注解,之前的博客中我已经介绍了许多Spring中会用到的注解,比如@Component,@Before等等。官方对注解的描述如下:注解是一种能被添加到java代码中的元数据,类、方法、变量、参数和包都可以用注解来修饰。注解对于它所修饰的代码并没有直接的影响。

换句话说,注解是java的一种数据类型,可以用来修饰类、方法、变量、参数和包,它对代码不会有直接的影响。注解的功能和XML文件类似。

 

2.如何使用自定义注解

注解的使用一共分为以下四步:

2.1 声明一个注解

比如我现在想要自定义一个名为LogAnnotation的注解,其注解类型元素是String为返回值的key(),实现代码如下所示:

public @interface LogAnnotation {
    String key() default "";
}

注解里面定义的是注解类型元素,它有如下的特点:

  1. 访问修饰符必须为public,不写默认为public;
  2. 该元素的类型只能是基本数据类型、String、Class、枚举类型、注解类型(体现了注解的嵌套效果)以及上述类型的一位数组;
  3. 该元素的名称一般定义为名词,如果注解中只有一个元素,请把名字起为value(后面使用会带来便利操作);
  4. ()不是定义方法参数的地方,也不能在括号中定义任何参数,仅仅只是一个特殊的语法;
  5. default代表默认值,值必须和第2点定义的类型一致;
  6. 如果没有默认值,代表后续使用注解时必须给该类型元素赋值。

2.2 使用元注解修饰注解

元注解的作用就是负责其他注解,java中一共有四个元注解,分别是@Target,@Retention,@Documented,@Inherited,下面先介绍以下四种注解的作用:

@TargetTarget说明了注解所修饰的对象范围,取值(ElementType)有:

  1. CONSTRUCTOR:用于描述构造器
  2. FIELD:用于描述符
  3. LOCAL_VARIABLE:用于描述局部变量
  4. METHOD:用于描述方法
  5. PACKAGE:用于描述包
  6. PARAMETER: 用于描述参数
  7. TYPE: 用于描述类、接口(包括注解类型)或者enum声明

@Retention:Retention定义了注解的保留范围,取值(RetentionPoicy)有:

  1. SOURCE:在源文件中有效(即源文件保留)
  2. CLASS:在class文件中有效(即class保留)
  3. RUNTIME:在运行时有效(即运行时保留)

@Documented:Documented用于描述其它类型的annotation应该被作为被标注的程序成员的公共API,因此可以被例如javadoc此类的工具文档化。Documented是一个标记注解,没有成员。

@Inherited:Inherited 元注解是一个标记注解,@Inherited阐述了某个被标注的类型是被继承的。如果一个使用了@Inherited修饰的annotation类型被用于一个class,则这个annotation将被用于该class的子类。 

接下来就可以用这四个元注解去修饰我们的自定义注解了

import java.lang.annotation.*;

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
public @interface LogAnnotation {
    String key() default "";
}

2.3 编写自己的切面实现类,也就是想要注解实现的功能

//定义这个类为切面,并扫描成bean实例
@Component
@Aspect
public class AnnotationAspect {
    //定义切点,切点指向我们的自定义注解
    @Pointcut("@annotation(aspect.LogAnnotation)")
    public void getnewpointcut(){}
    //使用环绕通知,获取方法名和写在注解中的参数
    @Around("getnewpointcut()&&@annotation(logAnnotation)")
    public void around(ProceedingJoinPoint jp,LogAnnotation logAnnotation){
        String note=logAnnotation.key();
        String name=jp.getSignature().getName();
        System.out.println("this method name is"+name);
        try {
            jp.proceed();
        } catch (Throwable throwable) {
            throwable.printStackTrace();
        }
        System.out.println("note is " + note);
    }
    //方法执行结束后输出的内容
    @AfterReturning("getnewpointcut()")
    public void afterrunning(){
        System.out.println("the method ending");
    }
}

在上面的代码中分别使用了Around注解和Before注解来实现功能。

2.4 在XML文件中配置包扫描和自动配置切面



2.5 在方法中使用该注解

package pojo;

import aspect.LogAnnotation;
import org.springframework.stereotype.Component;

@Component("annotiontest")
public class AnnotationTest {
    @LogAnnotation(key = "hello annotation")
    public void service(){
        System.out.println("this is a test");
    }
}

最后测试

@Test
public void test10(){
    ApplicationContext context=new ClassPathXmlApplicationContext("AOPcontext.xml");
    AnnotationTest test= (AnnotationTest) context.getBean("annotiontest");
    test.service();
}

测试结果:

Spring自定义注解的创建过程(亲身经历的一道阿里巴巴面试题)_第1张图片

你可能感兴趣的:(SSM框架,Spring,注解,框架,阿里面试,java)