java用Annotation注入到成员Bean对象

java用Annotation注入到成员Bean对象

在使用一些java框架的时候,经常看到一些注解,而且使用注解之后就可以免去一些xml的繁琐配置,本文记录如何通过注解获得成员Bean对象。

一、首先定义Bean

class Person {
    private String username;
    private int age;

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    @Override
    public String toString() {
        return "Person{" +
                "username='" + username + '\'' +
                ", age=" + age +
                '}';
    }
}

二、编写和bean一致的注解

// Retention为元注解(注解的注解),这里设置了注解的生命周期为运行时
// 默认情况下,RetentionPolicy为CLASS,字节码注释一般给IDE或者一些工具看的,不能在运行时读取值
// 还有一种为SOURCE,在编译时交给编译器处理,比CLASS时间更早
@Retention(RetentionPolicy.RUNTIME)
@interface InjectPerson {
    String username();
    int age();
}

三、编写DAO

我们在这里注入对象

class PersonDao {
    private Person person;

    public Person getPerson() {
        return person;
    }

    @InjectPerson(username = "Nike", age = 20)
    public void setPerson(Person person) {
        this.person = person;
    }
}

四、利用反射生成对象并读取注解装配对象

public class TestDemo2 {

    public static void main(String[] args) {
        try {
            // 获取通过反射创建person
            PropertyDescriptor descriptor = new PropertyDescriptor("person", PersonDao.class);
            Person person = (Person) descriptor.getPropertyType().newInstance();
            
            // 得到person成员对象的setter
            Method method = descriptor.getWriteMethod();

            // 得到setter的注解
            Annotation annotation = method.getAnnotation(InjectPerson.class);

            // 得到注解的值并装配对象
            Method[] methods = annotation.getClass().getMethods();
            for (Method m : methods) {
                String name = m.getName();
                for (Field field : person.getClass().getDeclaredFields()) {
                    // 匹配对应字段
                    if (name.equals(field.getName())) {
                        // 读取annotation中各个属性的值 annotation.age(), 以及annotation.name()
                        Object value = m.invoke(annotation, null);
                        
                        // 得到setter
                        PropertyDescriptor attributeDescriptor = new PropertyDescriptor(name, Person.class);
                        Method setPersonMethod = attributeDescriptor.getWriteMethod();
                        
                        // 装配
                        setPersonMethod.invoke(person, value);
                    }
                }
            }

            // 在把装配好的person注入到dao
            PersonDao personDao = new PersonDao();
            method.invoke(personDao, person);
            
            System.out.println(personDao.getPerson());
            
        } catch (IllegalAccessException |
                IntrospectionException |
                InstantiationException |
                InvocationTargetException e) {
            e.printStackTrace();
        }
    }
}

五、小结

总体思想就是:

  1. 得到想要注解的对象
  2. 得到该对象的setter
  3. 读取setter上annotation上的值并注入到对象上
  4. 把装配完之后的对象赋给所有者

本来一直以为注解只是给编译器检查代码用的,没想到利用反射能做这么多事,这种惊叹和博主刚接触C++的宏编程时类似,感觉奇妙无比。

posted @ 2019-06-21 14:34  潇雨危栏  阅读(535)  评论(0编辑  收藏  举报