模拟Spring---工厂模式和反射机制案例

  • 例如有配置文件stu.properties,存储在项目的src文件夹下,内容如下:
    class=sunny.reflect.Student name=rose gender=女 age=18
  • 根据配置文件信息创建一个学生对象。

模拟Spring---工厂模式和反射机制案例_第1张图片

 

public class Student {
    private String name;
    private int age;
    private String gender;

    public Student() {
    }

    public Student(String name, int age, String gender) {
        this.name = name;
        this.age = age;
        this.gender = gender;
    }

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

    public String getGender() {
        return gender;
    }

    public void setGender(String gender) {
        this.gender = gender;
    }

    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", age=" + age +
                ", gender='" + gender + '\'' +
                '}';
    }
}
  • 读取配置文件信息:创建Properties集合将配置文件信息放入集合中。
  • 创建字节输入流对象并关联源文件。
  • 下载文件。
  • 关闭流。
import java.io.FileInputStream;
import java.util.Properties;

public class ReflectDemo01 {
    public static void main(String[] args)throws Exception{
        //创建Properties集合
        Properties info = new Properties();
        //创建字节输入流对象并关联源文件
        FileInputStream fis = new FileInputStream("src/stu.properties");
        //下载文件
        info.load(fis);
        //关闭流
        fis.close();
        System.out.println(info);
    }
}


  •  我们想创建一个学生对象,不要直接去new它,因为在配置文件中有一个class对应一个类全名,我们根据class获得一个类全名字符串就可以得到一个class对象,则可以创建学生对象了。
  • 不过此时得到的name,age,gender都是默认值,接下来就需要利用反射机制对他们赋值。
import java.io.FileInputStream;
import java.util.Properties;

public class ReflectDemo01 {
    public static void main(String[] args)throws Exception{
        //创建Properties集合
        Properties info = new Properties();
        //创建字节输入流对象并关联源文件
        FileInputStream fis = new FileInputStream("src/stu.properties");
        //加载数据到集合中
        info.load(fis);
        //关闭流
        fis.close();

        //根据Class获得类全名字符串
        String str = info.getProperty("class");
        //根据类全名获得Class对象
        Class c = Student.class;
        //创建学生对象
        Object obj = c.newInstance();
        System.out.println(info);
        System.out.println(obj);
    }
}

 


  •  利用反射获得类所有的成员变量,遍历所有的成员变量。
  • 三个成员变量的名字相当于键,只需要获得成员变量的名字就可以给成员变量赋值了。
  • 获得成员变量名称,即Properties集合的键,根据键获得值就可以给对应的field赋值。
  • 给对象obj的成员变量赋值。
import java.io.FileInputStream;
import java.lang.reflect.Field;
import java.util.Properties;

public class ReflectDemo01 {
    public static void main(String[] args)throws Exception{
        //创建Properties集合
        Properties info = new Properties();
        //创建字节输入流对象并关联源文件
        FileInputStream fis = new FileInputStream("src/stu.properties");
        //加载数据到集合中
        info.load(fis);
        //关闭流
        fis.close();

        //根据Class获得类全名字符串
        String str = info.getProperty("class");
        //根据类全名获得Class对象
        Class c = Student.class;
        //创建学生对象
        Object obj = c.newInstance();
        System.out.println(info);
        //获得类的所有成员变量
        Field[] fields = c.getDeclaredFields();
        for (Field field : fields) {
            //获得成员变量名称
            String name = field.getName();
            //根据成员变量获得对应的值
            String value = info.getProperty(name);
            System.out.println("name="+name+",value="+value);
            //暴力反射
            field.setAccessible(true);
            //判断成员变量的类型
            Class type = field.getType();

            if(type == int.class){
                field.setInt(obj,Integer.parseInt(value));
            }else {
                //给对象obj的成员变量赋值
                field.set(obj,value);
            }

        }
        System.out.println(obj);
    }
}

 


扩展:根据不同的配置文件产生不同的对象(利用泛型)(模仿Spring框架)

假设还有一个Book文件的配置信息

public class Book {
    private String name;
    private double price;
    private String author;

    public Book() {
    }

