Spring FrameWork Core Tech

The IoC Container 1.6

2019-02-16  本文已影响0人  小鲍比大爷

1.6. Customizing the Nature of a Bean

The Spring Framework provides a number of interfaces you can use to customize the nature of a bean

Spring提供了非常多的接口,让用户可以自定义the nature of a bean(the nature of a bean,用英文描述起来感觉非常棒,但是中文实在不知道怎么翻译,翻译成bean的本性?bean的特性?怎么翻译都觉得尬。本文还是用英文称之为bean nature吧)。

1.6.1. Lifecycle Callbacks

bean生命周期简单说就是对象从生成到销毁的这个过程,其间如果用户想要插入相关操作,Spring通过提供相应的生命周期管理方法来达到这个目的。bean生命周期管理的意义:举个例子,假设在bean销毁时必须执行某些释放资源的操作,通过实现Spring给定的接口,Spring就会在bean销毁时自动调用相关操作,而不需要用户去显示调用。

Initialization and Destruction Callbacks

本节提供四种方式用来控制bean的生命周期,针对初始化和销毁这两个方法回调:

继承接口示例:

public class InterfaceBean implements InitializingBean, DisposableBean {

    public void destroy() throws Exception {
        System.out.println("InterfaceBean destroy.");
    }

    public void afterPropertiesSet() throws Exception {
        System.out.println("InterfaceBean Initializing.");
    }
}

自定义方法名配置示例:

<bean id="xmlBean" class="examples.XmlBean" init-method="init" destroy-method="cleanup"/>
package examples;

public class XmlBean {

    public void init() {
        System.out.println("XmlBean init.");
    }

    public void cleanup() {
        System.out.println("XmlBean cleanup.");
    }
}

全局方法名配置示例:

<?xml version="1.0" encoding="UTF-8"?>
<beans 
       default-init-method="init" 
      default-destroy-method="destroy">
</beans>

Startup and Shutdown Callbacks
前面演示了对象的初始化和销毁方法如何在Spring中实现,对于普通对象,可能初始化和销毁就足够了,但是对于类似服务这种对象,它会存在启动和停止操作,同样可以把这两种操作当做生命周期来管理。
Spring提供了两个接口,分别是Lifecycle和SmartLifecycle,需要启停的bean可以继承这两个接口。这两个接口的区别在于:Lifecycle必须用户自己调用start和stop方法,而SmartLifecycle可以支持在Container初始化完成后自动调用start方法(实现isAutoStartup(),返回true);SmartLifecycle通过继承Phased接口实现了启动的优先级,这块在后面说明。
Lifecycle:

public interface Lifecycle {

    void start();

    void stop();

    boolean isRunning();
}

SmartLifecycle:

public interface SmartLifecycle extends Lifecycle, Phased {

    boolean isAutoStartup();

    void stop(Runnable callback);
}

只要Spring Container中管理的bean实现了这两个接口,当ApplicationContext调用其start和stop方法,所有被它管理的bean都会调用相应接口的回调。ApplicationContext本质是交给了代理类LifecycleProcessor执行相关方法,LifecycleProcessor是个接口,它的Spring缺省实现是DefaultLifecycleProcessor。

public interface LifecycleProcessor extends Lifecycle {

    void onRefresh();

    void onClose();
}

SmartLifecycle支持设置启动停止优先级,当A和B都实现了SmartLifecycle接口,SmartLifecycle的父接口Phased支持设置启动停止优先级:

public interface Phased {

    int getPhase();
}

getPhase返回值越小,优先级越高,返回值越大,优先级越低。假设A和B继承SmartLifecycle,A的getPhase()返回值为-1,B的getPhase()返回值为1,那么A的start方法就会先于B调用,这样在对启动顺序有要求的情况下,可以有序的启动。而实现了Lifecycle接口的对象,优先级默认为0,相当于实现SmartLifecycle接口,但是getPhase()返回值为0。在调用stop方法时,优先级则相反。

Lifecycle接口的isRunning方法
isRunning方法的返回值会影响start和stop方法的调用,当调用start方法前 ,会检查isRunning返回值,如果为false,才会调用start;当调用stop方法前 ,也会检查isRunning返回值,如果为true,才会调用stop。

Shutting Down the Spring IoC Container Gracefully in Non-Web Applications
如何优雅的关闭Spring IoC Container(非web应用),很简单,调用registerShutdownHook方法即可,之后就会异步的执行每个bean的stop方法和destroy方法了:

import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public final class Boot {

    public static void main(final String[] args) throws Exception {
        ConfigurableApplicationContext ctx = new ClassPathXmlApplicationContext("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...
    }
}

1.6.2. ApplicationContextAware and BeanNameAware

ApplicationContextAware接口:

public interface ApplicationContextAware {

    void setApplicationContext(ApplicationContext applicationContext) throws BeansException;
}

BeanNameAware接口:

public interface BeanNameAware {

    void setBeanName(String name) throws BeansException;
}

Spring容器中管理的bean如果实现了上述两个接口,就可以通过这两个方法获取到ApplicationContext和BeanName的引用,进而做比较复杂的容器管理操作,当然,官方不建议使用这些接口,毕竟会跟Spring进行耦合,并且,现在的Spring版本都可以通过依赖注入的xml配置方式或者注解方式将想注入的对象注入到任何bean中,这种方式就显得比较麻烦了。
代码示例:

package examples;

import lombok.Getter;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.BeanNameAware;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;

@Getter
public class ContextContainedBean implements ApplicationContextAware, BeanNameAware {

    private ApplicationContext applicationContext;

    private String beanName;

    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        this.applicationContext = applicationContext;
    }

    public void setBeanName(String s) {
        this.beanName = s;
    }
}

1.6.3. Other Aware Interfaces
除了1.6.2提供的两种Aware接口,Spring还提供了一些其他接口,可以参考官方文档:Other Aware Interfaces

上一篇 下一篇

猜你喜欢

热点阅读