注解的入门使用
注解的基本概念
注解又叫标注,本质上就是对代码的特殊标记,通过这些标记可以在类的编译、加载以及运行时做指定的处理。
注解的语法格式
访问修饰符 @interface 注解名称{
}
自定义注解自动继承 java.lang.annotation.Annotation 接口
注解的使用
在类名上通过 @注解名称来引入
注解成员变量
在注解中只有成员变量,而没有成员方法。注解的成员变量以"无形参的方法" 形式来声明 。成员变量的类型用方法的返回值来表示。类型只能是八种基本数据类型、String类型、Class类型、enum类型以及Annotation类型。
public @interface MyAnnotation{
public String value() default "";
}
在定义注解的时候定义了成员变量,在使用注解的时候可以使用 成员参数名=成员参数值的方式给注解传值,如果不想传值的话就使用default 关键字
@MyAnnotation(value = "小李")
public class Person{
}
获取注解值
MyAnnotation annotion = Person.class.getAnnotation(MyAnnotation.class);
String value = annotion.value();
元注解
元注解是可以注解到注解上的注解,也就是给自定义注解贴标签标记。通常用来说明自定义注解的声明周期,以及作用范围,是否可以重复使用等等
-
@Retention 声明该注解的生命周期 常用值有
@RetentionPolicy.SOURCE 注解只在源码阶段有效 @RetentionPolicy.CLASS 注解只会保留在编译运行的时候,不会被jvm 加载到内存中 @RetentionPolicy.RUNTIME 注解可以保留到运行时阶段会被加载到jvm中 -
@Target 注解的作用范围,传入的值是一个数组,可以传多个值
ElementType.ANNOTATION_TYPE 可以给一个注解进行注解 ElementType.CONSTRUCTOR 可以给构造方法进行注解 ElementType.FIELD 可以给属性进行注解 ElementType.LOCAL_VARIABLE 可以给局部变量进行注解 ElementType.PACKAGE 可以给包进行注解 ElementType.PARAMETER 可以给参数进行注解 ElementType.TYPE 可以给类型进行注解 ElementType.METHOD 可以给方法进行注解 -
@Documented 使用javacdoc 工具可以从程序中抽取类、方法、成员 等注释形成一个和源代码配套的API文档,而该工具抽取时默认不包含注解内容
-
@Repeatable 表示可以重复使用,实际上也是依赖于一个注解数组的实现
public @interface ManTypes(){ Mantype[] value(); } @Reapeatable(ManType.class) public @interface ManType(){ String value(); } @ManType("运营") @ManType("客服") pulic class Person{}
-
@Inherited
@Inherited并不是说注解本身可以继承,而是说如果一个超类被该注解标记过的注解进行注解时,如果子类没有被任何注解应用时,则子类就继承超类的注解。
说起来有些绕口。可以这样想,如果子类想要继承父类上的注解,该怎么办呢?可以让父类的注解被@Inherited注解标记,被标记的注解就可以被继承。
常见的预制注解
实际应用
在反射创建对象的时候,可以根据注解值的不同做相应的处理
if(aClass.isAnnotationPresent(LagouController.class)){
//说明是一个controller 的id 此处不做过多处理 ,不取value 就拿首字母小写,保存到ioc 中
String simpleName = aClass.getSimpleName();
String lowerFirstSimpleName = lowerFirst(simpleName); //demoController
Object o = aClass.newInstance();
ioc.put(lowerFirstSimpleName,o);
}else if(aClass.isAnnotationPresent(LagouService.class)){
LagouService annotation = aClass.getAnnotation(LagouService.class);
//获取注解value 的值
String beanName = annotation.value();
//指定了id 就以指定的为准,如果没有指定那就以类名首字母小写
if(!"".equals(beanName.trim())){
ioc.put(beanName,aClass.newInstance());
}else {
// 如果没有指定 就以类名首字母小写
beanName = lowerFirst(aClass.getSimpleName());
ioc.put(beanName,aClass.newInstance());
}
//service 层往往有接口的,面向接口开发,再以接口名为id ,放入一份对象到IOC 容器中,便于后期根据接口类型注入
Class<?>[] interfaces = aClass.getInterfaces();
for (int j = 0; j < interfaces.length; j++) {
Class<?> aninterface = interfaces[j];
ioc.put(aninterface.getName(),aClass.newInstance());
}
}else {
continue;
}