• Java Sping 第二章——Spring IoC


    一、Spring IoC的基本概念

    控制反转(Inversion of Control,IoC)是一个比较抽象的概念,是Spring框架的核心,用来消减计算机程序的耦合问题。依赖注入(Dependency Injection,DI)是IoC的另外一种说法,只是从不同的角度,描述相同的概念。
    IOC(Inverse of Control)反转控制的概念,就是将原本在程序中手动创建对象的控制权,交由Spring框架管理。当某个Java对象(调用者)需要调用另一个Java对象(被调用者)时,在传统编程模式下,调用者通常会采用“new 被调用者”的代码方式来创建对象。这种方式会增加调用者与被调用者之间的耦合性,不利于后期代码的升级与维护。

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

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

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


    这些书面语还是有点抽象,看到有大佬写了一篇生活化的解释,https://blog.csdn.net/u013030441/article/details/53896091

    二、Spring IOC容器


    实现控制反转的是Spring IOC容器,Spring IOC容器的设计主要是基于Bean Factory和ApplicationContext两个接口。

    2.1、BeanFactory接口

    BeanFactory由org.springframework.beans.factory.BeanFactory接口定义,它提供了完整的IOC服务支持,是一个管理Bean的工厂,主要负责初始化各种Bean。
    BeanFactory接口最常用的实现类是org.springframework.beans.factory.xml.XMLBeanFactory,该类会根据XML配置文件中的定义来装配Bean。
    BeanFactory实例创建代码如下:

    @Test
    public void demo(){
        FileSystemResource file = new FileSystemResource("C:\demo\applicationContext.xml");
        BeanFactory beanFactory = new XmlBeanFactory(file);
        TestDao testDao = (TestDao) beanFactory.getBean("testDao");
        testDao.sayHello();
    }


    由于使用BeanFactory实例加载Spring配置文件在实际开发中并不多见,所以对于该接口仅了解即可。

    2.2、ApplicationContext接口

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

        通过ClassPathXmlApplicationContext创建
        通过FileSystemXmlApplicationContext创建
        通过Web服务器实例化ApplicationContext容器

    下面对这3种方法的代码做演示:

    (1)ClassPathXmlApplicationContext

    使用ClassPathXmlApplicationContext将从类路径目录(src根目录)中寻找指定的XML配置文件,代码示例:

    @Test
    public void demo(){
        //初始化Spring容器ApplicationContext,加载配置文件
        ApplicationContext application = new ClassPathXmlApplicationContext("applicationContext.xml");
        //通过容器获取testDao实例
        TestDao testDao = (TestDao) application.getBean("testDao");
        testDao.sayHello();
    
    }


    (2)FileSystemXmlApplicationContext

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

    @Test
    public void demo(){
        ApplicationContext application = new FileSystemXmlApplicationContext("C:\demo\applicationContext.xml");
        TestDao testDao = (TestDao) application.getBean("testDao");
        testDao.sayHello();
    
    }


    (3)使用Web服务器实例化

    通过Web服务器实例化ApplicationContext容器,一般使用org.springframework.web.context.ContextLoaderListener的实现方式,需要添加Spring-web依赖,pom.xml配置如下:

    <dependency>
       <groupId>org.springframework</groupId>
       <artifactId>spring-web</artifactId>
       <version>5.0.2.RELEASE</version>
     </dependency>


    在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.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>


    通过web.xml配置,web容器会自动加载context-param中的配置文件初始化ApplicationContext实例,然后就可以在web应用中通过WebApplicationContextUtils.getWebApplicationContext方法获取ApplicationContext的引用,Servlet中的代码如下:

    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws javax.servlet.ServletException, IOException {
        ApplicationContext application = WebApplicationContextUtils.getWebApplicationContext(request.getServletContext());
        TestDao testDao = (TestDao) application.getBean("testDao");
        testDao.sayHello();
    }

    三、依赖注入(基于XML方式)

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

    构造方法注入

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

    创建dao

    在ch2应用中,创建dao包,并在该包中创建TestDIDao接口和接口实现类TestDIDaoImpl。创建dao的目的是在service中使用构造方法依赖注入TestDIDao接口对象。

    package chap10.dao;
    
    public interface TestDao {
        public void sayHello();
    }
    package chap10.dao;
    
    public class TestDaoImpl implements TestDao{
        @Override
        public void sayHello() {
            System.out.println("Hello, Study hard!");
        }
    }

    创建service

    在ch2应用中,创建service包,并在该包中创建TestDIService接口和接口实现类TestDIServiceImpl。在TestDIServiceImpl中使用构造方法依赖注入TestDIDao接口对象。

    package chap10.service;
    
    public interface TestService {
        void sayHello();
    }
    package chap10.service;
    
    import chap10.dao.TestDao;
    
    public class TestServiceImpl implements TestService {
        private TestDao testDao;
        
        
        public TestServiceImpl(TestDao testDao) {
            this.testDao = testDao;
        }
        public TestServiceImpl() {
            
        }    
        public TestDao getTestDao() {
            return testDao;
        }
        public void setTestDao(TestDao testDao) {
            this.testDao = testDao;
        }
        @Override
        public void sayHello() {
            testDao.sayHello();
    
        }
    
    }

    编写配置文件

    在src根目录下,创建Spring配置文件applicationContext.xml。在配置文件中,首先,将dao.TestDIDaoImpl类托管给Spring,让Spring创建其对象。其次,将service.TestDIServiceImpl类托管给Spring,让Spring创建其对象,同时给构造方法传递实参。

    <bean id="test" class="spring01.dao.TestDaoImpl">
    </bean>
    <bean id="testServ" class="spring01.service.TestServImpl">
    <constructor-arg ref="test"></constructor-arg>
    </bean>

    创建test

    在ch2应用中,创建test包,并在该包中创建测试类TestDI,具体代码如下:

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

    属性setter方法注入

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

    创建接口实现类TestDIServiceImpl1

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

    TestDIServiceImpl1.java

    package service;
    
    import dao.TestDIDao;
    
    public class TestDIServiceImpl1 implements TestDIService{
        private TestDIDao testDIDao;
        public void setTestDIDao(TestDIDao testDIDao) {
            this.testDIDao = testDIDao;
        }
        public void sayHello() {
            testDIDao.sayHello();
            System.out.println("hello in service2");
        }
    }

    TestDIServiceImpl1类托管Spring

    将service.TestDIServiceImpl1类托管给Spring,让Spring创建其对象。同时,调用TestDIServiceImpl1类的setter方法完成依赖注入。在配置文件添加如下代码:

    <!-- 使用setter方法注入 -->
    <bean id="testDIService1" class="service.TestDIServiceImpl1">
            <property name="testDIDao" ref="myTestDIDao" />
    </bean>
    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">
        <!-- 将指定类TestDaoImpl配置给Spring,让Spring创建其实例 -->
        <bean id="myTestDIDao" class="dao.TestDIDaoImpl" />
        <bean id="testDIService" class="service.TestDIServiceImpl">
            <constructor-arg index="0" ref="myTestDIDao" /> 
        </bean>
        <!-- 使用setter方法注入 -->
        <bean id="testDIService1" class="service.TestDIServiceImpl1">
            <property name="testDIDao" ref="myTestDIDao" />
        </bean>
    </beans>

    在test中测试setter方法注入

    在Test.java主类中,添加如下代码,测试setter方法注入:

    TestDIService ts1 = (TestDIService)appCon.getBean("testDIService1");// test为配置文件中的id
    ts1.sayHello();

    Test.java

    package test;
    
    import org.springframework.context.ApplicationContext;
    import org.springframework.context.support.ClassPathXmlApplicationContext;
    
    import dao.TestDIDao;
    import service.TestDIService;
    
    public class Test {
        public static void main(String[] args) {
            // 初始化Spring容器ApplicationContext,加载配置文件
            ApplicationContext appCon = new ClassPathXmlApplicationContext("applicationContext.xml");
            TestDIService ts = (TestDIService)appCon.getBean("testDIService");// test为配置文件中的id
            ts.sayHello();
            TestDIService ts1 = (TestDIService)appCon.getBean("testDIService1");// test为配置文件中的id
            ts1.sayHello();
    
        }
    }
  • 相关阅读:
    Python循环语句
    Python基本数据类型
    Python条件句句
    Python基础
    jmeter用户自定义变量和CSV可变参数压测、和多参数的使用
    App资源在线升级更新
    javaweb项目启动报错org.apache.catalina.LifecycleException: Failed to start component [StandardEngine[Catalina].StandardHost[localhost].StandardContext[/cab-web]]
    mui移动端日期选择器的使用
    java把json字符串转成实体
    MUI集成个推实现消息推送
  • 原文地址:https://www.cnblogs.com/wkfvawl/p/12757800.html
Copyright © 2020-2023  润新知