Spring IoC的概念

Posted ooo0

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Spring IoC的概念相关的知识,希望对你有一定的参考价值。

  大部分的企业架构都基于Spring框架。它的成功来自于理念,而不是技术,它最为核心的理念是IoC(控制反转)和AOP(面向切面编程),其中IoC是Spring的基础,而AOP则是其重要的功能,最为典型的当属数据库事务的使用。

Spring的概述

  Spring提供了以下策略:
  •对于POJO的潜力开发,提供轻量级和低侵入的编程,可以通过配置(XML、注解等)来扩展POJO的功能,通过依赖注入的理念去扩展功能,建议通过接口编程,强调OOD的开发模式理念,降低系统耦合度,提高系统可读性和可扩展性。
  •提供切面编程,尤其是把企业的核心应用——数据库应用,通过切面消除了以前复杂的try...catch...finally...代码结构,使得开发人员能够把精力更加集中于业务开发而不是技术本身,也避免了try...catch...finally语句的滥用。
  •为了整合各个框架和技术的应用,Spring提供了模板类,通过模板可以整合各个框架和技术,比如支持Hibernate开发的HibernateTemplate、支持MyBatis开发的SqlSessionTemplate、支持Redis开发的RedisTemplate等,这样就把各种企业用到的技术框架整合到Spring中,提供了统一的模板,从而使得各种技术用起来更简单。

Spring IoC概述

  控制反转是一个比较抽象的概念,我们举例说明。在实际生活中,人们要用到一样东西时,人们的基本想法是找到东西,比如想喝杯橙汁,在没有饮品店的日子里,最直观的做法是,要买果汁机、橙子,准备开水。请注意这是你自己“主动”创造的过程,也就是一杯橙汁需要主动创造。然而到了今时今日,由于饮品店的盛行,已经没有必要自己去榨橙汁了。想喝橙汁的想法一出现,第一个想法是找到饮品店的联系方式,通过电话、微信等渠道描述你的需要、地址、联系方式等,下订单等待,过会就会有人送上橙汁了。请注意你并没有“主动”创造橙汁,也就是橙汁是由饮品店创造的,而不是你,但是也完全达到了你的要求。
  为了更好地阐述上面的抽象描述,我们用Java代码的形式模拟主动创建和被动创建的过程。
  代码清单:搅拌机和果汁生成器

/**
 * 搅拌机
 */
public class Blender 

    /**
     * 搅拌
     *
     * @param water 水描述
     * @param fruit 水果描述
     * @param sugar 糖描述
     * @return 果汁
     */
    public String mix(String water, String fruit, String sugar) 
        String juice = "这是一杯由液体:" + water + "\n 水果:" + fruit + "\n糖量:" + sugar + "\n组成的果汁";
        return juice;
    



/**
 * 果汁生成器
 */
public class JuiceMaker 

    private Blender blender = null;//搅拌机
    private String water;//水描述
    private String fruit;//水果
    private String sugar;//糖分描述

    /**
     * 果汁生成
     */
    public String makeJuice() 
        blender = new Blender();
        return blender.mix(water, fruit, sugar);
    

    /**** setter and getter ****/

 

  被动创建对象
  代码清单:果汁制造器和果汁描述

/**
 * 果汁制造器和果汁描述
 */
public class JuiceMaker2 

    private String beverageShop = null;
    private Source source = null;


    public String makeJuice() 
        String fileEncoding = System.getProperty("file.encoding");//查看系统默认编码方式
        System.out.println("fileEncoding:" + fileEncoding);
        String juice = "这是由" + beverageShop + "饮品店,提供的" + source.getSize() + source.getSugar() + source.getFruit();
        return juice;
    


    /**** setter and getter ****/


public class Source 

    private String fruit;//类型
    private String sugar;//糖分描述
    private Integer size;//大小杯

    /**** setter and getter ****/

 

Spring IoC阐述

  有了上面的实例,下面我们阐述控制反转的概念:控制反转是一种通过描述(在Java中可以是XML或者注解)并通过第三方去产生或获取特定对象的方式。
  在Spring中实现控制反转的是IoC容器,其实现方法是依赖注入(Dependency Injection,DI)。正如上述的例子,果汁制造器依赖于饮品店和订单去制造果汁的,而饮品店是别人去创造的,我们只需要知道它能生产果汁就可以了,并不需要去理解如何创建果汁。

