自定义注解
一、什么是注解
Annontation是Java1.5开始引入的新特征,中文名称叫注解。
它提供了一种安全的类似注释的机制,用来将信息或元数据(metadata)与程序元素(类、方法、成员变量等)进行关联。为程序的元素(类、方法、成员变量)加上更直观、更明了的说明,这些说明信息是与程序的业务逻辑无关,并且供指定的工具或框架使用。Annontation像一种修饰符一样,应用于包、类型、构造方法、方法、成员变量、参数及本地变量的声明语句中。Java注解是附加在代码中的一些元信息,用于一些工具在编译、运行时进行解析和使用,起到说明、配置的功能。注解不会也不能影响代码的实际逻辑,仅仅起到辅助性的作用。
注解和注释很像,注释是我们在开发中,提供给代码使用者或者是其他开发人员用来标注代码含义的功能;注解则是我们在开发中,通过注解向程序中的某个元素提供的相关信息,既是开发者告诉程序元素的内容,又可以作为程序元素为我们提供的相关信息的途径。
二、声明注解
注解的内容:
- 基本数据类型
- String
- enum
- Annotation
以上类型的数组
注解的使用:注解中的属性内容可以存在任意个,根据业务的需求和需要设置的内容,设置不同的属性内容。
- 属性内容可以通过default设置默认值,如果属性内容存在默认值,在使用注解时可以不为属性内容赋值,但是一旦赋值,则按照新的赋值内容进行处理。
- 如果只有一个属性内容需要赋值,并且属性内容的名称是value,则value可以省略,直接定义值即可。
- 数组赋值时,值使用{}包裹。如果数组中只有一个值,则{}可以省略
三、元注解
所有元注解定义在java.lang.annotation包下面,其中Annotation是注解的基本接口,所有的注解都继承这个接口。
java.lang.annotation 提供了四种元注解,专门注解其他的注解(在自定义注解的时候,需要使用到元注解):
- @Documented:指定被标注的注解会包含在javadoc中。
- @Retention: 指定注解的生命周期(源码、class文件、运行时)
@Retention(RetentionPolicy.CLASS)//仅class文件可以使用
@Retention(RetentionPolicy.RUNTIME)//运行期可以使用
@Retention(RetentionPolicy.SOURCE)//仅编译期可以使用
3.@Target:指定注解使用的目标范围(类、方法、字段等)
TYPE : 类、接口或enum声明
FIELD: 域(属性)声明
METHOD: 方法声明
PARAMETER: 参数声明
CONSTRUCTOR: 构造方法声明
LOCAL_VARIABLE:局部变量声明
ANNOTATION_TYPE:注释类型声明
PACKAGE: 包声明
4.@Inherited:指定子类可以继承父类的注解,只能是类上的注解,方法和字段的注解不能继承。即如果父类上的注解是@Inherited修饰的就能被子类继承。
四、注解的应用
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE,ElementType.FIELD,ElementType.METHOD,ElementType.CONSTRUCTOR})
public @interface MyAnnotation {
public String name();
public int val();
}
@MyAnnotation(name = "管理员信息", val = 1)
public class Admin {
@MyAnnotation(name = "管理员姓名", val = 2)
public String name;
@MyAnnotation(name = "管理员年龄", val = 3)
public int age;
@MyAnnotation(name = "管理员构造方法", val = 4)
public Admin() {
}
@MyAnnotation(name = "管理员自我介绍方法", val = 5)
public void say() {
System.out.println("我是管理员");
}
}
public static void main(String[] args)throws Exception {
Class c=Admin.class;
Field f1=c.getDeclaredField("name");
Field f2=c.getDeclaredField("age");
Constructor con=c.getConstructor();
Method m=c.getDeclaredMethod("say");
MyAnnotation ma0=(MyAnnotation) c.getAnnotation(MyAnnotation.class);
MyAnnotation ma1=f1.getAnnotation(MyAnnotation.class);
MyAnnotation ma2=f2.getAnnotation(MyAnnotation.class);
MyAnnotation ma3=(MyAnnotation) con.getAnnotation(MyAnnotation.class);
MyAnnotation ma4=m.getAnnotation(MyAnnotation.class);
System.out.println(ma0.name()+"---"+ma0.val());
System.out.println(ma1.name()+"---"+ma1.val());
System.out.println(ma2.name()+"---"+ma2.val());
System.out.println(ma3.name()+"---"+ma3.val());
System.out.println(ma4.name()+"---"+ma4.val());
}
五、通过自定义注解实现接口实现类注入
//声明自定义注解
@Retention(RUNTIME)
@Target(FIELD)
public @interface MyAnn {
public String val();
}
//不在showview里面实例化
public static void MyFac() {
try {
//获取要执行的类
Class c=Class.forName("com.woniuxy.crm.view.ShowView");
//通过属性名获取属性
Field f=c.getDeclaredField("userService");
//获取属性的注解
MyAnn ma=f.getAnnotation(MyAnn.class);
//根据注解的值进行加载
Class c1=Class.forName(ma.val());
//创建类的对象
Object o=c.newInstance();
//为注入的属性赋值
f.set(o, c1.newInstance());
}catch (Exception e) {
e.printStackTrace();
}
}
//属性通过注解赋值实现无需实例化注入对象
@MyAnn(val="com.woniuxy.crm.service.Impl.UserService")
public static IUserService userService;