码农小汪-spring框架学习之4-spring Bean的生命周期 ApplicationContextAware和BeanNameAware Spring Bean 的继承

来源:互联网 发布:向日葵软件如何视频 编辑:程序博客网 时间:2024/06/04 19:30

Spring可以管理singIeton作用域的Bean的生命周期,Spring可以精确的知道该Bean何时被创建,何时完成初始化,容器何时准备撤销该Bean的实例。

对于prototype作用域的bean。Spring容器仅仅负责创建Bean的实例。Bean完全由客服端的代码管理,容器不再去跟踪他们的生命周期。每次都去创建新的实例,无法管理哦。好多的个数。

对于单例Bean,每次都会返回一个共享的实例,客服端不能控制Bean的销毁,spring容器负责跟踪Bean实例的产生,销毁。spring容器可以在创建Bean之后,进行某些资源的申请;还可以在销毁Bean之前,对于某些资源的回收,比如数据库的连接

管理bean的生命周期主要有下面两个时机

  1. 实例化结束之后(也就是注入依赖关系之后)
  2. 销毁之前(即将销毁bean之前)

    Spring 容器可以控制 bean 的生命周期,通过实SpringInitializingBean 和DisposableBean 接口。容器会调用 InitializingBean 接口的afterPropertiesSet()方法,也会调用 DisposableBean 接口的 destroy()方法。 ,也就是运行 bean 自定义的初始化方法和销毁方法

Tip:在现代 Spring 应用中,一般都是用@PostConstruct 和@PreDestroy 注解定义生命周期回调函数。使用注解的话,你的 bean 就无需和Spring API 耦合了。
If you don’t want to use the JSR-250 annotations but you are still looking to remove coupling consider the use of init-method and destroy-method object definition metadata. 如果不想使用注解,可以使用元数据标签的

Spring 使用 BeanPostProcessor 实现类处理所有的回调接口并调用相应的方法,接口由 Spring 负责查找。若需要自定义功能或其他生命周期行为, Spring 并未提供开箱即用的支持,但是可以自己实现BeanPostProcessor 类。

package org.springframework.beans.factory.config;import org.springframework.beans.BeansException;/** * @author Juergen Hoeller * @since 10.10.2003 * @see InstantiationAwareBeanPostProcessor * @see DestructionAwareBeanPostProcessor * @see ConfigurableBeanFactory#addBeanPostProcessor * @see BeanFactoryPostProcessor */public interface BeanPostProcessor    /**     * @see org.springframework.beans.factory.InitializingBean#afterPropertiesSet     */    Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException;    /**     * @see org.springframework.beans.factory.InitializingBean#afterPropertiesSet     * @see org.springframework.beans.factory.FactoryBean     */    Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException;}

除了上面的,还可以使用lifecycle处理这些问题: Spring-managed objects may also implement the Lifecycle interface so that those objects can participate in the startup and shutdown process as driven by the container’s own lifecycle.

package org.springframework.context;/** *  * @see ConfigurableApplicationContext * @see org.springframework.jms.listener.AbstractMessageListenerContainer * @see org.springframework.scheduling.quartz.SchedulerFactoryBean */public interface Lifecycle {    void start();    void stop();    boolean isRunning();}public interface LifecycleProcessor extends Lifecycle {    /**     * Notification of context refresh, e.g. for auto-starting components.     */    void onRefresh();    /**     * Notification of context close phase, e.g. for auto-stopping components.     */    void onClose();}

初始化回调

package org.springframework.beans.factory;/** * @author Rod Johnson * @see BeanNameAware * @see BeanFactoryAware * @see BeanFactory * @see org.springframework.beans.factory.support.RootBeanDefinition#getInitMethodName * @see org.springframework.context.ApplicationContextAware */public interface InitializingBean {    /**     * Invoked by a BeanFactory after it has set all bean properties supplied     * (and satisfied BeanFactoryAware and ApplicationContextAware).     * <p>This method allows the bean instance to perform initialization only     * possible when all bean properties have been set and to throw an     * exception in the event of misconfiguration.     * @throws Exception in the event of misconfiguration (such     * as failure to set an essential property) or if initialization fails.     */    void afterPropertiesSet() throws Exception;}

推荐,尽量不用 InitializingBean 接口,因为这将导致不必要的与 Spring 的耦合。还有更好的办法,使用@PostConstruct 注解,或者指定一个 POJO 的initialization 方法。 XML 配置元数据中,使用 init-method 属性用来指定,其值为初始化方法名
例如:
init-method在全部设置执行完之后执行。

