用Annotation,内省技术给一个对象注入属性

xiaoxiao2021-02-28  55

首先声明两个重要概念 1.反射 反射就是在运行状态把 Java 类中的各种成分映射成相应相应的 Java 类,可以动态得获取所有的属性以及动态调用任意一个方法。这里特被强调是任意类 2.内省 内省是通过反射的方式操作JavaBean的属性,jdk提供了PropertyDescription类来操作访问JavaBean的属性,Beantils工具基于此来实现。这里强调的是JavaBean(一种只有getter和setter方法的Java类,这是一种规范)而非任意类。因为PropertyDescription只有 getReadMethod() 来获得应该用于读取属性值的方法。 Method getWriteMethod() 来获得应该用于写入属性值的方法。 两个方法。

下面交代我们的正题的思路 我们的目的是用注解(一种可以理解为系统配置的技术)的方式来直接给属性(在这里是我们的一个自定义的对象)赋值。 我们分为以下的步骤(在此特别声明我们的这个对象在另一个类中充当Field,比如说一个person对象在另一个类中充当一个字段) **1.用内省技术得到字段对象类型,并实例化(比如说得到了这个字段是属于Person类,然后实例化一个Person) 2.用反射技术得到注解中的信息 3.将注解中的信息整到这个字段上(在这里使用的也是内省技术) 4.测试这个字段的属性值来确认我们是否成功**

首先声明我们的JavaBean

package objectannotation; 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; } }

接下来说明我们的注解类和注解信息

package objectannotation; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; @Retention(RetentionPolicy.RUNTIME) public @interface InjectPerson { String name() default "hyl"; int age() default 15; }

然后在声明我们的JavaBean在那个类中充当Field

package objectannotation; public class PersonDao { @InjectPerson(name="hyl",age=23) Person person = new Person(); public Person getPerson(){ return person; } @InjectPerson(name="zhuliu",age=32) public void setPerson(Person person){ this.person = person; } }

从这个类我们可以看出我们要注入的地方可以有两个 一个是 **@InjectPerson(name=”hyl”,age=23) Person person = new Person();**

另一个是 @InjectPerson(name=”zhuliu”,age=32) public void setPerson(Person person){ this.person = person; }

接下来我们就来做两个测试将注解中的信息整到person字段上或者是person参数上,并且进行检验

测试1,将注解信息整到person字段上

package objectannotation; import java.beans.IntrospectionException; import java.beans.PropertyDescriptor; import java.lang.reflect.Field; import java.lang.reflect.Method; public class Test2 { public static void main(String[] args) throws NoSuchFieldException, SecurityException, InstantiationException, IllegalAccessException { //1.得到要注入的实例与写方法 //得到要注入的属性的描述(是那个类的那个方法或字段想注入) Field f = PersonDao.class.getDeclaredField("person");//与getField不同他得到的是任意字段而非只有public //得到要注入的对象的类型 Class clazz = f.getType(); //创建一个实例 Person person = (Person) clazz.newInstance(); //2.得到想要注入的对象的注解信息 //反射出属性上面的注解 InjectPerson inject = f.getAnnotation(InjectPerson.class); Method[] methods = inject.getClass().getMethods(); //得到注解声明的信息来填充对象 for(Method m : methods){ String name = m.getName(); try { PropertyDescriptor pd = new PropertyDescriptor(name,Person.class);//得到Person类中的名字为name的属性 Method set = pd.getWriteMethod(); //用指定对象指定参数去调用这个方法 set.invoke(person,m.invoke(inject, null)); } catch (Exception e) { continue; } } //3.用填充过后的对象来一些方法 PersonDao pdao = new PersonDao(); f.setAccessible(true); f.set(pdao, person); System.out.println(pdao.getPerson().getName());//zhuliu } }

2.测试1,将注解信息整到person参数上

package objectannotation; import java.beans.IntrospectionException; import java.beans.PropertyDescriptor; import java.lang.reflect.Field; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; public class Test { public static void main(String[] args) throws IntrospectionException, InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException { //得到要注入的属性描述在这里是person PropertyDescriptor pd = new PropertyDescriptor("person",PersonDao.class); //得到注入属性需要的类型 Class clazz = pd.getPropertyType(); //得到创建属性需要的对象 Object person = clazz.newInstance(); //得到属性的写方法 Method setPerson = pd.getWriteMethod(); //反射出方法上面的注解 InjectPerson inject = setPerson.getAnnotation(InjectPerson.class); //得到注解声明的信息填充person Method[] methods = inject.getClass().getMethods(); for(Method m : methods){ String name = m.getName(); try { /*Field field = Person.class.getDeclaredField(name); 拿到对应的方法的注解的值 Object value = m.invoke(inject,null); field.setAccessible(true); field.set(person, value);*/ PropertyDescriptor pd1 = new PropertyDescriptor(name,Person.class);//得到Person类中的名字为name的属性 Method setmethod = pd1.getWriteMethod(); setmethod.invoke(person, m.invoke(inject, null)); } catch (Exception e) { continue; } } //把填充了信息的person整到PersonDao上面去 PersonDao pdao = new PersonDao(); //Person的set方法进行执行 setPerson.invoke(pdao,person); System.out.println(pdao.getPerson().getName());//zhuliu } }

在以上的注释的代码块中是用反射的方法来操作JavaBean,由此可见操作JavaBean还是用内省比较简洁。

在此特别致敬方立勋老师!

转载请注明原文地址: https://www.6miu.com/read-37132.html

最新回复(0)