1.自定义注解:比如 @Controller,@Service,@Table等等,是开发者定义的注解。
2.元注解:jdk的注解,有四个:@Target,@Inherited ,@Retention,@Documented。
3.内置注解:jdk除了四个元注解之外的注解,如@Override,@SuppressWarnings等
自定义注解流程:
自定义注解很简单:选择ide,创建annotation取名即可。
然后我们的自定义注解就创建成功啦。
package com.jym.demo.bean;
public @interface MyAnnotation {
}
当然 我们还可以给注解添加属性。注解里定义属性,跟类中的方法类似,需要加括号,如果属性没有默认值,则被注解修饰的类上,必须定义值,否则编译不通过。
package com.jym.demo.bean;
public @interface MyAnnotation {
// 注解属性
String name(); // 被修饰的类必须给name属性赋值,否则会报错
int age() default 25; // 默认值为25
String hello() default "hello,world"; // 默认值为hello,world
}
@Retention(RetentionPolicy.SOURCE):
注解会保留在源码里,但是编译成class文件后不会出现,即为注解的第一阶段。@Override、@SuppressWarnings都属于这类注解,可以做一些检查性的操作;
@Retention(RetentionPolicy.CLASS):
注解会保留在源码,以及编译后的class文件中,但是不会保留在JVM中,为注解的第二阶段,同样注解也是默认使用这种方式
@Retention(RetentionPolicy.RUNTIME):注解的第三阶段,存在于源码,class文件,以及jvm中,因此我们可以通过反射拿到该注解的信息,我们自定义注解通常使用这种方式,@Deprecated属于此类注解。
具体的反射方式:
注解:
package com.jym.demo.bean;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@Retention(RetentionPolicy.RUNTIME)
public @interface MyAnnotation {
// 注解属性
String name(); // 被修饰的类必须给name属性赋值,否则会报错
int age() default 25; // 默认值为25
String hello() default "hello,world"; // 默认值为hello,world
}
被注解修饰的类:
@MyAnnotation(name = "jym")
public class Person {}
测试方法:
public static void main(String[] args) {
Class<Person> clazz = Person.class;
if(clazz.isAnnotationPresent(MyAnnotation.class)){
MyAnnotation myAnnotation = clazz.getAnnotation(MyAnnotation.class);
System.out.println(myAnnotation.name()+":"+myAnnotation.age());
}
}
结果:
jym:25
@Target(ElementType.TYPE) :用于接口、类、枚举、注解
@Target(ElementType.FIELD) :字段、枚举的常量
@Target(ElementType.METHOD) :方法
@Target(ElementType.PARAMETER) :方法参数
@Target(ElementType.CONSTRUCTOR) :构造函数
@Target(ElementType.LOCAL_VARIABLE) :局部变量
@Target(ElementType.ANNOTATION_TYPE) :注解
@Target(ElementType.PACKAGE) :包
具体反射流程:
注解:
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface MyAnnotation {
// 注解属性
String name(); // 被修饰的类必须给name属性赋值,否则会报错
int age() default 25; // 默认值为25
String hello() default "hello,world"; // 默认值为hello,world
}
修饰类:
public class Person {
private int age;
@MyAnnotation(name = "jym")
private String name;
private Date birth;
}
测试方法:
public static void main(String[] args) {
Class<Person> clazz = Person.class;
Field[] declaredFields = clazz.getDeclaredFields(); // 获取所有字段
for (Field declaredField : declaredFields) {
MyAnnotation annotation = declaredField.getAnnotation(MyAnnotation.class);
if(annotation!=null){
System.out.println("姓名:"+annotation.name());
}
}
结果:
姓名:jym
说明该注解将被包含在javadoc中,至于javadoc,就是通过Javadoc技术,从程序源代码中抽取类、方法、成员等注释形成一个和源代码配套的API帮助文档。需要更多了解的,请百度一下。
继承性,加上这个注解,别的类在继承被该注解修饰的类时,会自动加上这个注解。通过反射也是可以拿到的。
getFields()方法获得某个类的所有的public的字段,包括父类。getDeclaredFields()获得某个类的所有申明的字段,即包括public、private和proteced,但是不包括父类的申明字段。同样类似的还有getConstructors()和getDeclaredConstructors(),getMethods()和getDeclaredMethods()。如果感兴趣的,可以在控制台打印一下。
java的一切注解都是基于元注解的
@Override(重写父类方法)
@SuppressWarning(阻止警告)
@FunctionaInterface(指定接口函数式编程)
@SafeVarargs(堆污染警告)
在SpringMVC中,就是通过对controller修饰的类进行反射,将注解里的值存进MAP里,核心servlet才能找到对应的类中的对应方法所执行