• 【Spring学习随笔】2. Spring IoC


    2. Spring IoC

    2.1 Spring IoC的基本概念

    控制反转(Inversion of Control,IoC)是Spring框架的核心,用来消减计算机程序的偶合问题。

    依赖注入(Dependency Injection,DI)是IoC的另外一种说法,只是从不同的角度描述相同的概念。

    ​ 当Spring框架出现后,对象的实例不再由调用者来创建,而是由Spring容器来创建。Spring容器会负责控制程序之间的关系,而不是由调用者的程序代码直接控制。这样,控制权由调用者转移到Spring容器,控制权发生了反转,这就是Spring的控制反转

    ​ 从Spring容器角度来看,Spring容器负责将被依赖对象赋值给调用者的成员变量,相当于为调用者注入它所依赖的实例,这就是Spring的依赖注入

    ​ 综上所述,控制反转是一种通过描述(在Spring中可以是XML或注解)并通过第三方去产生或获取特定对象的方式。在Spring中实现控制反转的是IoC容器,其实现方法是依赖注入。

    2.2 Spring IoC容器

    2.2.1 BeanFactory

    ​ BeanFactory由org.springframework.beans.factory.BeanFactory接口定义,他提供了完整的IoC服务支持,是一个管理Bean的工厂,主要负责初始化各种Bean。BeanFactory接口有多个实现类,其中比较常用的是org.springframework.beans.factory.xml.XmlBeanFactory。

    ​ 在创建BeanFactory实例时需要提供XML文件的绝对路径。下面是main方法中的一个示例代码:

    public static void main(String[] args) {
        //初始化Spring容器,加载配置文件
        BeanFactory beanFac = new XmlBeanFactory(
        		new FileSystemResource("D:eclipse-workspacech1src
        		applicationContext.xml")
        );
        //通过容器获取test实例
        TestDao tt = (TestDao)beanFac.getBean("test");
        tt.sayHello();
    }
    

    2.2.2 ApplicationContext

    ​ ApplicationContext是BeanFactory的子接口,也称为应用上下文,由org.springframework.context.ApplicationContext接口定义。ApplicationContext接口除了包含BeanFactory的所有功能以外,还添加了对国际化、资源访问、事件传播等内容的支持。

    ​ 创建ApplicationContext接口实例通常有一下3种方法:

    • 通过ClassPathXmlApplicationContext创建

      ClassPathXmlApplicationContext将从类路径目录(src根目录)中寻找指定的XML配置文件。代码如下:

      public static void mian(String[] args) {
          //初始化Spring容器ApplicationContext,加载配置文件
          ApplicationContext appCon = new ClassPathXmlApplicationContext("applicationContext.xml");
          //通过容器获取test实例
          TestDao tt = new (TestDao)appCon.getBean("test");
          tt.sayHello();
      }
      
    • 通过FileSystemXmlApplicationContext创建

      FileSystemXmlApplicationContext将从指定文件的绝对路径中寻找XML配置文件,找到并装载完成ApplicationContext的实例化工作。代码如下:

      public static void mian(String[] args) {
          //初始化Spring容器ApplicationContext,加载配置文件
          ApplicationContext appCon = new FileSystemXmlApplicationContext("D:eclipse-workspacech1srcapplicationContext.xml");
          //通过容器获取test实例
          TestDao tt = new (TestDao)appCon.getBean("test");
          tt.sayHello();
      }
      

      采用绝对路径的加载方式将导致程序的灵活性变差,一般不推荐使用。因此块,通常在Spring的Java应用中采取通过ClassPathXmlApplicationContext类来实例化ApplicationContext容器的方式,而在Web应用中,ApplicationContext容器的实例化工作将交给Web服务器完成。

    • 通过Web服务器实例化ApplicationContext容器

      在Web服务器实例化ApplicationContext容器时,一般使用基于org.framework.web.context.ContextLoaderListener的实现方式(需要将spring-web-x.x.x.RELEASE.jar复制到WEB-INF/lib目录中),此方法只需在web.xml中添加如下代码:

      <context-param>
      	<!-- 加载src目录下的applicationContext.xml文件 -->
          <param-name>contextConfigLocation</param-name>
          <param-value>
          	classpath:applicationContext.xml
          </param-value>
      </context-param>
      <!-- 指定以ContextLoaderListener方式启动Spring容器 -->
      <listener>
      	<listener-class>
          	org.framework.web.context.ContextLoaderListener
          </listener-class>
      </listener>
      

    2.3 依赖注入的类型

    ​ 在Spring中实现IoC容器的方法是依赖注入,依赖注入的作用是在使用Spring框架创建对象时动态地将其所依赖的对象(例如属性值)注入Bean组件中。Spring框架的依赖注入通常有两种实现方式,一种是使用构造方法注入,另一种是使用属性的setter方法注入。

    2.3.1 使用构造方法注入

    ​ Spring框架可以采用Java的反射机制,通过构造方法完成依赖注入。

    实例讲解:

    • 创建dao包

      创建dao包在service中使用构造方法依赖注入TestDIDao接口对象。

      TestDIDao接口代码如下:

      package dao;
      public interface TestDIDao {
          public void sayHello();
      }
      

      TestDIDaoImpl实现类代码如下:

      package dao;
      public class TestDIDaoImpl implements TestDIDao {
          @Override
          public void sayHello() {
              system.out.println("TestDIDao say: Hello, Study hard!");
          }
      }
      
    • 创建service包

      在TestDIServiceImpl中使用构造方法依赖注入TestDIDao接口对象。

      TestDIService接口代码如下:

      package service;
      public interface TestDIService {
          public void sayHello();
      }
      

      TestDIServiceImpl实现类代码如下:

      package service;
      import dao.TestDIDao;
      public class TestDIServiceImlp implements TestDIService {
          private TestDIDao testDIDao;
          //构造方法,用于实现依赖注入接口对象testDIDao
          public TestDIServiceImpl(TestDIDao testDIDao) {
              super();
              this.testDIDao = testDIDao;
          }
          
          @Override
          public void sayHello() {
              //调用testDIDao中的sayHello方法
              testDIDao.sayHello();
              System.out.println("TestDIService构造方法注入say: Hello, Study hard!");
          }
      }
      
    • 编写配置文件

      在src根目录下根目录下创建Spring配置文件applicationContext.xml。在配置文件中首先将dao.TestDIDaoImpl类托管给Spring,让Spring创建其对象,然后将service.TestDIServiceImpl类托管给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">
      	<!-- 
      	模拟spring执行过程
      		创建service实例:BookService bookService = new BookServiceImpl()	IoC  <bean>
      		创建dao实例:BookDao bookDao = new BookDaoImpl()			IoC
      		将dao设置给service:bookService.setBookDao(bookDao);		DI   <property>
      		
      		<property> 用于进行属性注入
      			name: bean的属性名,通过setter方法获得
      				setBookDao ##> BookDao  ##> bookDao
      			ref :另一个bean的id值的引用
      	 -->
      
      	<!-- 将指定类TestDIDaoImpl配置给Spring,让Spring创建其实例 -->
          <bean id="myTestDIDao" class="dao.TestDIDaoImpl" />
          <!-- 使用构造方法注入 -->
          <bean id="testDIService" class="service.TestDIServiceImpl">
          	<!-- 将myTestDIDao注入到TestDIServiceImpl类的属性testDIDao上 -->
              <constructor-arg index="0" ref="myTestDIDao" />
          </bean>
      	
      
      </beans>
      
      
      
    • 创建test包

      创建测试类TestDI,代码如下:

      package test;
      import org.springframework.context.ApplicationContext;
      import org.springframework.context.support.ClassPathXmlApplicationContext;
      import service.TestDIService;
      public classs TestDI {
          public static void main(String[] args) {
              //初始化Spring容器ApplicationContext,加载配置文件
          	ApplicationContext appCon = new ClassPathXmlApplicationContext("applicationContext.xml");
          	//通过容器获取testDIService实例,测试构造方法注入
          	TestDIService ts = (TestDIService)appCon.getBean("testDIService");
          	ts.sayHello();
          }  
      }
      
      
    • 运行效果:

    2.3.2 使用属性的setter方法注入

    ​ 使用setter方法注入是Spring框架中最主流的注入方式,它利用Java Bean规范所定义的setter方法来完成注入,灵活且可读性高。对于setter方法注入,Spring框架也是使用Java的反射机制实现的。

    实例讲解:

    • 创建接口实现类TestDIServiceImpl

      在service包中创建接口实现类TestDIServiceImpl1,在TestDIServiceImpl1中使用属性的setter方法依赖注入TestDIDao接口对象,代码如下:

      package service;
      import dao.TestDIDao;
      public class TestDIServiceImpl implements TestDIService {
          private TestDIDao testDIDao;
          //添加testDIDao属性的setter方法,用于实现依赖注入
          public void setTestDIDao(TestDIDao testDIDao) {
              this.testDIDao = testDIDao;
          }
          @Override
          public void sayHello() {
             //调用testDIDao中的sayHello方法
              testDIDao.sayHello();
              System.out.println("TestDIService setter方法注入 say: Hello, Study hard!");
          }
      }
      
      
    • 将TestDIServiceImpl1类托管给Spring

      让Spring创建其对象,同时调用TestDISeriveImpl1类的setter方法完成依赖注入。代码如下:

      <!-- 使用setter方法注入 -->
      <bean id="testDIService1" class="service.TestDIServiceImpl1">
          <!-- 调用TestDIServiceImpl1类的setter方法,将myTestDIDao注入到TestDIServiceImpl1类的属性testDIDao上 -->
          <property name="testDIDao" ref="myTestDIDao" />
      </bean>
      
      
    • 在test中测试setter方法注入

      //通过容器获取testDIService实例,测试setter方法注入
      TestDIService ts1=(TestDIService)appCon.getBean("testDIService1");
      ts1.sayHello();
      
      
    • 运行效果:

    都说酒是陈的香。
  • 相关阅读:
    (字典树)Revenge of Fibonacci -- HDU -- 4099
    (字符串 KMP)Blue Jeans -- POJ -- 3080:
    (广搜)聪明的打字员 -- POJ --1184
    (线段树 点更新 区间求和)lightoj1112
    Jquery弹窗插件Lhgdialog的用法
    SQL Server数据库大型应用解决方案总结
    C# 使用XmlDocument类对XML文档进行操作
    反射实例【转】
    如何使用dynamic
    [C#]DataTable常用操作总结
  • 原文地址:https://www.cnblogs.com/yihangjou/p/11906865.html
Copyright © 2020-2023  润新知