(Spring-bean)生命周期接口、FactoryBean、BeanFactory交互、子bean
来源:互联网 发布:网购牛奶 知乎 编辑:程序博客网 时间:2024/05/24 03:56
依赖检查
对于部署在BeanFactory的bean的未解决的依赖,Spring有能力去检查他们的存在性。这些依赖要么是bean的JavaBean式的属性,在bean的定义中并没有为它们设置真实的值,要么是通过自动装配特性被提供。
当你想确保所有的属性(或者某一特定类型的所有属性)都被设置到bean上面的时候,这些特性就很有用了。当然,在很多情况下一个bean类的很多属性都会有缺省的值,或者一些属性并不会应用到所有的应用场景,那么这个特性的作用就有限了。依赖检查能够分别对每一个bean应用或取消应用,就像自动装配一样。缺省的是不检查依赖关系。依赖检查可以以几种不同的模式处理。在XmlBeanFactory中,通过bean定义中的dependency-check属性来指定依赖检查,这个属性有以下的值:
依赖检查模式
模式
解释
none
不进行依赖检查。没有指定值的bean属性仅仅是没有设值。
simple
对基本类型和集合(除了合作者外,比如其他的bean,所有东西)进行依赖检查。
object
对合作者进行依赖检查。
all
对合作者、基本类型和集合都进行依赖检查。
自定义bean的本质特征
生命周期接口
Spring提供了一些标志接口,用来改变BeanFactory中的bean的行为。它们包括InitializingBean和DisposableBean。实现这些接口将会导致BeanFactory调用前一个接口的afterPropertiseSet()方法,调用后一个接口destroy()方法,从而使得bean可以在初始化和析构后做一些特定的动作。
在内部,Spring使用BeanPostProcessors来处理它能找到的标志接口以及调用适当的方法。若需要自定义的特性或者其他的Spring没有提供的生命周期行为,可以实现自己的BeanPostProcessor。
InitializingBeanBean / init-method
实现org.springframework.beans.factory.InitializingBean接口允许一个bean在它所有必须的属性被BeanFactory设置后,来执行初始化的工作。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 falls.
*/
void afterPropertiesSet() throws Exception;
注意:通常InitializingBean接口的使用是能够避免的(而且不鼓励,因为没必要把代码同Spring耦合起来)。Bean的定义支持指定一个普通的初始化方法。在使用XmlBeanFactory的情况下,可以通过指定init-method属性来完成。举例来说,下面的定义:
<bean id="exampleInitBean" class="examples.ExampleBean" init-method="init"/>
public class ExampleBean{
public void init(){
//do some initialization work
}
}
同下面的完全一样:
<bean id="exampleInitBean" class="examples.AnotherExampleBean"/>
public class AnotherExampleBean implements InitializingBean{
public void afterPropertiesSet(){
//do some initialization work
}
}
但却不把代码耦合与Spring。
DisposableBean / destroy-method
实现org.springframework.beans.factory.DisposableBean接口允许一个bean,可以在包含它的BeanFactory销毁的时候得到一个回调。DisposableBean也指定了一个方法:
/**
*Invoked by a BeanFactory on destruction od a singleton
*@throws Exception in case of shutdown errors.
*Exception will get logged but not rethrown to allow other beans to release their resources too.
*/
void destroy() throws Exception;
注意:通常DisposableBean接口的使用是能够避免的(而且不鼓励,因为没必要把代码同Spring耦合起来)。Bean的定义支持指定一个普通的析构方法。在使用XmlBeanFactory的情况下,可以通过指定destroy-method属性来完成。举例来说,下面的定义:
<bean id="exampleInitBean" class="examples.ExampleBean" destroy-method="destroy"/>
public class ExampleBean{
public void cleanup(){
//do some destruction work(like closing connection)
}
}
同下面的完全一样:
<bean id="exampleInitBean" class="examples.AnotherExampleBean"/>
public class AnotherExampleBean implements DisposableBean{
public void destroy(){
//do some destruction work
}
}
但却不把代码耦合与Spring。
重要提示:当以prototype模式部署一个bean的时候,bean的生命周期将会有少许的变化。通过定义,Spring无法管理一个non-singleton/prototype bean的整个生命周期,因为当它创建之后,它被交给客户端而且容器根本不再留意它了。当说起non-singleton/prototype bean的时候,你可以把Spring的角色想象成“new”操作符的替代品。从那之后的任何生命周期方面的事情都由客户端来处理。
BeanFactoryAware
对于实现了org.springframework.beans.factory.BeanFactoryAware接口的类,当它被BeanFactory创建后,它会拥有一个指向创建它的BeanFactory的引用。
public interface BeanFactoryAware{
/**
* Callback that supplies the owning factory to a bean instance.
* <p>Invoked after population of normal bean properties but before an init
* callback like InitializingBean’s afterPropertiesSet or a custom init-method.
* @param beanFactory owing BeanFactory(may not be null).
* The bean can immediately call methods on the factory.
* @throw BeanException in case of initializaion errors
* @see BeanInitializationException
*/
void setBeanFactory(BeanFactory beanFactory) throws BeansException;
}
这允许bean可以以编程的方式操控创建它们的BeanFactory,既可以直接使用org.springframework.beans.factory.BeanFactory接口,也可以将引用强制将类型转换为已知的子类型从而获得更多的功能。这个特性主要用于编程式地取其他bean。虽然在一些场景下这个功能是有用的,但是一般来说它应该避免使用,因为它使代码与Spring耦合在一起,而且也不遵循反向控制的风格(合作者应当作属性提供给bean)。
BeanNameAware
如果一个bean实现了org.springframework.beans.factory.BeanNameAware接口,并且被部署到一个BeanFactory中,那么BeanFactory就会通过这个接口来调用bean,以便通知这个bean它被部署的id。这个回调发生在普通的bean属性设置之后,在初始化回调之前,比如InitializingBean的afterPropertiesSet方法(或者自定义的init-method)。
FactoryBean
接口org.springframework.beans.factory.FactoryBean一般由本身是工厂类的对象实现。BeanFactory接口提供了三个方法:
·Object getObject():必须返回一个这个工厂类创建的对象实例。这个实例可以是共享的(取决于这个工厂返回的是singleton还是prototype)。
·boolean isSingleton():如果Factory返回的对象是singleton,返回true,否则返回false。
·Class getObjectType():返回getObject()方法返回的对象的类型,如果类型不是预先知道的,则返回null。
子bean定义
一个bean定义可能会包含大量的配置信息,包括容器相关的信息(比如初始化方法,静态工厂方法名等等)以及构造函数参数和属性的值。一个子bean定义是一个能够从父bean定义继承配置数据的bean定义。它可以覆盖一些值,或者添加一些其他需要的值。使用父和子的bean定义可以节省很多输入工作。实际上,这就是一种模板形式。
当以编程的方式使用一个BeanFactory,子bean定义用ChildBeanDefinition类表示。大多数的用户从来不需要以这个方式使用它们,而是在类似XmlBeanFactory的BeanFactory中以声明的方式配置bean定义。在一个XmlBeanFactory的bean定义中,使用parent属性指出一个子bean定义,而父bean则作为这个属性的值。
<bean id="inheritedTestBean" class="org.springframework.beans.TestBean">
<property name="name"><value>parent</value></property>
<property name="age"><value>1</value></property>
</bean>
<bean id="inheritsWithDifferentClass" class="org.springframework.beans.DerivedTestBean" parent="inheritedTestBean" init-method="initialize">
<property name="name"><value>override</value></property>
<!--age should inherit value of 1 from parent-->
</bean>
如果子bean定义没有指定class属性,将使用父定义的class属性,当然也可以覆盖它。在后面一种情况中,子bean的class属性值必须同父bean的兼容,也就是它必须能够接受父亲的属性值。
一个子bean定义可以从父亲处继承构造函数参数,属性值以及方法,并且可以选择增加新的值。如果init-method,destroy-method和/或静态factory-method被指定了,它们就会覆盖父亲相应的设置。
剩余的设置将总是从子定义处得到:依赖,自动装配模式,依赖检查,singleton,延迟初始化。在下面的例子中父定义并没有指定class属性:
<bean id="inheritedTestBeanWithoutClass">
<property name="name"><value>parent</value></property>
<property name="age"><value>1</value></property>
</bean>
<bean id="inheritsWithClass" class="org.springframework.beans.DerivedTestBean" parent="inheritedTestBeanWithoutClass" init-method="initialize">
<property name="name"><value>override</value></property>
<!--age should inherit value of 1 from parent-->
</bean>
这个父bean就无法自己实例化;它实际上仅仅是一个纯模板或抽象bean,充当子定义的父定义。若要尝试单独使用这样的父bean(比如将它作为其他bean的ref属性而引用,或者直接使用这个父bean的id调用getBean()方法),将会导致一个错误。同样地,容器内部的preInstantiateSingletons方法会完全忽略这种既没有parent属性也没有class属性的bean定义,因为它们是不完整的。
特别注意:这里并没有办法显式地声明一个bean定义为抽象的。如果一个bean确实有一个class属性定义,那么它就能够被实例化。而且要注意XmlBeanFactory默认地将会预实例化所有的singleton的bean。因此很重要的一点是:如果你有一个(父)bean定义指定了class属性,而你又想仅仅把它当做模板使用,那么你必须保证将lazy-init属性设置为true(或将bean标记为non-singleton),否则XmlBeanFactory(以及其他可能的容器)将会预实例化它。
BeanFactory之间的交互
BeanFactory本质上不过是高级工厂的接口,它维护不同bean和它们所依赖的bean的注册。
BeanFactory使得你可以利用bean工厂读取和访问bean定义。当你使用BeanFactory的时候,你可以像下面一样创建并且读入一些XML格式的bean定义:
InputStream is = new FileInputStream("beans.xml");
XmlBeanFactory factory = new XmlBeanFactory(is);
基本上这就足够了。使用getBean(String)你可以取得你的bean实例。如果你将它定义为一个singleton(缺省的)你将会得到同一个bean的引用,如果你将singleton设置为false,那么你将会每次得到一个新的实例。在客户端的眼里BeanFactory是惊人的简单。BeanFactory接口仅仅为客户端调用提供了5个方法:
· boolean containsBean(String):如果BeanFactory包含一个与所给名称匹配的bean定义,则返回true
· Object getBean(String):返回一个以所给名字注册的bean的实例。返回一个singleton的共享的实例还是新建一个实例,这取决于bean在BeanFactory配置中如何被配置的。一个BeansException将会在下面两种情况中抛出:bean没有被找到(在这种情况下,抛出的是NoSuchBeanDefinitionException),或者在实例化和准备bean的时候发生异常。
·Object getBean(String,Class):返回一个以给定名字注册的bean。返回的bean将会被强制类型转换成给定的class。如果bean不能被类型转换,相应的异常将会被抛出(BeanNotOfRequiredTypeException)。此外getBean(String)的所有规则也同样适用这个方法(同上)
·boolean isSingleton(String):判断以给定名字注册的bean定义是一个singleton还是一个prototype。如果与给定名字相应的bean定义没有被找到,将会抛出一个异常(NoSuchBeanDefinitionException)
·String[] getAliases(String):如果给定的bean名字在bean定义中有别名,则返回这些别名
获得一个FactoryBean而不是它生成的bean
有时候我们需要向BeanFactory请求实际的FactoryBean实例本身,而不是它生产出来的bean。在调用BeanFactory(包括ApplicationContext)的getBean方法的时候,在传入的参数bean id前面加一个“&”符号,就可以做到这一点。所以,对于一个id为getBean的FactoryBean,在BeanFactory上调用getBean(“myBean”)将会返回FactoryBean的产品,而调用getBean(“&myBean”)将会返回这个FactoryBean实例本身。
- (Spring-bean)生命周期接口、FactoryBean、BeanFactory交互、子bean
- Spring中的bean,factoryBean,beanFactory
- spring中bean,factorybean与beanfactory
- spring中bean,factorybean与beanfactory
- Spring Bean在BeanFactory生命周期
- Spring bean ApplicationContext BeanFactory 生命周期
- Spring Bean的生命周期之我的理解(三)------BeanFactory和FactoryBean
- 【Spring】普通bean、FactoryBean、BeanFactory的区别与联系
- Spring BeanFactory管理Bean的生命周期
- Spring之Bean在BeanFactory的生命周期
- Spring之BeanFactory中Bean的生命周期
- spring FactoryBean配置Bean
- Spring bean 之 FactoryBean
- Spring - bean配置-FactoryBean
- Spring Bean ApplicationContext BeanFactory
- BeanFactory中Bean的生命周期
- BeanFactory中Bean的生命周期
- BeanFactory管理Bean的生命周期
- 关系运算符——条件运算
- zookeeper资料
- springMvc原理及配置详解
- Mac使用mysql中出现ERROR 1045: Access denied for user: 'root@localhost' 以及密码过期解决方法
- html一之背景图像
- (Spring-bean)生命周期接口、FactoryBean、BeanFactory交互、子bean
- iOS_消除标签栏(tabBar)顶部黑线
- C++基础
- HDU 5945 浅谈单调队列优化线性动态规划方程
- RedisTemplate访问Redis数据结构(二)——List
- 初学php
- 分布式服务框架学习笔记8 ActiveMQ入门2 发布/订阅模式
- Android如何通过代码方式打开微博 微信等应用.
- 赋值运算