Spring号称是一个可以实现模块可插拔(轻量级)的JavaEE开发框架,那么它是如何实现程序的可插拔的呢?实现程序可以插拔的核心理念就是,控制反转IOC。

  什么是IOC?

  所谓的控制反转IOC,就是将代码的控制权从调用方转移给被调用方(服务提供方)

SRE实战 互联网时代守护先锋,助力企业售后服务体系运筹帷幄!一键直达领取阿里云限量特价优惠。

  要实现IOC(控制反转)的前提,是不用new就可以创建对象,而Spring是一个IOC框架,所有首先需要证明使用Spring框架,不用new就可以创建对象。实现步骤如下:

  • 创建一个普通的类
public class UserService { public void Say(){ System.out.println("Hello Spring!"); } }
  • 创建一个Spring配置文件,用于描述类与类之间的关系  
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
    <!-- <bean>标签:用于声明一个类,在启动Spring框架的时候根据该配置的类创建对象到容器里面。创建一个Spring配置文件,用于描述类与类之间的关系。 用来创建指定类的实例对象,Spring容器加载的时候创建。 name属性:对象在容器中的名称 class:属性,描述类的全路径(指定特创建对象的类的全路径) -->
    <bean name="userService" class="cn.gzsxt.spring.service.UserService"></bean>
</beans>
  • 创建ApplicationContext容器对象根据Spring配置文件的描述,将对象创建并且放在Spring容器里面
  • 使用ApplicationContext容器对象的getBean方法,调用Spring容器里面的对象
import org.junit.Test; import org.springframework.context.support.ClassPathXmlApplicationContext; import cn.gzsxt.spring.service.UserService; public class UserServiceTEST { @Test //ctrl+1 快捷导入单元测试类库
    public void testSay(){ //1、初始化容器 获取ApplicationContext对象
        ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("classpath:applicationContext.xml"); //2、从容器中获取实例对象
        UserService userService = context.getBean("userService", UserService.class); //3、调用对象的方法
 userService.Say(); //4、关闭资源,注销容器
 context.close(); } }

   强耦合调用方式

  将UserService调用MySQLDaoImpl的对象修改为OracleDaoImpl类的对象,修改的是调用方的代码,所以我们认为代码的调用权在调用方,如下图所示:

  02-Spring IOC 随笔 第1张

  将上图的需求,修改为使用IOC的调用代码方式,就是将代码的控制权从调用方修改为被调用方,意味着,代码的调用权转移给被调用方,我们也称为服务方,此过程中,不用修改调用方的代码,只需要修改配置文件就实现对象的切换,如下图:

02-Spring IOC 随笔 第2张

  我们将代码的调用权(控制权)从调用方转移给被调用方(服务提供方)的设计模式称为控制反转(IOC)

  从前面分析可以知道,要实现IOC,必须满足下面两个条件:

  1. 被调用方(服务方),在程序启动时就要根据配置文件类与类的关系创建好对象,放在一个容器里面
  2. 调用方使用一个接口或类的引用(不用使用new),就可以创建获得对象

   我们将这种不用new,而是根据接口或者类的引用就可以从被调用的容器里获得创建的对象的方式称为依赖注入

  控制反转IOC=依赖注入+面向接口的编程思想的实现。

  • 第一步:创建CustomerService接口
public interface CustomerService { public void save(); }
  • 第二步:创建CustomerServiceImpl实现类
public class CustomerServiceImpl implements CustomerService { @Override public void save() { System.out.println("CustomerServiceImpl--保存用户1"); }
}
public class CustomerServiceImpl2 implements CustomerService {

    @Override
    public void save() {
        System.out.println("CustomerServiceImpl2--保存用户2");
    }
}
  • 第三步:创建CustomerClient类
public class CustomerClient { /* * 基于属性的依赖注入,必须给属性加上set方法 */
// 1.声明一个父接口的引用CustomerService customerService
    private CustomerService customerService; // 2.使用set方法注入对象,我们将通过方法注入的对象的方式成为依赖注入
    public void setCustomerService(CustomerService customerService) { this.customerService = customerService; } // 客户端保存用户的方法
    public void save(){ customerService.save(); } }
  • 第四步:创建applicationContext.xml配置文件
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
    
    <!-- <bean name="customerServiceImpl" class="cn.gzsxt.spring.service.impl.CustomerServiceImpl"></bean> -->
    <bean name="customerServiceImpl" class="cn.gzsxt.spring.service.impl.CustomerServiceImpl2"></bean>
    
    <bean name="customerClient" class="cn.gzsxt.spring.client.CustomerClient">
        <!-- 对应set方法关联的对象customerService name:关联对应的set方法,关联规则:xxx对应setXxx(); 如:customerService()对应setCustomerService() ref:指向容器中的对象 -->
        <!-- 注入 <property>标签  ref 引入-->
        <property name="customerService" ref="customerServiceImpl"></property>
    </bean>
</beans>
  • 第五步:创建测试类CustomerClientTEST
public class CustomerClientTEST {
@Test
//ctrl+1 快捷导入单元测试类库 public void testSave(){ // 1、初始化容器 获取ApplicationContext对象 ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("classpath:applicationContext.xml"); // 2.从容器中获取实例对象 CustomerClient customerClient = context.getBean("customerClient",CustomerClient.class); // 3.调用对象的方法 customerClient.save(); // 4.关闭资源,注销容器 context.close(); } }

 

扫码关注我们
微信号:SRE实战
拒绝背锅 运筹帷幄