一文理解Spring依赖注入与控制反转

Spring是什么

Spring是一个以IoC(Inversion of Control,控制反转)和AOP(Aspect OrientedProgramming)为内核的框架,本篇文章的话只会涉及到IoC相关的内容,而AOP的内容会在后续的文章中解释。框架就是人们在开发过程中发现有很多的技术和过程的重复性是非常大的,所以开发出一系列的框架技术来更加方便的搭建出相应的结构(骨架)与功能。

IoC(控制反转)和DI(依赖注入)的关系

其实这两个东西都是在讲一个概念,只不过是从不同的方面来阐述罢了,他们的本质是没有什么区别的。

IoC(控制反转)

IoC是Inversion of Control的缩写,简单来说的话就是在我们传统的面向对象的编程方式里我们需要实例对象的话,是需要我们自己主动的去 new 创建的,而Spring的控制反转就是,我们不再需要自己去new实例对象了,我们把实例对象的创建交给了Spring来执行,当我们需要实例对象时,只需要让Spring的IoC容器给我们即可。也就是控制权从我们自己手里转变到了Spring的手里。
举个例子:当我们创建了对象A和对象B,这时B对象运行到某一个时间需要使用(依赖)到A对象,而这时我是需要主动创建A对象的依赖的,否则我们将无法编译通过(这时候的控制权都是在程序也就是我们自己手中);但是当我们使用了Spring的IoC容器把对象B依赖的对象A的创建交给了Spring创建,当我们需要时就只需要向Spring的容器拿取相应的对象依赖即可。由主动的行为变为了被动的接受。(通过Spring的IoC控制反转,也让程序的耦合程度得到了一定程度的降低)
SpringIoC

DI(依赖注入)

DI是Dependency Inject的缩写,其实他和控制反转是在讲一个东西,只不过他是在程序的角度来讲的;对于传统的程序来说,依赖的对象需要自己主动的创建,而对于Spring的依赖注入来说,程序就是被动的被Spring容器注入了依赖对象。

下面用一个例子来解释Spring的IoC和DI的工作机制

例子我们以用户User,工具tools和work来演示,用户需要使用产品,也就是需要依赖产品对象。

传统的方式如何实现

对于传统方式,也就是远古时期我们的人类想要完成工作的话是需要是需要自己动手创造工具的,没有工具的话就无发完成相应的工作,所以我们就需要主动的创建相应的tools依赖,才可以完成工作。对于依赖的控制也是在程序自身。而这样的方式程序的耦合是非常强的,这种编译期的耦合是我们要避免的。

/**
 * 工具类
 */
public class Tools {
	// 工具类中的方法
    public  void doWork(){
        System.out.println("人使用工具完成工作");
    }
}

/**
 * 人类
 */
public class User {
	// 人依赖工具类,需要使用工具完成工作,主动创建依赖对象
    private Tools tools = new Tools();
    public void  doWork(){
        tools.doWork();
    }
}

/**
 * 工作类
 */
public class Work {
    public static void main(String[] args) {
    	// 我们可以看出控制权在程序本身,而且耦合非常强
		User user = new User();
		user.doWork();
    }
}

传统方式

工厂模式改造

经过时代的发展,我们已经来到了近代,人类可以自己建工厂来生产工具,而不是每次都是自己来造工具了。我们使用自己写的工厂类来改造上面的例子,我们把User类依赖的Tools类的创建交给我们自己写的工厂类来创建(这里就已经实现了控制反转了)对于依赖对象的控制权已经由程序本身交由了直接写的工厂类来创建了。通过这种第三方的方式也降低了程序的耦合性。

// 这是工厂类需要加载的配置文件bean.properties
tools=com.my.Tools
user=com.my.dao.User

/**
 * 一个创建Tools对象的工厂(后面我们会发现他其实就是创建Bean的工厂,Bean也被称为可复用组件)
 */

public class ToolsFactory {
    //定义一个Properties对象
    private static Properties props;

