Spring Ioc(控制反转)、DI(依赖注入)的理解,写一个简易的spring容器

这篇博客主要是对spring的相关概念进行通俗易懂的解释,以及用自己的代码写一个spring简易容器,实现类似于spring的功能。

Ioc概念

Ioc(控制反转):原本我们创建一个对象是用new关键字,我们可以很明确的知道自己要创建一个什么样的对象,而现在我们把创建对象的工作交给了spring来处理。也就是我们把控制权交给了别人,spring返回什么东西我们是不知道的。

DI概念

指Spring创建对象的过程中,将对象依赖的属性(简单值,集合,对象)通过配置的方式进行设值。

写一个简易spring容器

首先,我们应该了解Ioc带来的好处,就是帮助项目降低耦合。

解耦思路:
1.使用反射来创建对象,避免使用new关键字。
2.通过读取配置文件来获取创建对象的全限定名。

根据上面的思路,我们来写一个简易容器。

一、定义几个我们常用的实体类

//Student类
public class Student {
    private String name;
    private Integer age;
    public Student(){}
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public Integer getAge() {
        return age;
    }
    public void setAge(Integer age) {
        this.age = age;
    }
}
//User类
public class User {
    private  int id;
    private  String name;

    public int getId() {
        return id;
    }
    public void setId(int id) {
        this.id = id;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    @Override
    public String toString() {
        return "User{" +
                "id=" + id +
                ", name='" + name + '\'' +
                '}';
    }

二、定义枚举(用于判断单例模式和原型模式)

//SINGLETON代表单例模式,MORE代表原型模式,也就是多例
public  enum Model{
    SINGLETON,MORE;
}

三、application.properties核心配置文件

#把两个实体类的全限定名写入,类似于配置bean
user=pojo.User
student=pojo.Student

四、写核心类
我们使用spring容器时,是定义ApplicationContext来创建容器,那我们自己写一个类
MyApplicationContext。

public class MyApplicationContext {
//配置文件名字
    private String propertiesName;
   //定义map集合
    private static Map<String,Object> map=new HashMap();

//带参数构造函数
    public MyApplicationContext(String propertiesName){
        this.propertiesName=propertiesName;
        //读取配置文件
        InputStream inputStream=TextProperties.class.getClassLoader().getResourceAsStream(propertiesName);
        //创建properties对象
        Properties properties=new Properties();
        //关联文件
        try {
            properties.load(inputStream);
        } catch (IOException e) {
            e.printStackTrace();
        }
        
//获取配置文件中所有的key值
        Set<Object> keys = properties.keySet();
        Iterator<Object> iteratorKeys = keys.iterator();
        
        //获取配置文件中所有的value
        Collection<Object> values = properties.values();
        Iterator<Object> iteratorValues = values.iterator();
        
        //遍历,将bean的名字和对象保存进map集合,这样实现单例模式
        while (iteratorKeys.hasNext()){
            Class c = null;
            try {
                c = Class.forName((String) iteratorValues.next());
                //利用反射创建对象
                map.put((String)iteratorKeys.next(),c.newInstance());
            }
            catch (ClassNotFoundException e) {
                e.printStackTrace();
            }
            catch (InstantiationException e) {
                e.printStackTrace();
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            }
        }
    }


    //多实例创建对象,这样可以保证每次创建的对象都不是相同的
    private Object createMore(String beanId)throws Exception{
        //读取配置文件
        InputStream inputStream=TextProperties.class.getClassLoader().getResourceAsStream(this.propertiesName);
        //创建properties对象
        Properties properties=new Properties();
        //关联文件
        try {
            properties.load(inputStream);
        } catch (IOException e) {
            e.printStackTrace();
        }
        String property = properties.getProperty(beanId);
            Class c = Class.forName(property);
            return c.newInstance();
    }

//getBean方法,默认使用单实例
public Object getBean(String beanId)throws Exception{
        return getBean(beanId,Model.SINGLETON);
    }

//getBean重载方法,可以选择单例模式或者原型模式
    public Object getBean(String beanId,Model e)throws  Exception{
        Object o="";
        //switch进行选择
        switch (e){
            case SINGLETON:
               o= map.get(beanId);
                break;
            case MORE:
               o= this.createMore(beanId);
                break;
        }
        return o;
    }
}

测试

  public static void main(String[] args)throws  Exception {
        MyApplicationContext myApplicationContext=new MyApplicationContext("application.properties");
        User user =(User) myApplicationContext.getBean("user", Model.MORE);
        User user1 = (User) myApplicationContext.getBean("user", Model.MORE);
        User user2 =(User) myApplicationContext.getBean("user");
        User user3 =(User) myApplicationContext.getBean("user");
        System.out.println("单例模式,判断容器获取的对象是否为同一个:"+(user2==user3));
        System.out.println("原型模式,判断容器获取的对象是否为同一个:"+(user==user1));
    }

运行结果:
在这里插入图片描述
根据结果,我们写的容器简单实现了spring容器的一些功能。
包括选择创建单例模式还是原型模式。

欢迎大家一起讨论学习,学无止境加油!

猜你喜欢

转载自blog.csdn.net/gtahxm1314/article/details/107983251