`

Spring知识整理(七)—— IoC容器扩展(下)

阅读更多

Bean的生命周期

IoC容器的启动分为两个阶段,容器启动阶段和Bean实例化阶段。容器启动阶段上一篇已经介绍过了,下面说下Bean实例化阶段。对于BeanFactory,对象默认是延迟加载的,而ApplicationContext启动之后会实例化所有的bean定义,只不过ApplicationContext在启动后会调用注册到该容器的所有beangetBean()方法。不妨根据Bean的生命周期做下理解:


 
1.       实例化bean对象

容器内部采用“策略模式(Strategy Pattern)”来决定采用何种方式初始化bean实例。通常,可以通过反射或者CGLIB动态字节码生成来初始化相应的bean实例或者动态生成其子类。InstantiationStrategy是实例化策略的抽象接口,它有以下两个子类:

SimpleInstantiationStrategy:通过反射实例化,不支持注入。

CglibSubclassingInstantiationStrategy:继承于SimpleInstantiationStrategy,反射实例化,并通过CGLIB的动态字节码生成功能,可以动态生成某个类的子类,进而实现了方法注入。

容器根据bean定义的BeanDefintion取得实例化信息,结合CglibSubclassingInstantiationStrategy以及bean定义的类型,返回实例化完成的以BeanWrapper进行包裹的对象实例。

 

2.       设置对象属性

BeanWrapper继承于PropertyAccessor接口有一实现类BeanWrapperImpl,功能包括设置或者获取bean的相应属性值。同时又直接或者间接继承了PropertyEditorRegistryTypeConverter接口。在介绍CustomEditorConfigurer时,我们提到了PropertyEditor,而注册到容器的PropertyEditor就是供BeanWrapper使用的。

在第一步构造完成对象之后,Spring会根据对象实例构造一个BeanWrapperImpl实例,然后将之前CustomEditorConfigurer注册的PropertyEditor复制一份给BeanWrapperImpl实例(这就是BeanWrapper同时又是PropertyEditorRegistry的原因)。这样BeanWrapper就可以根据给出的PropertyEditor来转换类型、设置对象属性值。

 

3.       检查Aware接口并设置依赖

当对象属性和依赖设置完成之后,Spring容器会检查当前对象实例是否实现了一系列的以Aware命名结尾的接口定义。如果是,则将这些Aware接口定义中规定的依赖注入到当前对象。

Spring定义了如下几个Aware接口:

BeanNameAware:将beanName设置到当前对象实例。

BeanClassLoaderAware:将对应加载当前beanClassloader注入当前对象实例。

BeanFactoryAwareBeanFactory容器会将自身设置到当前对象实例。

(以下为ApplicationContext容器会进一步检查的接口,都是将ApplicationContext自身注入到当前对象实例)

ResourceLoaderAware

ApplicationEventPublisherAware

MessageSourceAware

ApplicationContextAware

 

4.       BeanPostProcessor

在容器的启动阶段,我们提到过BeanFactoryPostProcessor的概念。BeanPostProcessor容易与BeanFactoryPostProcessor混淆,只要记住这两个概念分别存在于不同阶段就能很好的区分。

BeanPostProcessor接口定义了两个方法,分别是postProcessBeforeInitialization()postProcessAfterInitialization(),这两个方法分别对应BeanPostProcessor的前置处理和后置处理阶段,两个方法的参数都是bean的实例和beanName,这样我们就可以对对象进行任何操作了。

通常比较常见的使用BeanPostProcessor的场景,是处理标记接口实现类,或者为当前对象提供代理实现。ApplicationContext容器定义的Aware接口的处理和Spring中注解的处理就是由BeanPostProcessor完成的。我们可以看下处理Aware的相关代码: 

public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
    if (bean instanceof ResourceLoaderAware) { 
        ((ResourceLoaderAware) bean).setResourceLoader(this.applicationContext);
    }
    if (bean instanceof ApplicationEventPublisherAware) {
        ((ApplicationEventPublisherAware) bean).setApplicationEventPublisher (this.applicationContext);
    } 
    if (bean instanceof MessageSourceAware) { 
        ((MessageSourceAware) bean).setMessageSource(this.applicationContext);
    }
    if (bean instanceof ApplicationContextAware) { 
        ((ApplicationContextAware) bean).setApplicationContext(this.applicationContext);
    }
    return bean; 
}

 

SpringAOP同样使用BeanPostProcessor来为对象生成相应的代理对象,如BeanNameAutoProxyCreator等,这个会在介绍AOP的时候详细说明。

 

当然,我们可以定义自己的BeanPostProcessor,做法就是实现BeanPostProcessor接口,然后将自定义的BeanPostProcessor注册到容器中:

ConfigurableBeanFactory beanFactory = new XmlBeanFactory(new ClassPathResource(...));

beanFactory.addBeanPostProcessor(new PasswordDecodePostProcessor());

对于于ApplicationContext,会自动识别并加载,所以只要在配置文件中配置下即可:

<bean id="passwordDecodePostProcessor" class="package.name.PasswordDecodePostProcessor">

<!--如果需要,注入必要的依赖-->

</bean>

 

1.       InitializingBeaninit-method

InitializingBean是容器内部广泛使用的一个对象生

命周期标识接口,其定义如下:

public interface InitializingBean {

void afterPropertiesSet() throws Exception;

}

该接口定义很简单,其作用在于,在调用过“BeanPostProcessor的前置处理”之后,会接着检测当前对象是否实现了InitializingBean接口,如果是,则会调用其afterPropertiesSet()方法进一步调整对象的状态。比如,在有些情况下,某个业务对象实例化完成后,还不能处于可以使用状态。这个时候就可以让该业务对象实现该接口,并在方法afterPropertiesSet()中完成对该业务对象的后续处理。

虽然该接口在Spring容器内部广泛使用,但如果真的让我们的业务对象实现这个接口,则显得Spring容器比较具有侵入性。所以,Spring还提供了另一种方式,在XML配置的时候,使用<bean>init-method属性:

<bean id="myCar" class=" com.zrabbit.production.Car" init-method="initCar">

 

至此,容器使用前的初始化工作已经全部完成。

 

2.       DisposableBeandestroy-method

当一个singleton类型的bean实例使用后,容器将检查其是否实现了DisposableBean接口。或者是否通过<bean>destroy-method属性指定了自定义的对象销毁方法。如果是,就会为该实例注册一个用于对象销毁的回调(Callback),以便在这些singleton类型的对象实例销毁之前,执行销毁逻辑。

InitializingBeaninit-method用于对象的自定义初始化相对应,DisposableBeandestroy-method为对象提供了执行自定义销毁逻辑的机会:

<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">

 

不过,这些自定义的销毁逻辑,在对象实例初始化完成并注册了相关的回调方法之后,并不会马上执行。回调方法注册后,返回的对象实例即处于使用状态,只有该对象实例不再被使用的时候,才会执行相关的自定义销毁逻辑,此时通常也就是Spring容器关闭的时候。但Spring容器在关闭之前,不会聪明到自动调用这些回调方法。所以,需要我们告知容器,在哪个时间点来执行对象的自定义销毁方法。

对于BeanFactory容器来说,我们需要调用ConfigurableBeanFactory提供的destroySingletons()方法销毁容器中管理的所有singleton类型的对象实例。对于ApplicationContext容器来说,我们可以调用AbstractApplicationContext提供的registerShutdownHook()方法。

 

public static void main(String[] args) {
    BasicConfigurator.configure();
    BeanFactory container = new XmlBeanFactory(new ClassPathResource("..."));
    BusinessObject bean = (BusinessObject)container.getBean("...");
    bean.doSth();
    ((ConfigurableListableBeanFactory)container).destroySingletons();
    // 应用程序退出,容器关闭
}

 

public static void main(String[] args) {
    BasicConfigurator.configure();
    BeanFactory container = new ClassPathXmlApplicationContext("..."); 
    ((AbstractApplicationContext)container).registerShutdownHook();
    BusinessObject bean = (BusinessObject)container.getBean("...");
    bean.doSth();
    // 应用程序退出,容器关闭
}

  

 

  • 大小: 43.6 KB
分享到:
评论

相关推荐

    Spring的IoC容器初始化源码解析

    #### 一、Spring框架的核心——IoC容器 Spring框架是一个开源的轻量级Java开发框架,其核心功能是IoC(Inversion of Control,控制反转)容器和AOP(Aspect Oriented Programming,面向切面编程),这些功能大大...

    Spring基础:IoC容器(1)

    在“Spring基础:IoC容器(1)”这个主题中,我们将深入探讨Spring的核心组件——IoC容器,以及它如何管理对象的生命周期和依赖关系。 IoC(Inversion of Control),也称为控制反转,是一种设计模式,它将对象的创建...

    Spring源码分析_Spring_IOC

    ### Spring源码分析_Spring_IOC:深入理解Spring的IOC容器机制 #### 基本概念与核心作用 在探讨Spring框架的核心组件之一——IOC(Inversion of Control,控制反转)容器之前,首先需要理解它在Spring框架中的角色...

    Spring——IOC(控制反转)与DI(依赖注入).docx

    控制反转是一种设计思想,它改变了传统的对象创建方式,将对象的创建和管理权从应用程序自身转移到一个外部的容器,比如Spring的IOC容器。在没有IOC的情况下,开发者需要在代码中直接创建对象并管理它们的依赖关系,...

    第四章 在Ioc容器中装配Bean

    Spring的IoC容器是一个高度可扩展的框架,允许开发者实现自己的装配机制,自定义Bean的解析、创建、装配过程。 综上所述,本章通过介绍IoC容器的概念、Bean的定义、依赖注入、作用域、生命周期管理以及自动装配等...

    Spring3.1.3 Ioc在Web容器中的建立

    综上所述,"Spring3.1.3 Ioc在Web容器中的建立"涵盖了Spring的核心特性之一——IoC,以及在Web环境下的具体配置和使用方法。这个过程涉及到Spring容器的初始化、bean的定义与依赖注入,以及Web应用的结构配置。通过...

    一个简单的IOC容器实现

    Spring的IOC容器在这一基础上进行了大量的扩展和优化,使得我们可以轻松地管理和组合复杂的系统组件。通过深入学习和实践,我们可以更好地利用Spring的IOC容器来构建更加健壮和灵活的软件系统。

    spring ioc

    标题 "Spring IOC" 描述了我们讨论的核心主题——Spring 框架中的依赖注入(Inversion of Control,简称 IOC)机制。Spring 是一个广泛应用的 Java 应用开发框架,其核心特性之一就是IOC,它极大地简化了软件组件...

    springioc和spring aop

    这样,对象不再负责创建和管理依赖,而是由IoC容器负责。Spring通过反射机制来实现这一过程,比如在上述的`TestIOC`例子中,Spring能够根据类名动态地创建对象,并通过setter方法注入属性值,实现了对象的实例化和...

    Spring.net二----初探IOC容器.rar源代码

    总的来说,Spring.NET的IOC容器提供了一种强大的方式来组织和管理.NET应用中的对象,使得代码更加模块化、易于测试和扩展。通过学习和实践,开发者能够充分利用这个框架来构建健壮的企业级应用程序。

    关于spring框架中的ioc的幽默解释.

    在Spring框架中,IoC容器是实现这一原则的关键组件。 ### IoC的核心思想 IoC的核心思想是将对象的创建和依赖关系的管理交由外部容器完成,而不是在对象内部进行。这与传统的编程方式相反,在传统方式中,对象自己...

    Spring开发指南——中文版

    - Spring框架的核心组件包括IoC容器、AOP、数据访问/集成、Web、工具类和模块化扩展。 2. **依赖注入(DI)** - DI是Spring框架的核心特性,它允许开发者将对象之间的依赖关系解耦,提高代码的灵活性和可测试性。...

    Java EE 框架整合开发⼊⻔到实战——Spring+Spring MVC+MyBatis(微课版)课后习题答案.pdf

    Spring通过BeanFactory接口和ApplicationContext接口实现IoC容器。BeanFactory提供了基础的IoC支持,而ApplicationContext是BeanFactory的子接口,为Spring应用提供配置服务,并且支持国际化和资源访问。 通过这...

    小读spring ioc源码(一)——整体介绍

    Spring的核心就是IOC容器,它负责管理应用程序中的对象,通过反转控制权,使得对象的创建和依赖关系的维护不再由代码直接操控,而是交由容器来处理。这种方式提高了代码的可测试性和可维护性。接下来,我们将围绕...

    Sping翻转控制器

    ### Sping翻转控制器知识点详解 #### 一、Spring IoC 容器概述 ...在实际项目开发中,合理选择和利用Spring的IoC容器可以帮助我们更好地管理应用程序中的对象及其依赖关系,提高代码的可维护性和可扩展性。

    Spring IOC:找对象的一次革命(1)

    Spring IoC提供了BeanFactory和ApplicationContext两种容器类型,其中BeanFactory是基础的IoC容器,而ApplicationContext则提供了更多高级功能,如资源加载、事件发布等。 Spring IoC的配置主要通过XML或注解的方式...

    Spring IoC简单示例-注解配置-Maven构建

    Spring IoC容器通过解析XML配置文件或使用注解来识别对象及其依赖关系,并在运行时自动装配这些对象,这就是依赖注入。 在Spring中,注解配置是取代传统XML配置的一种方式,它使得代码更加简洁、易读。例如,我们...

    spring 源码中文注释

    首先,我们来看看Spring的核心组件——IoC容器。IoC容器是Spring的核心,它负责管理对象的生命周期和对象之间的依赖关系。通过XML配置或基于注解的方式,我们可以告诉IoC容器如何创建和装配对象。在源码中,`...

    Spring的IoC实现案例

    在Spring框架中,IoC容器负责创建对象、管理它们之间的依赖关系,并在需要时注入这些依赖。 让我们开始分析“Priter”类。这个类代表了打印机,它可能有一个或多个方法用于执行打印操作。为了实现灵活性,我们不...

Global site tag (gtag.js) - Google Analytics