    //定义一个Map,用于存放我们要创建的对象。我们把它称之为容器
    private static Map<String,Object> beans;

    //使用静态代码块为Properties对象赋值
    static {
        try {
            //实例化对象
            props = new Properties();
            //获取properties文件的流对象,并且放入哈希表中
            InputStream in = ToolsFactory.class.getClassLoader().getResourceAsStream("bean.properties");
            props.load(in);
            //实例化容器
            beans = new HashMap<String,Object>();
            //取出配置文件中所有的Key
            Enumeration keys = props.keys();
            //遍历枚举
            while (keys.hasMoreElements()){
                //取出每个Key
                String key = keys.nextElement().toString();
                //根据key获取value
                String beanPath = props.getProperty(key);
                //反射创建对象
                Object value = Class.forName(beanPath).newInstance();
                //把key和value存入容器中
                beans.put(key,value);
            }
        }catch(Exception e){
            throw new ExceptionInInitializerError("初始化properties失败!");
        }
    }

    /**
     * 根据bean的名称获取对象
     * @param beanName
     * @return
     */
    public static Object getBean(String beanName){
        return beans.get(beanName);
    }
}

/**
 * 工具类
 */
public class Tools {
	// 工具类中的方法
    public  void doWork(){
        System.out.println("人使用工具完成工作");
    }
}

/**
 * 人类
 */
public class User {
	// 人依赖工具类,需要使用工具完成工作,被动接受工厂创建依赖对象
    private Tools tools = (Tools) ToolsFactory.getBean("tools");
    public void  doWork(){
        tools.doWork();
    }
}

/**
 * 工作类
 */
public class Work {
    public static void main(String[] args) {
    	// 到这程序的耦合性就降低很多了,至少编译器耦合已经解决了
    	User user = (User) ToolsFactory.getBean("user");
		User user = new User();
		user.doWork();
    }
}

工厂类

Spring来管理

到达现代之后,我们工厂也不需要自己建了,我们可以直接使用创建好的Spring来创建我们需要的工具用来完成工作。而Spring是通过Beans来管理相应的实例的,我们可以把需要创建的实例对象通过Bean来配制到Spring中,让Spring的IoC容器来创建相应的对象,并注入程序需要的地方。

// 需要加载的bean.xml配置文件
<!-- 把对象的创建全部交给spring来管理
    bean标签,用于配置相应的对象信息,对象的为一标识和全限定类名,并存入IOC容器中,其实就是相当于与是把工厂交给了Spring配置文件就是bean.xml
     -->

    <!-- Tools的配置 -->
    <bean id="tools" class="com.my.Tools"></bean>
    <!-- User的配置 -->
    <bean id="user" class="com.my.User"></bean>

/**
 * 工具类
 */
public class Tools {
	// 工具类中的方法
    public  void doWork(){
        System.out.println("人使用工具完成工作");
    }
}

/**
 * 人类
 */
public class User {
	// 人依赖工具类,这里Spring只能降低耦合,但无法消除耦合(这个问题后面会有属性注入和注解的方式解决,本文就不过多描述)
    private Tools tools = new Tools();
    public void  doWork(){
        tools.doWork();
    }
}

/**
 * 工作类
 */
public class Work {
    public static void main(String[] args) {
    	// 可以发现其实这很像工厂类的形式,只不过是换成了Spring的Ioc容器来实现
		// 1.使用ApplicationContext接口就是在获取Spring容器对象
        ApplicationContext ac = new ClassPathXmlApplicationContext("bean.xml");
        // 2.根据bean的id来获取对象
        User user = (User) ac.getBean(user");
		user.doWork();
    }
}

SpringIoC

总结

到这里,我们发现控制权从最开始的程序本身自主创建依赖对象,到工厂类和Spring创建对象,被动的注入程序,而这一整个变化过程我们就可以称之为是Spring的依赖注入(DI)和控制反转(IoC)。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值