做为一名开发人员,注解的的使用是最多见的了,好比Spring框架里的业务层注解@Service、@Transaction,控制层用的@Controller、@Autowired,SpringBoot框架的启动类注解@SpringBootApplication等等。那么如何自定义注解呢?java
注解(Annotation)是元数据的一种形式,从JDK5.0 引入,它能为代码提供一些相关数据,以便于在代码编译或运行时使用。spring
Java中的注解能够修饰类、方法、变量、参数等。注解能够经过反射手段获取其内容,在编译器生成类文件时,注解能够被嵌入到字节码中。固然JVM也能够保留注解的内容,在运行时动态,总结起来主要是如下几个层面:数组
public static void main(String[] args) {
Date date = new Date();
//JDK源码中,Date类的getDay方法被@Deprecated注解标注,表明方法已过期
int day = date.getDay();
}
复制代码
@Slf4j
@Component
@Aspect
public class MyAspect {
@Before(value = "execution(public * com.test.controller.*.*(..))")
public void before(JoinPoint joinPoint) {
log.info("CLASS_METHOD:[{}]" , joinPoint.getSignature().getName());
}
}
复制代码
@Configuration
public class RabbitMqConfig {
@Value("${spring.rabbitmq.host}")
private String rabbitMqHost;
@Value("${spring.rabbitmq.port}")
private String rabbitMqPort;
}
复制代码
首先咱们先看下一个注解示例,下面是javafx.beans包下的@DefaultProperty注解 :springboot
package javafx.beans;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Inherited;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/** * Specifies a property to which child elements will be added or set when an * explicit property is not given. * * @since JavaFX 2.0 */
@Inherited
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface DefaultProperty {
/** * The name of the default property. */
public String value();
}
复制代码
咱们看到定义注解与定义一个class类类似,不过其中class关键字被替换为了@interface,注解里声明了一个String类型的value属性,注意这种声明属性方式!稍后会详细说明。同时还能够看到DefaultProperty注解被@Inherited、@Documented、@Retention(RetentionPolicy.RUNTIME)、@Target(ElementType.TYPE)这些注解所修饰,这就是咱们须要知道另一个概念——元注解(meta-annotations)。bash
元注解是咱们在定义注解时须要用到的一些特殊含义的注解,能够说它们是对声明注解时的注解。java语言为咱们默认提供了如下元注解,在java.lang.annotation包下,咱们来看下:框架
@Retention(RetentionPolicy.XX) 注解的保留域,表示注解的保留范围,可选项有ide
@Target( ElementType.XX) 指定该注解可使用的地方,如类声明、方法声明,变量声明等等, 在定义注解时,若是没有使用Target指定,默认均可以使用。若是使用了Target指定使用的位置,那么该注解只能在所指定的位置使用工具
@Documented 表示在使用Javadoc工具生成文档时,包含此注解信息spa
@Inherited 表示当前注解是可继承的,父类中所使用的注解若是被@Inherited修饰,子类会继承父类中对应的注解code
明白了注解的外在定义形式,那么咱们就来看下注解内部的属性的定义方式,Talk is cheap. Show me the code 多说无益,直接上代码
@Documented
@Inherited
@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface MyAnnotation {
/** *一、属性的定义和接口中方法声明相似,访问修饰符默认是public,可省略,注意属性名后面跟了() */
String name();
/** * 二、能够经过default为属性指定默认值,在注解使用时,能够为之赋值, 也能够不赋值 * 固然若是不经过default为属性指定默认值,在注解使用必须使用该属性而且为之赋值 */
int age() default 1;
/** * 三、注解中的属性value比较特殊,若是使用注解时仅为该属性赋值,"value="能够省略掉, * 可是若是和其余属性同时赋值,“value=”则不能省略,这个特性和value的属性类型无关 */
String value() default "";
/** * 4.注解中属性的类型能够是基本数据类型及其数组、类、枚举、注解 */
boolean sex() default true;
}
复制代码
在上面代码中,咱们自定义了@MyAnnotation注解,而且指明@Target({ElementType.METHOD})代表此注解只能用在方法声明上, @Retention(RetentionPolicy.RUNTIME)指定其保留到代码运行时,因此咱们能够经过反射获取MyAnnotation的属性值。下面咱们定义了一个Person类,并在其中定义了一个sayHello方法,在方法声明上,咱们使用@MyAnnotation注解,咱们将使用反射调用sayHello方法,而且使用MyAnnotation注解中的属性值
package com.test.annotation;
import com.test.enu.Color;
import java.lang.annotation.Annotation;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
public class Person {
@MyAnnotation(name="韩梅梅",age = 30,sex = true,clothes = Color.YELLOW)
public void sayHello(String name){
System.out.println("Hello!" + name);
}
public static void main(String[] args) throws InvocationTargetException, IllegalAccessException {
Person person = new Person();
//获取Person类的Class对象
Class<? extends Person> personClass = person.getClass();
//获取类中声明的方法列表
Method[] declaredMethods = personClass.getDeclaredMethods();
for (Method method : declaredMethods) {
//判断当前方法是否含有MyAnnotation注解
if(method.isAnnotationPresent(MyAnnotation.class)){
//获取MyAnnotation类型注解
MyAnnotation myAnnotation = method.getAnnotation(MyAnnotation.class);
//反射调用方法,并传递注解name属性值为参数
Object invoke = method.invoke(person,myAnnotation.name());
//打印注解中定义的各个类型的值
System.out.println(myAnnotation);
System.out.println(myAnnotation.name()+","+myAnnotation.sex()+","+myAnnotation.age());
}
}
}
}
复制代码
此时的IDE控制台输出,说明咱们经过反射在运行时获取到了@MyAnnotation注解的值
Hello!韩梅梅
韩梅梅,true,30
@com.test.annotation.MyAnnotation(value=, age=30, sex=true, name=韩梅梅, clothes=YELLOW)
复制代码
JDK自带了一些原先定义好的注解,咱们能够直接使用
至于注解内部详细内容,你们能够点进去源码查看。但愿本篇文章对你有所帮助!