新建一个注解类
/** * @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()); }