注解的简单介绍以及自定义注解

    xiaoxiao2021-04-13  39

    注解的使用方法以及自定义注解

    注解的简单用法

    /* * 注解是给编译器看的 * 如下是复写的Object类的方法 * Override代表此方法是复写的 * 如果父类中没有此方法,会报编译错误 */ @Override public boolean equals(Object obj){ return super.equals(obj); } /* * 表示该方法已过时 */ @Deprecated public void add(){ } /* * 去掉由于没有使用泛型而出现的警告 */ @SuppressWarnings("rawtypes") public void doit(){ List list=new ArrayList<>(); System.out.println(list); }

    自定义注解

    新建一个注解类

    /** * @author Administrator * 使用注解可以替代配置文件,将原来配置文件中的信息 * 在注解中描述 */ public @interface Annotation1 { String name();//声明一个String属性 //声明一个枚举属性,并给出默认值 Gender gender() default Gender.FEMALE; Class cla();//声明一个类属性 //声明一个注解属性,这样可以嵌套数据 MyAnnotation2 my2(); //声明一个数组属性,不能这样写default new int[]; int [] arr() default {1,2,4}; //注解中不能使用集合类型属性 /* * Invalid type List for the annotation attribute Annotation1.ss; * only primitive type, String, Class, annotation, enumeration * are permitted or 1-dimensional arrays thereof */ //List ss(); }

    Annotation1中的注解属性MyAnnotation2

    public @interface MyAnnotation2 { String name(); }

    使用该注解类

    /* * 使用自定义annotation */ @Annotation1(name="zhangsan",gender=Gender.MALE,cla=String.class,my2=@MyAnnotation2(name="xxx")) public void doaa(){ }

    注解中名称为“value”的属性,可以直接赋值,但是这只是在注解中只有这一个属性的情况下

    public @interface MyAnnotation3 { String value(); } //使用MyAnnotation3 @MyAnnotation3("xxx") public void dobb(){ }

    使用注解替代配置文件,将原来配置文件中的信息在注解中描述

    存储信息的注解类

    /* * @Retention包含RetentionPolicy,通过它指定域 * RetentionPolicy.CLASS * 把注解记录在class文件中,jvm不会保留注解,这是默认值 * RetentionPolicy.RUNTIME * 把注解记录在class文件中,jvm会保留注解 * RetentionPolicy.SOURCE * 编译器直接丢弃这种策略注释 */ //下面四个是元Annotation,也就是修饰Annotation的Annotation //------------------------------------------- //定义了该Annotation被保留的时间(一定要在这里声明作用域,否则运行时不能得到该注解) @Retention(RetentionPolicy.RUNTIME) //这个是指定注解用于修饰类的哪个成员 @Target({ElementType.METHOD,ElementType.PACKAGE}) @Documented//被该注解修饰的注解类将被javadoc工具提取成文档 @Inherited//被它修饰的注解将具有继承性 //-------------------------------------------------------- public @interface DBInfoAnnotation { String url(); String username(); String pwd(); }

    在下面的类中使用上面的自定义注解(只是用来模拟,并没有真正连接数据库)

    public class DBConnect { @DBInfoAnnotation(url="jdbc:mysql://localhost:3306/test",username="root",pwd="123") public Connection getConnection(String url,String username,String pwd){ System.out.println(url); System.out.println(username); System.out.println(pwd); return null; } }

    使用反射获取注解中配置的信息,并执行getConnection方法

    public class Demo2 { public static void main(String[] args) throws Exception{ Class cla=DBConnect.class; //得到需要运行的方法 Method method= cla.getMethod("getConnection", String.class, String.class, String.class); DBInfoAnnotation di= method.getAnnotation(DBInfoAnnotation.class); String url=di.url(); String username=di.username(); String pwd=di.pwd(); method.invoke(cla.newInstance(), url,username,pwd); } }

    执行上面的demo,可以打印出DBConnect的getConnection方法使用 注解配置的信息

    使用注解将实体类传给方法或类属性供其使用

    实体类

    public class Person { private String name; private int age; public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } }

    传递该实体类的注解

    @Retention(RetentionPolicy.RUNTIME) public @interface InjectPerson { String name(); int age(); }

    操作该实体类的Dao

    public class PersonDao { @InjectPerson(name="laoli",age=23) private Person person; public Person getPerson() { return person; } @InjectPerson(name="laowang",age=23) public void setPerson(Person person) { this.person = person; } }

    —————通过注解将person传给方法

    /** * @author Administrator * 通过注解将person传给方法 */ public class Test { public static void main(String[] args) throws IntrospectionException, InstantiationException, IllegalAccessException, NoSuchFieldException, SecurityException, IllegalArgumentException, InvocationTargetException { //1.得到要注入的属性 PropertyDescriptor pd=new PropertyDescriptor("person", PersonDao.class); //2.得到要注入的属性需要的类型 Class cla= pd.getPropertyType();//person //3.得到创建属性需要的对象 Object person=cla.newInstance(); //4得到属性的写方法(set) Method setPerson=pd.getWriteMethod(); //5反射方法上声明的注解 InjectPerson inject= setPerson.getAnnotation(InjectPerson.class); //6得到注解上声明的信息,填充person对象 Method[] methods=inject.getClass().getMethods(); for(Method m:methods){ String methodName=m.getName(); try{ //如果没有该方法会抛出异常(methodName) Field f= Person.class.getDeclaredField(methodName); Object value= m.invoke(inject, null);//得到注解上配置的属性的值 f.setAccessible(true);//如果实体类中的成员变量为private,必须进行此操作 f.set(person, value); }catch(Exception e){ continue; } } //7把填充了数据的person通过setPerson方法整到personDao上 PersonDao dao=new PersonDao(); setPerson.invoke(dao, person);//执行personDao的setPerson方法 System.out.println(dao.getPerson().getName());//打印一下,测试是否成功获取 } }

    ————–通过注解将person传给属性

    /** * @author Administrator * 通过注解将person传给属性 */ public class Test2 { public static void main(String[] args) throws NoSuchFieldException, SecurityException, InstantiationException, IllegalAccessException, IntrospectionException { // TODO Auto-generated method stub //1.得到需要注入的属性 Field f=PersonDao.class.getDeclaredField("person"); //2得到属性需要的类型 Class cla=f.getType(); System.out.println(cla); //3创建person Person person=(Person) cla.newInstance(); //4反射属性的注解 InjectPerson inject=f.getAnnotation(InjectPerson.class); //5并用注解的信息填充person Method m[]=inject.getClass().getMethods(); for(Method ms:m){ String methodName=ms.getName(); //看person对象上有没有注解与之对应的属性 try{ //如果没有该方法会抛出异常(methodName) PropertyDescriptor pd=new PropertyDescriptor(methodName,Person.class); Method set=pd.getWriteMethod(); set.invoke(person, ms.invoke(inject, null)); }catch(Exception e){ continue; } } //6.把person赋给dao PersonDao dao=new PersonDao(); f.setAccessible(true); f.set(dao, person); System.out.println(dao.getPerson().getName()); }
    转载请注明原文地址: https://ju.6miu.com/read-669513.html

    最新回复(0)