    public Book(String name, double price, String author) {
        this.name = name;
        this.price = price;
        this.author = author;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public double getPrice() {
        return price;
    }

    public void setPrice(double price) {
        this.price = price;
    }

    public String getAuthor() {
        return author;
    }

    public void setAuthor(String author) {
        this.author = author;
    }

    @Override
    public String toString() {
        return "Book{" +
                "name='" + name + '\'' +
                ", price=" + price +
                ", author='" + author + '\'' +
                '}';
    }
}
import java.io.FileInputStream;
import java.lang.reflect.Field;
import java.util.Properties;

public class ReflectDemo01 {
    public static void main(String[] args)throws Exception{
        Student stu = creatObject("src/stu.properties");
        Book book = creatObject("src/book.properties");
        System.out.println(book);
        System.out.println(stu);
    }
    public static T creatObject(String file)throws Exception{
        //创建Properties集合
        Properties info = new Properties();
        //创建字节输入流对象并关联源文件
        FileInputStream fis = new FileInputStream(file);
        //加载数据到集合中
        info.load(fis);
        //关闭流
        fis.close();

        //根据Class获得类全名字符串
        String str = info.getProperty("class");
        //根据类全名获得Class对象
        Class c = Class.forName(str);
        //创建对象
        Object obj = c.newInstance();
        //System.out.println(info);
        //获得类的所有成员变量
        Field[] fields = c.getDeclaredFields();
        for (Field field : fields) {
            //获得成员变量名称
            String name = field.getName();
            //根据成员变量获得对应的值
            String value = info.getProperty(name);
            System.out.println("name="+name+",value="+value);
            //暴力反射
            field.setAccessible(true);
            //判断成员变量的类型
            Class type = field.getType();

            if(type == int.class){
                field.setInt(obj,Integer.parseInt(value));
            }else if(type == double.class){
                field.setDouble(obj,Double.parseDouble(value));
            }else {
                //给对象obj的成员变量赋值
                field.set(obj,value);
            }

        }
        return (T)obj;
    }
}
  •  java.lang.ClassNotFoundException: sunny.reflect.Student  :运行发现报错了,这是因为stu.properties和book.properties两个配置文件里面的信息不小心出现了空格,那么在创建对象的时候是加了空格的,这样就找不到对象对应的类,出现报错的情况,为了防止这种情况的发生,我们可以在获得类全名字符串的时候加上trim方法,消除前后的空格。
  • 错误原因: 

  • 正确代码(加上trim) :

模拟Spring---工厂模式和反射机制案例_第2张图片


  • 案例正确代码最终版:
import java.io.FileInputStream;
import java.lang.reflect.Field;
import java.util.Properties;

public class ReflectDemo01 {
    public static void main(String[] args)throws Exception{
        Student stu = creatObject("src/stu.properties");
        Book book = creatObject("src/book.properties");
        System.out.println(book);
        System.out.println(stu);
    }
    public static T creatObject(String file)throws Exception{
        //创建Properties集合
        Properties info = new Properties();
        //创建字节输入流对象并关联源文件
        FileInputStream fis = new FileInputStream(file);
        //加载数据到集合中
        info.load(fis);
        //关闭流
        fis.close();

        //根据Class获得类全名字符串
        String str = info.getProperty("class").trim();
        //根据类全名获得Class对象
        Class c = Class.forName(str);
        //创建对象
        Object obj = c.newInstance();
        //System.out.println(info);
        //获得类的所有成员变量
        Field[] fields = c.getDeclaredFields();
        for (Field field : fields) {
            //获得成员变量名称
            String name = field.getName();
            //根据成员变量获得对应的值
            String value = info.getProperty(name);
            System.out.println("name="+name+",value="+value);
            //暴力反射
            field.setAccessible(true);
            //判断成员变量的类型
            Class type = field.getType();

            if(type == int.class){
                field.setInt(obj,Integer.parseInt(value));
            }else if(type == double.class){
                field.setDouble(obj,Double.parseDouble(value));
            }else {
                //给对象obj的成员变量赋值
                field.set(obj,value);
            }

        }
        return (T)obj;
    }
}

 模拟Spring---工厂模式和反射机制案例_第3张图片

你可能感兴趣的:(反射)