Spring IoC容器

  Spring IoC容器的作用,它可以容纳我们所开发的各种Bean,并且我们可以从中获取各种发布在Spring IoC容器里的Bean,并且通过描述可以得到它。

Spring IoC容器的设计

  Spring IoC容器的设计主要是基于BeanFactory和Applica-tionContext两个接口,其中ApplicationContext是BeanFactory的子接口之一,换句话说BeanFactory是Spring IoC容器所定义的最底层接口,而ApplicationContext是其高级接口之一,并且对BeanFactory功能做了许多有用的扩展,所以在绝大部分的工作场景下,都会使用ApplicationContext作为Spring IoC容器
代码清单:spring-cfg.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-4.0.xsd">

    <bean id="source" class="com.ssm.chapter9.pojo.Source">
        <property name="fruit" value="橙汁"/>
        <property name="sugar" value="少糖"/>
        <property name="size" value="3"/>
    </bean>

    <bean id="juiceMaker2" class="com.ssm.chapter9.pojo.JuiceMaker2">
        <property name="beverageShop" value="贡茶"/>
        <property name="source" ref="source"/>
    </bean>

</beans>
ApplicationContext ctx = new ClassPathXmlApplicationContext("ssm/chapter9/spring-cfg.xml");
JuiceMaker2 juiceMaker2 = (JuiceMaker2) ctx.getBean("juiceMaker2");
System.out.println(juiceMaker2.makeJuice());

 

Spring IoC容器的初始化和依赖注入

  这里需要注意的是Bean的初始化和依赖注入在Spring IoC容器中是两大步骤,它是在初始化之后,才会进行依赖注入。Bean的初始化分为3步:
(1)Resource定位,这步是Spring IoC容器根据开发者的配置,进行资源定位,在Spring的开发中,通过XML或者注解都是十分常见的方式,定位的内容是由开发者所提供的。
(2)BeanDefinition的载入,这个过程就是Spring根据开发者的配置获取对应的POJO,用以生成对应实例的过程。
(3)BeanDefinition的注册,这个步骤就相当于把之前通过BeanDefinition载入的POJO往Spring IoC容器中注册,这样就可以使得开发和测试人员都可以通过描述从中得到Spring IoC容器的Bean了。
  做完了这3步,Bean就在Spring IoC容器中得到了初始化,但是没有完成依赖注入,也就是没有注入其配置的资源给Bean,那么它还不能完全使用。对于依赖注入,Spring Bean还有一个配置选项——lazy-init,其含义就是是否初始化Spring Bean。在没有任何配置的情况下,它的默认值为default,实际值为false,也就是Spring IoC默认会自动初始化Bean。如果将其设置为true,那么只有当我们使用Spring IoC容器的getBean方法获取它时,它才会进行初始化,完成依赖注入。

Spring Bean的生命周期

  SpringIoC容器的本质目的就是为了管理Bean。对于Bean而言,在容器中存在其生命周期,它的初始化和销毁也需要一个过程,在一些需要自定义的过程中,我们可以插入代码去改变它们的一些行为,以满足特定的需求,这就需要使用到Spring Bean生命周期的知识了。
  生命周期主要是为了了解Spring IoC容器初始化和销毁Bean的过程,通过对它的学习就可以知道如何在初始化和销毁的时候加入自定义的方法,以满足特定的需求。
  BeanPostProcessor接口则是针对所有Bean而言的;接口DisposableBean则是针对Spring IoC容器本身。当一个Bean实现了上述的接口,我们只需要在Spring IoC容器中定义它就可以了,Spring IoC容器会自动识别。
  代码清单:BeanPostProcessor的实现类

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;

public class BeanPostProcessorImpl implements BeanPostProcessor 

    // @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException 
        System.out.println("【" + bean.getClass().getSimpleName() + "】对象" + beanName + "开始实例化");
        return bean;
    

    // @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException 
        System.out.println("【" + bean.getClass().getSimpleName() + "】对象" + beanName + "实例化完成");
        return bean;
    

 

  代码清单:DisposableBean实现类

