欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

Java底层技术之反射机制

程序员文章站 2022-06-17 19:07:34
一、反射机制的应用之一——IOC(控制权反转)和DI(依赖注入)IOC和DI:控制反转(Inversion of Control,缩写为IoC),是面向对象编程中的一种设计原则,可以用来减低计算机代码之间的耦合度。其中最常见的方式叫做依赖注入(Dependency Injection,简称DI),还有一种方式叫“依赖查找”(Dependency Lookup)。通过控制反转,对象在被创建的时候,由一个调控系统内所有对象的外界实体将其所依赖的对象的引用传递给它。也可以说,依赖被注入到对象中(来自百度)。I...

一、反射机制的应用之一

——IOC(控制权反转)和DI(依赖注入)

IOC和DI:控制反转(Inversion of Control,缩写为IoC),是面向对象编程中的一种设计原则,可以用来减低计算机代码之间的耦合度。其中最常见的方式叫做依赖注入(Dependency Injection,简称DI),还有一种方式叫“依赖查找”(Dependency Lookup)。通过控制反转,对象在被创建的时候,由一个调控系统内所有对象的外界实体将其所依赖的对象的引用传递给它。也可以说,依赖被注入到对象中(来自百度)。IOC简单来理解就是把对象的创建权交给另外的一个类,而不是通过自己自己来创建对象,而DI则是在创建对象的时候,给对象注入一些属性值。一般用于框架的设计,用到的是反射的技术,反射的相关知识可以看我的上一篇博客。下面看看一个一个应用:分别有三个类Person、Dog、IOC、Animal、TestMain。
附图解释:Java底层技术之反射机制类Person:


package IOC;

/**
 * person这个类就是简单的容器,用来存储每个人的信息
 * 其中的特点就是每个属性都是私有的
 * 只能通过get方法来获取
 */
public class Person implements Animal{
    private String name;
    private String sex;
    private Integer age;//为什么不使用int,而是使用int对应的包装类,原因是:使用Integer更安全,具体解释在资料中解释

    @Override
    public String toString() {
        StringBuilder personString = new StringBuilder();
        personString.append("{姓名:"+this.name);
        personString.append(",性别:"+this.sex);
        personString.append(",年龄:"+this.age+"}");
        return personString.toString();
    }

    public Person() {//无参构造方法
    }

    public Person(String name, String sex, Integer age) {//含参构造方法
        this.name = name;
        this.sex = sex;
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public String getSex() {
        return sex;
    }

    public Integer getAge() {
        return age;
    }

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

    public void setSex(String sex) {
        this.sex = sex;
    }

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

    @Override
    public void eat() {
        System.out.println("这是人类的吃饭方法。。。。。");
    }
}



类Dog:

package IOC;
/**
 * Dog这个类就是简单的容器,用来存储每个狗的信息
 * 其中的特点就是每个属性都是私有的
 * 只能通过get方法来获取
 */
public class Dog implements Animal{
    private String name;
    private String color;

    public Dog() {
    }

    public Dog(String name, String color) {
        this.name = name;
        this.color = color;
    }

    public String getName() {
        return name;
    }

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

    public String getColor() {
        return color;
    }

    public void setColor(String color) {
        this.color = color;
    }
    public void eat(){
        System.out.println("这是狗的吃饭方法。。。。");
    }

    @Override
    public String toString() {
        StringBuilder dogToString  = new StringBuilder("{"+"The dog name:"+this.name+",Color:"+this.color+"}");
        return dogToString.toString();
    }
}

类Animal:

 package IOC;

public interface Animal {
    public abstract void eat();//定义规则:也就是把人类和狗类相同的属性或者方法抽象出来
}
类Ico:
package IOC;

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.Scanner;

/**
 - 这个类只负责类的创建和属性的注入,也就是IOC和DI的设计思想,将对象的创权交给别人
 - 用户拿到对象的时候,属性已经注入好了
 */
public class Ioc {
    /*
    设计一个方法:
	给定一个字符串,返回一个对象,同时并给返回的对象中的属性值赋值。(采用的是IOC控制反转的设计思想,DI依赖注入)
	例如:给定一个String字符串得到一个对象Person,或者是其他的对象。
	设计过程:为了保证方法的通用性,选择Object
	是否需要返回值:返回值是用户需要的那个对象,根据参数的传入进行选择
	是否需要参数:需要参数,参数是用户给定的类,给定什么类,就返回该类的对象,并且注入属性值
     */
    public Object getTarget(String className){//获取目标对象
        Scanner input = new Scanner(System.in);
        System.out.println("请给"+className+"类的对象赋值");
        Object obj = null;
        try {
            //1、获取参数对应的类
            Class clazz = Class.forName(className);
            //2、用获取到的类创建对象,获取到的是一个Object类型的对象
             obj = clazz.newInstance();
            //3、将该对象的属性注入一些值
            //通过什么进行赋值------>类中的set方法,同时还需要获取属性
            //set方法的命名规范:set+属性名(其中属性名的第一个字母大写)
                //1)获取类中的属性和属性名
                Field[] fields = clazz.getDeclaredFields();
                //2)手动拼串,拼接出类中的set方法
                for(Field field : fields){//增强的for循环,将类中的每一个set方法都拼接出来
                    //获取属性名
                    String fieldName = field.getName();
                    //将属性的第一个字母变成大写的
                    String first = fieldName.substring(0,1).toUpperCase();
                    //截取除了第一个字母以后的字符串
                    String ends = fieldName.substring(1);
                    //拼接
                    StringBuilder setMethodName = new StringBuilder("set");
                    setMethodName.append(first);
                    setMethodName.append(ends);
                    //获取每个属性的类型
                    Class fieldClass = field.getType();
                    //通过处理好的set方法名找寻类中set方法
                    Method setMethod = clazz.getMethod(setMethodName.toString(),fieldClass);//第二个参数是属性的类型
                    //获得set方法后就可以开始进行属性值的注入了
                    System.out.println("请给"+fieldName+"属性赋值");
                    String value = input.nextLine();
                    /*
                    属性的值是接受过来的,通过Scanner接收得到的,全部都是String类型的
                    如何将所有带有String类型的值转化成属性类型的值
                    基本类型都有带String的构造方法,可以利用包装类带String构造方法的处理
                     */
                    Constructor constructor = fieldClass.getConstructor(String.class);
                    setMethod.invoke(obj,constructor.newInstance(value));
                }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return obj;
    }
}

二、 代码都准备好了,下面就测试试试吧:
测试类TestMain:

public class testMain {
    public static void main(String[] args) {
       Ioc ioc = new Ioc();
//       Object obj = ioc.getTarget("IOC.Dog");
//       System.out.println(obj);
       Object obj =  ioc.getTarget("IOC.Person");
       System.out.println(obj);
    }
}

继续来图证明:
Java底层技术之反射机制
Java底层技术之反射机制有图有证据,感谢各位码友交流。。。。。

本文地址:https://blog.csdn.net/qq_45095925/article/details/110008181