Spring的IOC浅析

概述

spring是一款 轻量级、 提供 容器化依赖注入、和 AOP面向切面编程的实现的框架。

依赖注入:

传统的创建对象都需要手动创建,那么会使我们修改不方便,比如,我们可能会需要切换实现类,或者挪动类的位置,比如:

public class Main{
    public class List<Integer> list = new ArryayList<>();
}

// 如果我们需要切换List的实现类,那么必须手动修改为如下
public class Main{
    public class List<Integer> list = new LinkedList<>();
}

// 这样叫做有侵入性的代码修改方式,表示我们需要重新修改源代码,以适应新的要求

传统的方式的 需要修改源代码 而且数量庞大的话很麻烦,比如:我们有一百个引用List的地方,都想切换,那么我们怎么做才能实现较好的替换呢?可以用个 工厂

其实我个人来说,很多人,包括我自己,没接触过过设计模式的话,很难去想到工厂是啥?

但是:我们基本都能想到,需要加一个中间层,让所有的获取对象引用这个对象或者把这个对象放到一个容器里,类似这样

最简单版本,所有的类都引用这个类的list对象,只需要修改这一个类,别的类就可以修改了。:

public class ObjectPool {
    // 单例
    public static List<Integer> list = new ArrayList<>();
}

public class ObjectPool {
    // 非单例
    public static List<?> getList() {
        return new ArrayList<>();
    }
}

n个不同的接口就需要写n个属性或者写n个方法,不好维护。

那么可以改成这样,一劳永逸:

// 所有的对象获取这个对象,默认单例
public class ObjectPool {
    // 记录类对应的对象
    public static Map<Class<?>, Object> objectMap = new HashMap<>();
    // 记录类对应的实现类
    public static Map<Class<?>, Class<?>> implMap = new HashMap<>();
    
    // 根据类获取对象
    public static <T> T getObject(Class<T> cls) {
        T res;
        
        // 如果已经实例化过,直接获取
        res = objectMap.get(cls);
        
        // 未实例化过,根据实现类创建对象,返回对象
        if (res == null) {
            Class<?> implClass = implMap.get(cls);
            
            // 如果没有指定实现类,那么就采用原来的类
            if (implClass == null) {
                implClass = cls;
            }
            
            // 创建对象
            Object obj = implClass.getConstructor().newInstance();
            // 把对象放入map,以便后续使用
            objectMap.put(cls, obj);
            
            res = (T)obj;
        }
        
        return res;
    }
    
    // 设置实现类
    public static void setImpl(Class<?> cls, Class<?> implCls) {
        implMap.put(cls, implCls);
    }
}

然后,我们如果需要改动,可以直接修改该类的实现类。用别的方式来指定实现类

如果我们需要对于每一个对象都创建一个新对象呢?

上面的代码简单修改就可以了

// 所有的对象获取这个对象,默认单例
public class ObjectPool {
    // 记录类对应的实现类
    public static Map<Class<?>, Class<?>> implMap = new HashMap<>();
    
    // 根据类获取对象
    public static <T> T getObject(Class<T> cls) {
        T res;
        
        // 获取实现类
        Class<?> implClass = implMap.get(cls);
            
        // 如果没有指定实现类,那么就采用原来的类
        if (implClass == null) {
            implClass = cls;
        }
        
        // 创建对象
        Object obj = implClass.getConstructor().newInstance();

        res = (T)obj;
        
        return res;
    }
    
    // 设置实现类
    public static void setImpl(Class<?> cls, Class<?> implCls) {
        implMap.put(cls, implCls);
    }
}

其实可以组合成这样:

// 所有的对象获取这个对象,默认单例
public class ObjectPool {
    // 是否为单例模式
    public static boolean isSingleton = true;
    // 记录类对应的对象
    public static Map<Class<?>, Object> objectMap = new HashMap<>();
    // 记录类对应的实现类
    public static Map<Class<?>, Class<?>> implMap = new HashMap<>();
    
    // 根据类获取对象
    public static <T> T getObject(Class<T> cls) {
        T res;
        
        if (isSingleton) {
            // 如果已经实例化过,直接获取
        	res = objectMap.get(cls);
        } 
        
        // 未实例化过,根据实现类创建对象,返回对象
        if (res == null) {
            Class<?> implClass = implMap.get(cls);
            
            // 如果没有指定实现类,那么就采用原来的类
            if (implClass == null) {
                implClass = cls;
            }
            
            // 创建对象
            Object obj = implClass.getConstructor().newInstance();
            if (isSingleton) {
                // 把对象放入map,以便后续使用
            	objectMap.put(cls, obj);
            }
            
            res = (T)obj;
        }
        
        return res;
    }
    
    // 设置实现类
    public static void setImpl(Class<?> cls, Class<?> implCls) {
        implMap.put(cls, implCls);
    }
    
    // 设置是否为单例模式
    public static vodi setSingleton(boolean isSingleton) {
        this.isSingleton = isSingleton;
    }
}

上面的实现是一种简单的实现,可以看到,我们的改动减小到了一个类中。

上面的代码还是要修改类,如果可以用另一种方式来描述就好了,xml就是spring选用的方式。

用xml描述类的实现关系,修改只需要修改xml即可,代码无需修改就可以切换到相同接口的另一个实现类。

后续我发现了问题,在于这种方式只能确定一种类型的实现,如果项目中有部分List想要使用ArrayList,有一部分想要使用LinkedList我们又该如何使用IOC容器来控制呢?

所以,我们的IOC的Map实现可以修改为Map<String id, Class<?> cls>

这样我们可以对于不同的需要list的场景按照ID进行分类,从而控制。所以,代码整体类似,不过需要修改的就是Map的结构罢了。

(不过为了方便,也可以针对没有传入id的,按照默认的类型首字母小写来方便不写id)

这种IOC:(使用容器帮助创建对象)的好处在于

  1. 低耦合
  2. 方便修改

关于工厂,就是工厂模式,也是用来根据传入类型的不同来创建对象的。我觉得它的不好处也在于,如果需要控制的类太多,要写n个工厂,这种方式可以不写很多工厂。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值