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

首先声明两个重要概念
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还是用内省比较简洁。

在此特别致敬方立勋老师!
这里写图片描述

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Elong_Hu

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值