360SDN.COM

Spring Framework 5 权威指南(8)

来源:程序员阮威  2017-09-11 13:23:54    评论:0点击:

这是一个Spring 5专题系列,其诞生的动机是:

1.介绍最新的Spring Framework特性;

2.介绍最系统化的Spring Framework;

3.介绍最佳实践的Spring Framework;

 6. BeanDefinition 

要参与Spring容器对bean的生命周期的管理,只需要实现相应的生命周期回调函数即可。这些生命周期包括bean的初始化和销毁,以及容器的启动和关闭。Spring Framework内部是使用BeanPostProcessor来寻找和调用这些回调函数的。这里是容器的扩展点之一。

org.springframework.beans.factory.InitializingBean接口允许bean在容器设置了其所有必要的属性之后执行初始化工作。org.springframework.beans.factory.DisposableBean接口允许bean在容器销毁时执行销毁工作。例如:

<bean id="anotherExampleBean" class="examples.AnotherExampleBean"/>

代码如下:

public class AnotherExampleBeanimplements InitializingBean,DisposableBean {

 

       public void afterPropertiesSet() {

                //do some initialization work

       }

 

        public void destroy(){

                //do some destruction work (like releasing pooled connections)

       }

 

}

实现上述接口会导致代码与Spring之间的耦合,通常不推荐这种方式。

另一种方式是在bean定义中指定init-method属性和destroy-method属性,指向一个无参无返回值的方法,如下:

<bean id="exampleBean" class="examples.ExampleBean" init-method="init"      destroy-method="destroy"/>

代码如下:

public class ExampleBean{

 

       public void init() {

                //do some initialization work

       }

       

        publicvoid destory() {

                // do somedestruction work (like releasing pooled connections)

       }

 

}

可以在<beans>中定义默认的初始化和销毁方法,这样就不必为每一个bean定义指定。例如:

<beans default-init-method="init"default-destroy-method="destroy">

 

        <bean id="exampleBean" class="examples.ExampleBean" />

 

</beans>

注意:

1.bean定义的destroy-method属性和default-destroy-method属性可以赋值为inferred,这样,只要bean实现了java.lang.AutoCloseablejava.io.Closeable接口,就会自动推测其回调方法。

2.如果同一个bean定义上使用不同的方式指定了不同的回调方法,则其执行顺序为@PostConstructInitializingBean.afterPropertiesSet()init-method@PreDestroyDisposableBean.destroy()destroy-method

3.初始化回调函数会在AOP拦截器之前执行。

org.springframework.context.Lifecycle接口为需要自定义生命周期需求的对象定义了必要的方法:

public interface Lifecycle {

 

       void start();

 

       void stop();

 

       boolean isRunning();

 

}

任何被Spring容器管理的组件都可以实现这个接口,Spring容器自身也实现了该接口。当容器收到startstop信号时,会将其传播给所有实现了Lifecycle接口的组件(不保证stop信号一定在销毁回调之前到达),这是通过代理给LifecycleProcessor处理的,后者还专门定义了针对容器的refreshclose的回调函数:

public interface LifecycleProcessor extends Lifecycle {

 

       void onRefresh();

 

       void onClose();

 

}

org.springframework.context.SmartLifecycle接口相对Lifecycle接口提供了更细粒度的控制:

public interface Phased {

 

       int getPhase();

 

}

public interface SmartLifecycle extends Lifecycle,Phased {

 

       boolean isAutoStartup();

 

       void stop(Runnable callback);

 

}

getPhase()决定了启动和关闭时的顺序。启动时,拥有最低phase的对象先启动,停止时,顺序则相反。对于只实现了Lifecycle接口而没有实现SmartLifecycle接口的对象其phase值为0

isAutoStartup()表示组件在容器刷新时,是否需要显式的调用start才能启动。

要在非Web类应用中优雅的关闭Spring容器,你需要向JVM注册一个关闭钩子:

import org.springframework.context.ConfigurableApplicationContext;

import org.springframework.context.support.ClassPathXmlApplicationContext;

 

public final class Boot {

 

       public static void main(final String[]args) throws Exception {

 

                ConfigurableApplicationContextctx = 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...

 

       }

}

该钩子的主要作用是使容器关闭过程像主动调用close()的过程一样,Web类容器已经实现了优雅的关闭过程,无需额外注册钩子。

bean定义中的各种配置信息是可以被继承的,子bean定义可以覆盖或者新增父bean定义中的属性。在父bean定义中指定abstract属性为true(当父bean定义中没有指定class属性时必须为true)表示其不能被实例化。

<bean id="inheritedTestBean" abstract="true"

                class="org.springframework.beans.TestBean">

       <property name="name" value="parent"/>

       <property name="age" value="1"/>

</bean>

 

<bean id="inheritedTestBeanWithoutClass" abstract="true">

       <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 willbe inherited from parent -->

</bean>

 

<bean id="inheritsWithClass"

      class="org.springframework.beans.DerivedTestBean"

      parent="inheritedTestBeanWithoutClass"init-method="initialize">

       <property name="name" value="override"/>

     <!-- age will inherit the value of 1from the parent bean definition-->

</bean>



阅读原文

为您推荐

友情链接 |九搜汽车网 |手机ok生活信息网|ok生活信息网|ok微生活
 Powered by www.360SDN.COM   京ICP备11022651号-4 © 2012-2016 版权