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

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>

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

你可能感兴趣的:(spring)