import org.springframework.beans.factory.DisposableBean;

public class DisposableBeanImpl implements DisposableBean 

    // @Override
    public void destroy() throws Exception 
        System.out.println("调用接口DisposableBean的destroy方法");
    


  代码清单:JuiceMaker2_1

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.BeanFactoryAware;
import org.springframework.beans.factory.BeanNameAware;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;

public class JuiceMaker2_1 implements BeanNameAware, BeanFactoryAware, ApplicationContextAware, InitializingBean 

    private String beverageShop = null;
    private Source source = null;


    public void init() 
        System.out.println("【" + this.getClass().getSimpleName() +
                "】执行自定义初始化方法");
    

    public void destroy() 
        System.out.println("【" + this.getClass().getSimpleName() + "】执行自定义销毁方法");
    

    public String makeJuice() 
        String juice = "这是一杯由" + beverageShop + "饮品店,提供的" + source.getSize() + source.getSugar() + source.getFruit();
        return juice;
    

    // @Override
    public void setBeanName(String arg0) 
        System.out.println("【" + this.getClass().getSimpleName() + "】调用BeanNameAware接口的setBeanName方法");
    

    // @Override
    public void setBeanFactory(BeanFactory arg0) throws BeansException 
        System.out.println("【" + this.getClass().getSimpleName() + "】调用BeanFactoryAware接口的setBeanFactory方法");
    

    // @Override
    public void setApplicationContext(ApplicationContext arg0) throws BeansException 
        System.out.println("【" + this.getClass().getSimpleName() + "】调用ApplicationContextAware接口的setApplicationContext方法");
    

    // @Override
    public void afterPropertiesSet() throws Exception 
        System.out.println("【" + this.getClass().getSimpleName() + "】调用InitializingBean接口的afterPropertiesSet方法");
    

    /**** setter and getter ****/

 

  代码清单:声明自定义初始化和销毁方法的Bean spring-cfg2.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-4.0.xsd">

    <!--BeanPostProcessor定义-->
    <bean id="beanPostProcessor" class="com.ssm.chapter9.bean.BeanPostProcessorImpl"/>  <!--DisposableBean定义 -->
    <bean id="disposableBean" class="com.ssm.chapter9.bean.DisposableBeanImpl"/>
    <bean id="source" class="com.ssm.chapter9.pojo.Source">
        <property name="fruit" value="橙汁"/>
        <property name="sugar" value="少糖"/>
        <property name="size" value="3"/>
    </bean>

    <bean id="juiceMaker2_1" class="com.ssm.chapter9.pojo.JuiceMaker2_1" init-method="init" destroy-method="destroy">
        <property name="beverageShop" value="贡茶"/>
        <property name="source" ref="source"/>
    </bean>

</beans>

 

  代码清单:测试Spring Bean的生命周期

ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext("ssm/chapter9/spring-cfg2.xml");
JuiceMaker2_1 juiceMaker2_1 = (JuiceMaker2_1) ctx.getBean("juiceMaker2_1");
System.out.println(juiceMaker2_1.makeJuice());
ctx.close();

 

小结

  重点在于理解使用Spring IoC的好处和其容器的基本设计,懂得Spring IoC容器主要是为了管理Bean而服务的,需要注意掌握BeanFactory所定义的最为基础的方法,以及Spring Bean生命周期的用法,通过那些生命周期接口和方法的使用,允许我们自定义初始化和销毁方法。

 

参考:SSM框架第九章

以上是关于Spring IoC的概念的主要内容,如果未能解决你的问题,请参考以下文章

Spring框架[一]——spring概念和ioc入门(ioc操作xml配置文件)

spring中的ioc和aop概念

阶段3 2.Spring_03.Spring的 IOC 和 DI_1 ioc的概念和作用

Spring 与 IoC

阶段3 2.Spring_03.Spring的 IOC 和 DI_1 ioc的概念和作用

Spring第二天——IOC注解操作与AOP概念