<bean id="exampleInitBean" class="examples.ExampleBean" init-method="init"/>public class ExampleBean {    public void init() {        // do some initialization work    }}

下面这个是和spring没有解耦的

<bean id="exampleInitBean" class="examples.AnotherExampleBean"/>public class AnotherExampleBean implements InitializingBean {    public void afterPropertiesSet() {        // do some initialization work    }}

org.springframework.beans.factory.DisposableBean,@PreDestroy,destroy-method。这些都是差不多的啊!和上面的类似的作用。我们不太需要了解好多!

public class AnotherExampleBean implements DisposableBean {    public void destroy() {        // do some destruction work (like releasing pooled connections)    }}

默认的初始化函数和销毁函数,不需要通过init-method之类的东西!不需要配置,只要命名规范就行了!
有三种生命周期回调机制,或者说是三种方式实现:InitializingBean 和 DisposableBean 回调接口;自定义 init()
和 destroy()方法; @PostConstruct and @PreDestroy 注解。这些方式可以混合使用

Spring的IoC容器关闭优雅地在非web应用程序中

在一个非 web 应用的环境中使用 Spring IoC 容器;比如,在一个富客户端桌面环境中;得在 JVM 中注册一个 shutdown 钩子。这么做是为了安全的关闭,关闭时保证所单例 bean 的相关的 destroy 方法会被调用,这样就可以释放所的资源。当然了,你必须得正确的配置和实现销毁回调。要注册 shutdown 钩子,得调用 registerShutdownHood()方法,该方法在
AbstractApplicationContext 类中

import org.springframework.context.support.AbstractApplicationContext;import org.springframework.context.support.ClassPathXmlApplicationContext;public final class Boot {    public static void main(final String[] args) throws Exception {        AbstractApplicationContext ctx = new ClassPathXmlApplicationContext(                new String []{"beans.xml"});        // add a shutdown hook for the above context...        ctx.registerShutdownHook();        // app runs here...        // main method exits, hook is called prior to the app shutting down...    }}

ApplicationContextAware和BeanNameAware

因此可以编程式的使用 ApplicationContext 手动的创建 bean,通过ApplicationContext 接口或者是该接口的子类,比如ConfigurableApplicationContext,该类还增加了方法。用途之一是编程式的检索 bean,有时非常有用。然而,大多数情况下,要避免编程式检索 bean,这样的话你的代码就会和 Spring 耦合,这不是 IoC 的风格, Ioc 的风格是协作类作为 bean 的属性。 ApplicationContext 类的其他方法提供了文件资源的访问接口、发布应用事件、访问 MessageSource 消息资源

org.springframework.beans.factory.BeanNameAware 接口的实现类,若是由ApplicationContext 创建了该类的实例,该实例将会持有相关的对象定义的引用

还有好多的Aware
除了ApplicationContextAware和BeanNameAware上面所讨论的,Spring提供了 范围的Aware接口允许bean来表示他们的容器 需要一定的基础设施依赖。 最重要的Aware接口 总结如下
这里写图片描述

Spring Bean 的继承

Spring bean 定义包含各种配置信息,包括构造参数,属性值,容器特定信息例如初始化方法、静态工厂方法等等。 Spring 子 bean 定义继承父bean 定义配置。子 bean 能覆盖值,若有需要还能增加其他配置。使用继承能少打好多字。这是模板的一种形式,讲究的就是效率
若子 bean 中未指定 class 属性,则子 bean 集成父 bean 的 class 属性,子bean 可以重写覆盖此属性。若要覆盖重写 class 属性,子 bean 的 class 类型必须兼容父 bean 的 class,也就是,子 bean 必须能接收父 bean 的属性值。其他的属性也是通常取自子 bean 的配置: depends on, autowire mode,dependency check, singleton, lazy init.

<bean id="inheritedTestBean" abstract="true"        class="org.springframework.beans.TestBean">    <property name="name" value="parent"/>    <property name="age" value="1"/></bean><bean id="inheritsWithDifferentClass"        class="org.springframework.beans.DerivedTestBean"        parent="inheritedTestBean" init-method="initialize">    <property name="name" value="override"/>    <!-- the age property value of 1 will be inherited from parent --></bean>

其实很简单的,就和是一个复用的问题。

0 0
原创粉丝点击