Spring IoC 的概念

本章目标
  1. 了解Spring的历史和发胀概况
  2. 掌握Spring IoC容器的大致设计
  3. 掌握Spring IoC的实现过程
  4. 掌握Spring Bean的生命周期

Spring 的概述

一些历史可以自行百度

这里做个小总结,Spring提供以下策略:

  • 对于POJO的潜力开发,提供了轻量级和低侵入的编程,可以通过配置XML或者注解等来扩展POJO的功能,通过依赖注入的理念去扩展功能,建议通过接口编程,强调OOD的开发模式理念,降低耦合度,提高系统可读性和扩展性
  • 提供切面编程,使得开发人员能够集中于业务开发而不是技术本身,也避免了try…catch…finally语句的滥用
  • 为了整合各个框架和技术的应用,Spring提供了模版类,通过模版类可以整合各个框架和技术,比如支持Hibernate开发的HibernateTemplate、支持MyBatis开发的SplSessionTemplate、支持Redis开发的RedisTemplate等,这样就把各种技术框架整合到Spring中,提供了统一的模版。

Spring IoC 概述

主要理解两个概念:
1. 控制反转
2. 依赖注入

场景:A类中包含B类的对象b

控制反转:以前对象b需要程序员自己创建,主动权在程序员,现在这个对象不需要程序员自己创建,由容器来创建。

依赖注入:上面IoC容器负责对象的创建和管理,但是需要通过依赖注入的方式注入到类A中。

Spring实现控制反转的是IoC容器,实现方法是依赖注入。

Spring IoC 容器

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

Spring IoC 容器的设计

Spring IoC 容器的设计主要是基于BeanFactory和ApplicationContext两个接口,其中ApplicationContext是BeanFactory的子接口之一,ApplicationContext是高级接口之一。下图是Spring IoC 容器接口的设计:

image

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

Bean的定义和初始化在Spring IoC容器中是两大步骤:
- 先定义
- 然后初始化和依赖注入

Bean的定义分3步:
1. Resource定位,这步是Spring IoC 容器根据开发者的配置进行资源定位。
2. BeanDefinition的载入,将Resource定位到的信息保存到Bean定义中,此时并不会创建Bean的实例
3. BeanDefinition的注册,将BeanDefinition的信息发布到Spring IoC容器中,注意此时仍然没有创建Bean实例

上面三部后,Bean在Spring IoC 容器中被定义,但是没有被初始化,更没有完成依赖注入。

Spring Bean 还有一个配置:lazy-init,默认值为:false,Spring IoC 默认会自动初始化Bean。如果将其设置为true,只有当我们使用Spring IoC容器的getBean方法获取它,它才会进行Bean的初始化,完成依赖注入。

Spring Bean 的生命周期

Spring IoC 容器的本质目的就是为了管理Bean。在容器中Bean的初始化以及销毁有一个过程,存在一个生命周期。

下图是Bean的生命周期:

image
image

Bean的完整生命周期经历了各种方法调用,这些方法可以划分为以下几类:
- Bean自身的方法  :  这个包括了Bean本身调用的方法和通过配置文件中的init-method和destroy-method指定的方法
- Bean级生命周期接口方法  :  这个包括了BeanNameAware、BeanFactoryAware、InitializingBean和DiposableBean这些接口的方法
- 容器级生命周期接口方法  :  这个包括了InstantiationAwareBeanPostProcessor 和 BeanPostProcessor 这两个接口实现,一般称它们的实现类为“后处理器”。
- 工厂后处理器接口方法  :  这个包括了AspectJWeavingEnabler, ConfigurationClassPostProcessor, CustomAutowireConfigurer等等非常有用的工厂后处理器  接口的方法。工厂后处理器也是容器级的。在应用上下文装配配置文件之后立即调用。

其中BeanPostProcessor接口则是针对所有Bean而言的。

示例

BeanPostProcessorImpl类,实现了BeanPostProcessor,是针对所有Bean而言的。

package com.ssm.chapter9.bean;

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;
    }
}

DisposableBeanImpl类

package com.ssm.chapter9.bean;

import org.springframework.beans.factory.DisposableBean;

public class DisposableBeanImpl implements DisposableBean {

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

Blender类

package com.ssm.chapter9.pojo;

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;
    }
}

JuiceMaker类

package com.ssm.chapter9.pojo;

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

    public Blender getBlender() {
        return blender;
    }

    public void setBlender(Blender blender) {
        this.blender = blender;
    }

    public String getWater() {
        return water;
    }


    public void setWater(String water) {
        this.water = water;
    }

    public String getFruit() {
        return fruit;
    }

    public void setFruit(String fruit) {
        this.fruit = fruit;
    }

    public String getSugar() {
        return sugar;
    }

    public void setSugar(String sugar) {
        this.sugar = sugar;
    }

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

