b springbean加载的机制,和自定义bean加载行为
Customizing the Nature of a Bean
Spring Framework 提供了一堆api,去自定义加载bean时的行为
-
Lifecycle Callbacks
周期回调 -
ApplicationContextAware and BeanNameAware
容器aware和 BeanNameAware 其他 Aware Interfaces
aware指的是spring 自身框架的对外接口,提供和框架交互的
6.1 Lifecycle Callbacks
解释可以置入的点
和container的管理的bean 生命周期交互,你可以通过实现InitializingBean
和DisposableBean
接口。
容器调用afterPropertiesSet() 在初始化之前 和 destroy() 在摧毁之后,以让bean执行确定的动作
JSR-250的 @PostConstruct和 @PreDestroy是广泛使用的最佳时间。不想用 JSR-250,可以使用
init-method
和destroy-method
内部,spring框架使用BeanPostProcessor
的实现类去处理回调函数–他可以找到和调用合适 的方法。
如果你需要自定义其他行为,spring 默认不会提供,你可以实现BeanPostProcessor
类。
额外的,Spring 管理对象也可以通过实现Lifecyle
接口以让对象加入到启动和停止进程,被容器自己的声明周期地调用。
初始化Initialization Callbacks
该接口org.springframework.beans.factory.InitializingBean
让bean在设置完所有必要的properties后初始化。
接口就一个方法
我们不推荐使用该接口,因为冗余的代码。我们推荐使用@PostConstruct
。在xml 风格里 使用init-method
属性。对于java configuration, 你可以使用@Bean
的initMethod
属性
示例1
示例2
示例1等于示例2,但是示例1就不会有冗余
销毁 Destruction Callbacks
通过实现org.springframework.beans.factory.DisposableBean
完成销毁前的动作。
接口有单一方法
同初始化,不推荐使用代码而是使用@PreDestroy
注解。inxml是destroy-method
属性。java configuration 是用@Bean
的destroyMethod
示例1
示例2
同样1与2相同,但是1不会有多余的冗余
默认的 nitialization 和 Destroy Methods
除了像上面一样去配置,也可以约定固定方法的名称,让container去找对应方法去调用。default-init-method
和default-destroy-method
示例
配置如下
类中的init方法会被调用
同样在<beans>
中的谁定可以在<bean>
中用同样的标签覆盖掉
联合 Lifecycle Mechanisms
首先总共有三种方式来进行置入神生命周期行为
-
The
InitializingBean
和DisposableBean
callback interfaces -
Custom
init()
anddestroy()
methods -
The
@PostConstruct
and@PreDestroy
annotations.
这些方式可以混合使用,一个init只会被调用一次,以下是调用顺序
- 初始化
- 销毁
satrtup和shutdown回调
常规的启停
lifecle
接口定义了任何对象必要的使用的方法。任何实现了该接口的类都会被容器调用
比如ApplicationContext
收到了启动和停止信号会挨个调用lifecle
的实现。
实现这样的功能被委托给类LifecycleProcessor
,如下
org.springframework.context.Lifecycle
是用来控制严格的启动和停止,不能被自动启停所使用。想使对bean的自动启停控制推荐org.springframework.context.SmartLifecycle
。
自动启停
原因:依赖位置
启动和关闭调用的顺序可能很重要。如果任何两个对象之间存在“依赖”关系,则依赖方在其依赖之后开始,而在依赖之前停止。但是,有时直接依赖项是未知的。您可能只知道某种类型的对象应该先于另一种类型的对象开始。
结果:数字标识启动顺序
在这些情况下,SmartLifecycle接口定义了另一个选项,即在其超级接口Phased上定义的getPhase()方法。以下清单显示了Phased接口的定义。
SmartLifecycle接口
简单来讲,启动小order先启动:Integer.MIN_VALUE
最先启动,Integer.MAX_VALUE
最后启动。
停止时,刚好顺序相反。0
意味值是Lifecle
接口,不是smartLifecle
。负数意味着先于标准组件的启动,正数意味着后于。停止刚好相反。
延时:按照顺序的启动默认30s
顺序启动不是无限的等待有最大时长。
可以通过覆盖lifecycleProcessor
来控制。
例如时长的控制如下
开关:有些场景不需要stmart
常规的lifecycle
是加载一次的,但是stmartLifecycle
的refresh属性,会让容器在启动后再次刷新和加载。容器check,即phase为0
的不refresh,isAutoStartup()
为false不刷新
优雅的在 非web应用启停容器
本节仅适用于非Web应用程序。 Spring的基于Web的ApplicationContext实现已经具有适当的代码,可以在相关Web应用程序关闭时正常关闭Spring IoC容器。
如果您在非Web应用程序环境中(例如,在很多客户端桌面环境中)使用Spring的IoC容器,请向JVM注册一个关闭钩子。这样做可以确保正常关机,并在您的Singleton bean上调用相关的destroy方法,以便释放所有资源。您仍然必须正确配置和实现这些destroy回调。
要注册关闭挂钩,请调用在ConfigurableApplicationContext
接口上声明的registerShutdownHook()
方法,如以下示例所示:
6.2 ApplicationContextAware 和 BeanNameAware
通常用户bean是不需要和框架交互的。aware就是满足和框架交互的类
ApplicationContextAware
当一个ApplicationContext
创建一个实现了org.springframework.context.ApplicationContextAware
的接口的对象实例时,这个实例会保存一个对ApplicationContext
的引用。
ApplicationContextAware接口的函数
因此,bean可以通过ApplicationContext接口或通过将引用转换为该接口的已知子类(例如ConfigurableApplicationContext,它暴露了其他功能)来以编程方式操纵创建它们的ApplicationContext。一种用途是通过编程方式检索其他bean。有时,此功能很有用。但是,通常应避免使用它,因为它会将代码耦合到Spring,并且不遵循控制反转样式,在该样式中,将协作者作为属性提供给bean。 ApplicationContext的其他方法提供对1.文件资源的访问
、2.发布应用程序事件
、3访问MessageSource
Autowiring是获得对ApplicationContext的引用的另一种方法。传统的构造函数和byType自动装配模式(如“自动装配协作器”中所述)可以分别为构造函数参数或setter方法参数提供ApplicationContext类型的依赖项。要获得更大的灵活性,包括能够自动连接字段和使用多个参数方法,请使用基于注解
的自动装配功能。如果这样做,则将ApplicationContext自动连接到需要使用ApplicationContext类型的字段,构造函数参数或方法参数中(如果有问题的字段,构造函数或方法带有@Autowire批注)。有关更多信息,请参见使用@Autowired。
BeanNameAware
当ApplicationContext创建一个实现org.springframework.beans.factory.BeanNameAware接口的类时,该类将获得对其关联对象定义中定义的名称的引用。以下清单显示了BeanNameAware接口的定义:
和这个回调在bean初始化正常的属性之后,但是在初始化一个回调函数如InitializingBean, afterPropertiesSet
之前,或者自定义的 custom init-method。
6.3 Other Aware Interface
除了其他ApplicationContextAware
和BeanNameAware
,Spring也提供了其他aware接口。
我们不反对来使用Spring API,也不反对不遵从控制反转的风格。因此,我们推荐使用这些我们提供的基础设施bean,来编程化的和容器交互
Name | Injected Dependency | Explained in… |
---|---|---|
ApplicationContextAware | 描述 ApplicationContext. | ApplicationContextAware and BeanNameAware |
ApplicationEventPublisherAware | ApplicationContext内的事件发布者 | Additional Capabilities of the ApplicationContext |
BeanClassLoaderAware | 类加载器用来加载bean | Instantiating Beans |
BeanFactoryAware | 描述 BeanFactory. | ApplicationContextAware and BeanNameAware |
BeanNameAware | Name of the declaring bean. | ApplicationContextAware and BeanNameAware |
BootstrapContextAware | 启动资源的适配Resource adapter BootstrapContext the container runs in. Typically available only in JCA-aware ApplicationContext instances. | JCA CCI |
LoadTimeWeaverAware | AOP置入在启动阶段Defined weaver for processing class definition at load time. | Load-time Weaving with AspectJ in the Spring Framework |
MessageSourceAware | 配置消息接受策略Configured strategy for resolving messages (with support for parametrization and internationalization). | Additional Capabilities of the ApplicationContext |
NotificationPublisherAware | Spring JMX notification publisher. spring的 JMX 事件发布者 | Notifications |
ResourceLoaderAware | 资源加载器Configured loader for low-level access to resources. | Resources |
ServletConfigAware | Servelet的加载器的配置Current ServletConfig the container runs in. Valid only in a web-aware Spring ApplicationContext. | Spring MVC |
ServletContextAware | 当前运行的Servelet管理Current ServletContext the container runs in. Valid only in a web-aware Spring ApplicationContext. | Spring MVC |