JuiceMaker2 类

package com.ssm.chapter9.pojo;

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 implements BeanNameAware, BeanFactoryAware, ApplicationContextAware, InitializingBean{
    private String beverageShop = null;
    private Source source = null;

    public String getBeverageShop() {
        return beverageShop;
    }

    public void setBeverageShop(String beverageShop) {
        this.beverageShop = beverageShop;
    }

    public Source getSource() {
        return source;
    }

    public void setSource(Source source) {
        this.source = source;
    }

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

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

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

    @Override
    public void setBeanName(String s) {
        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 afterPropertiesSet() throws Exception {
        System.out.println("【" + this.getClass().getSimpleName() + "】调用InitializingBean接口的afterPropertiesSet方法");
    }

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

    }
}

Source 类

package com.ssm.chapter9.pojo;

public class Source {
    private String fruit;// 类型
    private String sugar;// 糖分描述
    private String size;// 大小杯
    public String getFruit() {
        return fruit;
    }
    public void setFruit(String fruit) {
        this.fruit = fruit;
    }
    public String getSugar() {
        return sugar;
    }
    public void setSugar(String sugar) {
        this.sugar = sugar;
    }
    public String getSize() {
        return size;
    }
    public void setSize(String size) {
        this.size = size;
    }

}

配置文件 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">

    <!--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="大杯" />
    </bean>

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

</beans>

测试主函数,Chapter9Main 类

package com.ssm.chapter9.main;

import org.springframework.context.support.ClassPathXmlApplicationContext;

import com.ssm.chapter9.pojo.JuiceMaker;
import com.ssm.chapter9.pojo.JuiceMaker2;

public class Chapter9Main {
    public static void main(String[] args) {
        testIoC();
    }

    public static void testCommon() {
        JuiceMaker juiceMaker = new JuiceMaker();
        juiceMaker.setWater("矿泉水");
        juiceMaker.setFruit("橙子");
        juiceMaker.setSugar("少糖");
        System.out.println(juiceMaker.makeJuice());
    }

    public static void testIoC() {
        ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext("spring-cfg.xml");
        JuiceMaker2 juiceMaker2 = (JuiceMaker2) ctx.getBean("juiceMaker2");
        System.out.println(juiceMaker2.makeJuice());
        ctx.close();
    }
}

运行结果:

1. [DisposableBeanImpl] 对象disposableBean开始实例化
2. [DisposableBeanImpl] 对象disposableBean完成实例化
3. [Source] 对象source开始实例化
4. [Source] 对象source完成实例化
5.【JuiceMaker2】调用BeanNameAware接口的setBeanName方法
6.【JuiceMaker2】调用BeanFactoryAware接口的setBeanFactory方法
7.【JuiceMaker2】调用ApplicationContextAware接口的setApplicationContext方法
8. [JuiceMaker2] 对象juiceMaker2开始实例化
9.【JuiceMaker2】调用InitializingBean接口的afterPropertiesSet方法
10.【JuiceMaker2】执行自定义初始化方法
11. [JuiceMaker2] 对象juiceMaker2完成实例化
这是一杯由贡茶饮品店,提供的大杯少糖橙汁
12.【JuiceMaker2】执行自定义销毁方法
13. 调用接口DisposableBean的destroy方法。
说明
  1. BeanPostProcessor针对所有Bean的,所以不管哪个Bean实例化的时候都会调用实现的两个接口,所以后面所有包含开始实例化和完成实例化的打印都是Bean实例化的时候调用下面两个接口:
    • postProcessBeforeInitialization
    • postProcessAfterInitialization
  2. 上面前4个打印是对应xml中BeanPostProcessor以及DisposableBean两个对象的实例化的打印
  3. 第5行是对应BeanNameAware的setBeanName接口
  4. 第6行是对应BeanFactoryAware的setBeanFactory接口
  5. 第7行是对应ApplicationContext的setApplicationContext方法,并且Spring IoC 容器必须是一个ApplicationContext接口的实现类,因为ClassPathXmlApplicationContext是ApplicationContext的实现类
  6. 第9行时InitializingBean的afterPropertiesSet方法
  7. 第10行执行自己定义的init方法,这个在xml配置
  8. 第12行对象通过getBean方法得到,病调用相关方法打印的结果
  9. 第13行时执行自定义的destroy方法,在xml中配置
  10. 最后一行是DisposableBean的destroy方法。
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值