spring bean 注入接口可以为接口类型吗

Spring IoC容器的设计
本文所属图书&>&
本书是国内唯一一本系统分析Spring源代码的著作,也是Spring领域的问鼎之作,由业界拥有10余年开发经验的资深Java专家亲自执笔,Java开发者社区和Spring开发者社区联袂推荐。本书第1版不仅在内容上获得了读者的广...&&
在前面的小节中,我们了解了IoC容器系列的概况。在Spring中,这个IoC容器是怎样设计的呢?我们可以看一下如图2-2所示的IoC容器的接口设计图,这张图描述了IoC容器中的主要接口设计。
下面对接口关系做一些简要的分析,可以依据以下内容来理解这张接口设计图。
m 从接口BeanFactory到HierarchicalBeanFactory,再到ConfigurableBeanFactory,是一条主要的BeanFactory设计路径。在这条接口设计路径中,BeanFactory接口定义了基本的IoC容器的规范。在这个接口定义中,包括了getBean()这样的IoC容器的基本方法(通过这个方法可以从容器中取得Bean)。而HierarchicalBeanFactory接口在继承了BeanFactory的基本接口之后,增加了getParentBeanFactory()的接口功能,使BeanFactory具备了双亲IoC容器的管理功能。在接下来的ConfigurableBeanFactory接口中,主要定义了一些对BeanFactory的配置功能,比如通过setParentBeanFactory()设置双亲IoC容器,通过addBeanPostProcessor()配置Bean后置处理器,等等。通过这些接口设计的叠加,定义了BeanFactory就是简单IoC容器的基本功能。关于BeanFactory简单IoC容器的设计,我们会在后面的内容中详细介绍。
m 第二条接口设计主线是,以ApplicationContext应用上下文接口为核心的接口设计,这里涉及的主要接口设计有,从BeanFactory到ListableBeanFactory,再到ApplicationContext,再到我们常用的WebApplicationContext或者ConfigurableApplicationContext接口。我们常用的应用上下文基本上都是ConfigurableApplicationContext或者WebApplicationContext的实现。在这个接口体系中,ListableBeanFactory和HierarchicalBeanFactory两个接口,连接BeanFactory接口定义和ApplicationConext应用上下文的接口定义。在ListableBeanFactory接口中,细化了许多BeanFactory的接口功能,比如定义了getBeanDefinitionNames()接口方法;对于HierarchicalBeanFactory接口,我们在前文中已经提到过;对于ApplicationContext接口,它通过继承MessageSource、ResourceLoader、ApplicationEventPublisher接口,在BeanFactory简单IoC容器的基础上添加了许多对高级容器的特性的支持。
&这里涉及的是主要接口关系,而具体的IoC容器都是在这个接口体系下实现的,比如DefaultListableBeanFactory,这个基本IoC容器的实现就是实现了Configurable-BeanFactory,从而成为一个简单IoC容器的实现。像其他IoC容器,比如XmlBeanFactory,都是在DefaultListableBeanFactory的基础上做扩展,同样地,ApplicationContext的实现也是如此。
&这个接口系统是以BeanFactory和ApplicationContext为核心的。而BeanFactory又是IoC容器的最基本接口,在ApplicationContext的设计中,一方面,可以看到它继承了BeanFactory接口体系中的ListableBeanFactory、AutowireCapableBeanFactory、HierarchicalBeanFactory等BeanFactory的接口,具备了BeanFactory IoC容器的基本功能;另一方面,通过继承MessageSource、ResourceLoadr、ApplicationEventPublisher这些接口,BeanFactory为ApplicationContext赋予了更高级的IoC容器特性。对于ApplicationContext而言,为了在Web环境中使用它,还设计了WebApplicationContext接口,而这个接口通过继承ThemeSource接口来扩充功能。
1. BeanFactory的应用场景
BeanFactory提供的是最基本的IoC容器的功能,关于这些功能定义,我们可以在接口BeanFactory中看到。
BeanFactory接口定义了IoC容器最基本的形式,并且提供了IoC容器所应该遵守的最基本的服务契约,同时,这也是我们使用IoC容器所应遵守的最底层和最基本的编程规范,这些接口定义勾画出了IoC的基本轮廓。很显然,在Spring的代码实现中,BeanFactory只是一个接口类,并没有给出容器的具体实现,而我们在图2-1中看到的各种具体类,比如DefaultListableBeanFactory、XmlBeanFactory、ApplicationContext等都可以看成是容器附加了某种功能的具体实现,也就是容器体系中的具体容器产品。下面我们来看看BeanFactory是怎样定义IoC容器的基本接口的。
用户使用容器时,可以使用转义符&&&来得到FactoryBean本身,用来区分通过容器来获取FactoryBean产生的对象和获取FactoryBean本身。举例来说,如果myJndiObject是一个FactoryBean,那么使用&myJndiObject得到的是FactoryBean,而不是myJndiObject这个FactoryBean产生出来的对象。关于具体的FactoryBean的设计和实现模式,我们会在后面的章节中介绍。
注意&& 理解上面这段话需要很好地区分FactoryBean和BeanFactory这两个在Spring中使用频率很高的类,它们在拼写上非常相似。一个是Factory,也就是IoC容器或对象工厂;一个是Bean。在Spring中,所有的Bean都是由BeanFactory(也就是IoC容器)来进行管理的。但对FactoryBean而言,这个Bean不是简单的Bean,而是一个能产生或者修饰对象生成的工厂Bean,它的实现与设计模式中的工厂模式和修饰器模式类似。
BeanFactory接口设计了getBean方法,这个方法是使用IoC容器API的主要方法,通过这个方法,可以取得IoC容器中管理的Bean,Bean的取得是通过指定名字来索引的。如果需要在获取Bean时对Bean的类型进行检查,BeanFactory接口定义了带有参数的getBean方法,这个方法的使用与不带参数的getBean方法类似,不同的是增加了对Bean检索的类型的要求。
用户可以通过BeanFactory接口方法中的getBean来使用Bean名字,从而在获取Bean时,如果需要获取的Bean是prototype类型的,用户还可以为这个prototype类型的Bean生成指定构造函数的对应参数。这使得在一定程度上可以控制生成prototype类型的Bean。有了BeanFactory的定义,用户可以执行以下操作:
&通过接口方法containsBean让用户能够判断容器是否含有指定名字的Bean。
&通过接口方法isSingleton来查询指定名字的Bean是否是Singleton类型的Bean。对于Singleton属性,用户可以在BeanDefinition中指定。
&通过接口方法isPrototype来查询指定名字的Bean是否是prototype类型的。与Singleton属性一样,这个属性也可以由用户在BeanDefinition中指定。
&通过接口方法isTypeMatch来查询指定了名字的Bean的Class类型是否是特定的Class类型。这个Class类型可以由用户来指定。
&通过接口方法getType来查询指定名字的Bean的Class类型。
&通过接口方法getAliases来查询指定了名字的Bean的所有别名,这些别名都是用户在BeanDefinition中定义的。
这些定义的接口方法勾画出了IoC容器的基本特性。因为这个BeanFactory接口定义了IoC容器,所以下面给出它定义的全部内容供大家参考,如代码清单2-1所示。
代码清单2-1&& BeanFactory接口
public interface BeanFactory {
&String FACTORY_BEAN_PREFIX = &&&;
&Object getBean(String name) throws BeansE
&&T& T getBean(String name, Class&T& requiredType) throws BeansE
&Object getBean(String name, Object... args) throws BeansE
&boolean containsBean(String name);
&boolean isSingleton(String name) throws NoSuchBeanDefinitionE
&boolean isPrototype(String name) throws NoSuchBeanDefinitionE
&boolean isTypeMatch(String name, Class targetType) throws
&NoSuchBeanDefinitionE
&Class getType(String name) throws NoSuchBeanDefinitionE
&String[] getAliases(String name);
可以看到,这里定义的只是一系列的接口方法,通过这一系列的BeanFactory接口,可以使用不同的Bean的检索方法,很方便地从IoC容器中得到需要的Bean,从而忽略具体的IoC容器的实现,从这个角度上看,这些检索方法代表的是最为基本的容器入口。
2. BeanFactory容器的设计原理
BeanFactory接口提供了使用IoC容器的规范。在这个基础上,Spring还提供了符合这个IoC容器接口的一系列容器的实现供开发人员使用。我们以 XmlBeanFactory的实现为例来说明简单IoC容器的设计原理。如图2-3所示为XmlBeanFactory设计的类继承关系。
可以看到,作为一个简单IoC容器系列最底层实现的XmlBeanFactory,与我们在Spring应用中用到的那些上下文相比,有一个非常明显的特点:它只提供最基本的IoC容器的功能。理解这一点有助于我们理解ApplicationContext与基本的BeanFactory之间的区别和联系。我们可以认为直接的BeanFactory实现是IoC容器的基本形式,而各种ApplicationContext的实现是IoC容器的高级表现形式。关于ApplicationContext的分析,以及它与BeanFactory相比的增强特性都会在下面进行详细的分析。
让我们好好地看一下图2-3中的继承关系,从中可以清楚地看到类之间的联系,它们都是IoC容器系列的组成部分。在设计这个容器系列时,我们可以从继承体系的发展上看到IoC容器各项功能的实现过程。如果要扩展自己的容器产品,建议读者最好在继承体系中检查一下,看看Spring是不是已经提供了现成的或相近的容器实现供我们参考。下面就从我们比较熟悉的XmlBeanFactory的实现入手进行分析,来看看一个基本的IoC容器是怎样实现的。
仔细阅读XmlBeanFactory的,在一开始的注释里会看到对 XmlBeanFactory功能的简要说明,从代码的注释还可以看到,这是Rod Johnson在2001年就写下的代码,可见这个类应该是Spring的元老类了。XmlBeanFactory继承自DefaultListableBeanFactory这个类,后者非常重要,是我们经常要用到的一个IoC容器的实现,比如在设计应用上下文ApplicationContext时就会用到它。我们会看到这个DefaultListableBeanFactory实际上包含了基本IoC容器所具有的重要功能,也是在很多地方都会用到的容器系列中的一个基本产品。
在Spring中,实际上是把DefaultListableBeanFactory作为一个默认的功能完整的IoC容器来使用的。XmlBeanFactory在继承了DefaultListableBeanFactory容器的功能的同时,增加了新的功能,这些功能很容易从XmlBeanFactory的名字上猜到。它是一个与XML相关的BeanFactory,也就是说它是一个可以读取以XML文件方式定义的BeanDefinition的IoC容器。
这些实现XML读取的功能是怎样实现的呢?对这些XML文件定义信息的处理并不是由XmlBeanFactory直接完成的。在XmlBeanFactory中,初始化了一个 XmlBeanDefinitionReader对象,有了这个Reader对象,那些以XML方式定义的BeanDefinition就有了处理的地方。我们可以看到,对这些XML形式的信息的处理实际上是由这个XmlBeanDefinitionReader来完成的。
构造 XmlBeanFactory这个IoC容器时,需要指定BeanDefinition的信息来源,而这个信息来源需要封装成Spring中的Resource类来给出。Resource是Spring用来封装I/O操作的类。比如,我们的BeanDefinition信息是以XML文件形式存在的,那么可以使用像&ClassPath-Resource res = new ClassPathResource(&beans.xml&);&这样具体的ClassPathResource来构造需要的Resource,然后将Resource作为构造参数传递给XmlBeanFactory构造函数。这样,IoC容器就可以方便地定位到需要的BeanDefinition信息来对Bean完成容器的初始化和依赖注入过程。
XmlBeanFactory的功能是建立在DefaultListableBeanFactory这个基本容器的基础上的,并在这个基本容器的基础上实现了其他诸如XML读取的附加功能。对于这些功能的实现原理,看一看XmlBeanFactory的代码实现就能很容易地理解。如代码清单2-2所示,在XmlBeanFactory构造方法中需要得到Resource对象。对XmlBeanDefinitionReader对象的初始化,以及使用这个对象来完成对loadBeanDefinitions的调用,就是这个调用启动从Resource中载入BeanDefinitions的过程,LoadBeanDefinitions同时也是IoC容器初始化的重要组成部分。
代码清单2-2&& XmlBeanFactory的实现
public class XmlBeanFactory extends DefaultListableBeanFactory {
private final XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(this);
public XmlBeanFactory(Resource resource) throws BeansException {
&this(resource, null);
public XmlBeanFactory(Resource resource, BeanFactory parentBeanFactory)
&throws BeansException {
&super(parentBeanFactory);
&this.reader.loadBeanDefinitions(resource);
我们看到XmlBeanFactory使用了DefaultListableBeanFactory作为基类,DefaultListable-BeanFactory是很重要的一个IoC实现,在其他IoC容器中,比如ApplicationContext,其实现的基本原理和XmlBeanFactory一样,也是通过持有或者扩展DefaultListableBeanFactory来获得基本的IoC容器的功能的。
参考XmlBeanFactory的实现,我们以的方式使用DefaultListableBeanFactory。从中我们可以看到IoC容器使用的一些基本过程。尽管我们在应用中使用IoC容器时很少会使用这样原始的方式,但是了解一下这个基本过程,对我们了解IoC容器的工作原理是非常有帮助的。因为这个式使用容器的过程,很清楚揭示了在IoC容器实现中的那些关键的类(比如Resource、DefaultListableBeanFactory和BeanDefinitionReader)之间的相互关系,例如它们是如何把IoC容器的功能解耦的,又是如何结合在一起为IoC容器服务的,等等。在代码清单2-3中可以看到编程式使用IoC容器的过程。
代码清单2-3&& 编程式使用IoC容器
ClassPathResource res = new ClassPathResource(&beans.xml&);
DefaultListableBeanFactory factory = new DefaultListableBeanFactory();
XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(factory);
reader.loadBeanDefinitions(res);
这样,我们就可以通过factory对象来使用 DefaultListableBeanFactory这个IoC容器了。在使用IoC容器时,需要如下几个步骤:
1)创建IoC配置文件的抽象资源,这个抽象资源包含了BeanDefinition的定义信息。
2)创建一个BeanFactory,这里使用DefaultListableBeanFactory。
3)创建一个载入BeanDefinition的读取器,这里使用XmlBeanDefinitionReader来载入XML文件形式的BeanDefinition,通过一个回调配置给BeanFactory。
4)从定义好的资源位置读入配置信息,具体的解析过程由XmlBeanDefinitionReader来完成。完成整个载入和注册Bean定义之后,需要的IoC容器就建立起来了。这个时候就可以直接使用IoC容器了。
3. ApplicationContext的应用场景
上一节中我们了解了IoC容器建立的基本步骤。理解这些步骤之后,可以很方便地通过编程的方式来手工控制这些配置和容器的建立过程了。但是,在Spring中,已经为用户提供了许多已经定义好的容器实现,而不需要开发人员事必躬亲。相比那些简单拓展BeanFactory的基本IoC容器,开发人员常用的ApplicationContext除了能够提供前面介绍的容器的基本功能外,还为用户提供了以下的附加服务,可以让客户更方便地使用。所以说,ApplicationContext是一个高级形态意义的IoC容器,如图2-4所示,可以看到ApplicationContext在BeanFactory的基础上添加的附加功能,这些功能为ApplicationContext提供了以下BeanFactory不具备的新特性。
&支持不同的信息源。我们看到ApplicationContext扩展了MessageSource接口,这些信息源的扩展功能可以支持国际化的实现,为开发多语言版本的应用提供服务。
&访问资源。这一特性体现在对ResourceLoader和Resource的支持上,这样我们可以从不同地方得到Bean定义资源。这种抽象使用户程序可以灵活地定义Bean定义信息,尤其是从不同的I/O途径得到Bean定义信息。这在接口关系上看不出来,不过一般来说,具体ApplicationContext都是继承了DefaultResourceLoader的子类。因为DefaultResourceLoader是AbstractApplicationContext的基类,关于Resource在IoC容器中的使用,后面会有详细的讲解。
&支持应用事件。继承了接口ApplicationEventPublisher,从而在上下文中引入了事件机制。这些事件和Bean的生命周期的结合为Bean的管理提供了便利。
&在ApplicationContext中提供的附加服务。这些服务使得基本IoC容器的功能更丰富。因为具备了这些丰富的附加功能,使得ApplicationContext与简单的BeanFactory相比,对它的使用是一种面向框架的使用风格,所以一般建议在开发应用时使用ApplicationContext作为IoC容器的基本形式。
4. ApplicationContext容器的设计原理
在ApplicationContext容器中,我们以常用的FileSystemXmlApplicationContext的实现为例来说明ApplicationContext容器的设计原理。
在FileSystemXmlApplicationContext的设计中,我们看到ApplicationContext应用上下文的主要功能已经在FileSystemXmlApplicationContext的基类AbstractXmlApplicationContext中实现了,在FileSystemXmlApplicationContext中,作为一个具体的应用上下文,只需要实现和它自身设计相关的两个功能。
一个功能是,如果应用直接使用FileSystemXmlApplicationContext,对于实例化这个应用上下文的支持,同时启动IoC容器的refresh()过程。这在FileSystemApplicationContext的代码实现中可以看到,代码如下:
public FileSystemXmlApplicationContext(String[] configLocations, boolean refresh,
ApplicationContext parent) throws BeansException {
&super(parent);
&setConfigLocations(configLocations);
&if (refresh) {
&&&& refresh();
这个refresh()过程会牵涉IoC容器启动的一系列复杂操作,同时,对于不同的容器实现,这些操作都是类似的,因此在基类中将它们封装好。所以,我们在FileSystemXml的设计中看到的只是一个简单的调用。关于这个refresh()在IoC容器启动时的具体实现,是后面要分析的主要内容,这里就不详细展开了。
另一个功能是与FileSystemXmlApplicationContext设计具体相关的功能,这部分与怎样从文件中加载XML的Bean定义资源有关。
通过这个过程,可以为在文件系统中读取以XML形式存在的BeanDefinition做准备,因为不同的应用上下文实现对应着不同的读取BeanDefinition的方式,在FileSystemXml-ApplicationContext中的实现代码如下:
protected Resource getResourceByPath(String path) {
&if (path != null && path.startsWith(&/&)) {
&&&& path = path.substring(1);
&return new FileSystemResource(path);
可以看到,调用这个方法,可以得到FileSystemResource的资源定位。
您对本文章有什么意见或着疑问吗?请到您的关注和建议是我们前行的参考和动力&&
(window.slotbydup=window.slotbydup || []).push({
id: '2467141',
container: s,
size: '1000,90',
display: 'inlay-fix'
您的浏览器不支持嵌入式框架,或者当前配置为不显示嵌入式框架。
(window.slotbydup=window.slotbydup || []).push({
id: '2467142',
container: s,
size: '1000,90',
display: 'inlay-fix'
(window.slotbydup=window.slotbydup || []).push({
id: '2467143',
container: s,
size: '1000,90',
display: 'inlay-fix'
(window.slotbydup=window.slotbydup || []).push({
id: '2467148',
container: s,
size: '1000,90',
display: 'inlay-fix'<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
您的访问请求被拒绝 403 Forbidden - ITeye技术社区
您的访问请求被拒绝
亲爱的会员,您的IP地址所在网段被ITeye拒绝服务,这可能是以下两种情况导致:
一、您所在的网段内有网络爬虫大量抓取ITeye网页,为保证其他人流畅的访问ITeye,该网段被ITeye拒绝
二、您通过某个代理服务器访问ITeye网站,该代理服务器被网络爬虫利用,大量抓取ITeye网页
请您点击按钮解除封锁&<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
您的访问请求被拒绝 403 Forbidden - ITeye技术社区
您的访问请求被拒绝
亲爱的会员,您的IP地址所在网段被ITeye拒绝服务,这可能是以下两种情况导致:
一、您所在的网段内有网络爬虫大量抓取ITeye网页,为保证其他人流畅的访问ITeye,该网段被ITeye拒绝
二、您通过某个代理服务器访问ITeye网站,该代理服务器被网络爬虫利用,大量抓取ITeye网页
请您点击按钮解除封锁&不知道为什么看着Spring的源码,感触最深的是Spring对概念的抽象,所以我就先学接口了.
BeanFactory是Spring IOC实现的基础,这边定义了一系列的接口,我们通过这些接口的学习,可以大致了解BeanFactory体系各接口如何分工合作.
为学习具体实现打下基础.毕竟这边逻辑复杂,涉及的概念很多.
BeanFactory 是Spring&bean容器的根接口.提供获取bean,是否包含bean,是否单例与原型,获取bean类型,bean 别名的api.
-- AutowireCapableBeanFactory 添加集成其他框架功能.如果集成WebWork则可以使用Spring对Actions等进行管理.
-- HierarchicalBeanFactory 提供父容器的访问功能
-- -- ConfigurableBeanFactory 如名,提供factory的配置功能,眼花缭乱好多api
-- -- -- ConfigurableListableBeanFactory 集大成者,提供解析,修改bean定义,并与初始化单例.
-- ListableBeanFactory 提供容器内bean实例的枚举功能.这边不会考虑父容器内的实例.
看到这边,我们是不是想起了设计模式原则里的接口隔离原则
&Interface Segregation Principle(ISP):客户端不应该依赖它不需要的接口;类间的依赖关系应该建立在最小的接口上
对这个有兴趣的话,找度娘或者看看这个
这边清晰地定义了如下的体系:
  根接口BeanFactory(基础容器)
  第二层:&第三方集成,继承体系,遍历bean
  第三层: 配置功能
  第四层: 配置+迭代
接下来具体分析下各个接口吧(顺便做目录):
1. BeanFactory
2. AutowireCapableBeanFactory
3. HierarchicalBeanFactory
4. ListableBeanFactory
5. ConfigurableBeanFactory
6. ConfigurableListableBeanFactory
1. BeanFactory
BeanFactory是Spring bean容器的根接口.
每个bean都是通过string类型bean name进行标识.这边提供了设计模式单例,原型的替代实现.
  如果bean name配置为单例,应用内只会获取到一个实例.如果配置为原型,那么可以实例化好后填充属性(基于用户的配置).
BeanFactory作为应用集中配置管理的地方,极大简便应用开发,这样开发人员可以集中与业务.
BeanFactory需要管理bean的生命周期,比如初始化时需要按顺序实现如下接口:
  1. BeanNameAware's {@code setBeanName}
  2. BeanClassLoaderAware's {@code setBeanClassLoader}
  3. BeanFactoryAware's {@code setBeanFactory}
  4. ResourceLoaderAware's {@code setResourceLoader}仅对application context有效
  5. ApplicationEventPublisherAware's {@code setApplicationEventPublisher}仅对application context有效
  6. MessageSourceAware's {@code setMessageSource}仅对application context有效
  7. ApplicationContextAware's {@code setApplicationContext}仅对application context有效
  8. ServletContextAware's {@code setServletContext}仅对application context有效
  9. {@code postProcessBeforeInitialization} methods of BeanPostProcessors
  10. InitializingBean's {@code afterPropertiesSet}
  11. a custom init-method definition xml中配置的init-method
  12. {@code postProcessAfterInitialization} methods of BeanPostProcessors
还有关闭容器的接口:
  1. DisposableBean's {@code destroy}
  2. a custom destroy-method definition xml配置中的destroy-method
接口里定义了一个变量String FACTORY_BEAN_PREFIX = "&";
  这是用来区分是获取FactoryBean还是FactoryBean的createBean创建的实例.如果&开始则获取FactoryB否则获取createBean创建的实例.
我们来看下定义的方法:
  a, 获取bean,这边可以实现单例,原型
    Object getBean(String name) throws BeansE 可以用别名查找哦
    &T& T getBean(String name, Class&T& requiredType) throws BeansE
    &T& T getBean(Class&T& requiredType) throws BeansE 这边的类型可以是接口或者子类,但不能是null
    Object getBean(String name, Object... args) throws BeansE
  b, 判断是否包含bean.陷阱出现:这边不管类是否抽象类,懒加载,是否在容器范围内,只要符合都返回true,所以这边true,不一定能从getBean获取实例
    boolean containsBean(String name);
  c, 单例,原型,bean类型的判断
    boolean isSingleton(String name) throws NoSuchBeanDefinitionE
    boolean isPrototype(String name) throws NoSuchBeanDefinitionE
    boolean isTypeMatch(String name, Class&?& targetType) throws NoSuchBeanDefinitionE
  d, 获取bean 的类型,别名
    Class&?& getType(String name) throws NoSuchBeanDefinitionE
    String[] getAliases(String name);
2. AutowireCapableBeanFactory
在BeanFactory基础上实现对已存在实例的管理.
可以使用这个接口集成其它框架,捆绑并填充并不由Spring管理生命周期并已存在的实例.像集成WebWork的Actions 和Tapestry Page就很实用.
一般应用开发者不会使用这个接口,所以像ApplicationContext这样的外观实现类不会实现这个接口,如果真手痒痒可以通过ApplicationContext的getAutowireCapableBeanFactory接口获取.&
这边定义了5种自动装配策略:不注入AUTOWIRE_NO,使用bean name策略装配AUTOWIRE_BY_NAME,使用类型装配策略AUTOWIRE_BY_TYPE,使用构造器装配策略AUTOWIRE_CONSTRUCTOR,自动装配策略AUTOWIRE_AUTODETECT
  这边的自动策略是先尝试构造器,然后才是byType.这边应该是跟xml配置文件中的装配策略对应.
继续看定义的api:
  a,&创建和填充外部bean实例的典型方法
    &T& T createBean(Class&T& beanClass) throws BeansE
    void autowireBean(Object existingBean) throws BeansE // 使用autowireBeanProperties装配属性
    Object configureBean(Object existingBean, String beanName) throws BeansE //&自动装配属性,填充属性值,使用诸如setBeanName,setBeanFactory这样的工厂回调填充属性,最好还要调用post processor
    Object resolveDependency(DependencyDescriptor descriptor, String beanName) throws BeansE
  b,&在bean的生命周期进行细粒度控制的专门方法
    Object createBean(Class&?& beanClass, int autowireMode, boolean dependencyCheck) throws BeansE // 会执行bean完整的初始化,包括BeanPostProcessors和initializeBean
    Object autowire(Class&?& beanClass, int autowireMode, boolean dependencyCheck) throws BeansE
    void autowireBeanProperties(Object existingBean, int autowireMode, boolean dependencyCheck)&throws BeansE
    void applyBeanPropertyValues(Object existingBean, String beanName) throws BeansE
    Object initializeBean(Object existingBean, String beanName) throws BeansE
    Object applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName)&throws BeansE
    Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName)&throws BeansE
    Object resolveDependency(DependencyDescriptor descriptor, String beanName,&Set&String& autowiredBeanNames, TypeConverter typeConverter) throws BeansE
3. HierarchicalBeanFactory
&提供父容器的访问功能.至于父容器的设置,需要找ConfigurableBeanFactory的setParentBeanFactory(接口把设置跟获取给拆开了!).
这边可说的不多,直接上api:
  a, 获取父容器 bean factory
    BeanFactory getParentBeanFactory();
  b, 判断当前容器是否保护bean
    boolean containsLocalBean(String name);
4. ListableBeanFactory
获取bean时,Spring 鼓励使用这个接口定义的api. 还有个Beanfactory方便使用.其他的4个接口都是不鼓励使用的.
提供容器中bean迭代的功能,不再需要一个个bean地查找.比如可以一次获取全部的bean(太暴力了),根据类型获取bean.在看SpringMVC时,扫描包路径下的具体实现策略就是使用的这种方式(那边使用的是BeanFactoryUtils封装的api).
&如果同时实现了HierarchicalBeanFactory,返回值不会考虑父类BeanFactory,只考虑当前factory定义的类.当然也可以使用BeanFactoryUtils辅助类来查找祖先工厂中的类.&
&这个接口中的方法只会考虑本factory定义的bean.这些方法会忽略ConfigurableBeanFactory的registerSingleton注册的单例bean(getBeanNamesOfType和getBeansOfType是例外,一样会考虑手动注册的单例).当然BeanFactory的getBean一样可以透明访问这些特殊bean.当然在典型情况下,所有的bean都是由external bean定义,所以应用不需要顾虑这些差别.
注意:getBeanDefinitionCount和containsBeanDefinition的实现方法因为效率比较低,还是少用为好.
继续上api吧
  a, 暴力获取全部bean的属性:
    boolean containsBeanDefinition(String beanName); &//是否包含bean
    int getBeanDefinitionCount(); // 当前factory中定义的bean数量
    String[] getBeanDefinitionNames(); // 获取当前工厂中定义的所有bean 的name
  b, 根据bean 的类型获取bean
    这边的方法仅检查顶级bean.它不会检查嵌套的bean.FactoryBean创建的bean会匹配为FactoryBean而不是原始类型.
    一样不会考虑父factory中的bean,非要用可以通过BeanFactoryUtils中的beanNamesForTypeIncludingAncestors.    其他方式注册的单例这边会纳入判断.    这个版本的getBeanNamesForType会匹配所有类型的bean,包括单例,原型,FactoryBean.返回的bean names会根据backend 配置的进行排序.
    String[] getBeanNamesForType(Class&?& type); //&获取给定类型的bean names(包括子类),通过bean 定义或者FactoryBean的getObjectType判断.
    String[] getBeanNamesForType(Class&?& type, boolean includeNonSingletons, boolean allowEagerInit);
    &T& Map&String, T& getBeansOfType(Class&T& type) throws BeansE // 如果保护懒加载的类,FactoryBean初始化的类和工厂方法初始化的类会被初始化.就是说执行这个方法会执行对应的初始化.
    &T& Map&String, T& getBeansOfType(Class&T& type, boolean includeNonSingletons, boolean allowEagerInit)&throws BeansE
  c, 查找使用注解的类
    Map&String, Object& getBeansWithAnnotation(Class&? extends Annotation& annotationType)&throws BeansE
  d,&查找一个类上的注解,如果找不到,父类,接口使用注解也算.
    &A extends Annotation& A findAnnotationOnBean(String beanName, Class&A& annotationType);
5. ConfigurableBeanFactory
定义BeanFactory的配置.
这边定义了太多太多的api,比如类加载器,类型转化,属性编辑器,BeanPostProcessor,作用域,bean定义,处理bean依赖关系,合并其他ConfigurableBeanFactory,bean如何销毁.
定义了两个作用域: 单例和原型.可以通过registerScope来添加.
  SCOPE_SINGLETON,SCOPE_PROTOTYPE
这边定义了好多好多的api,所以我们这边只讲业务,具体的api看文末的附录吧:
  a, 父容器设置.而且一旦设置了就不让修改
  b, 类加载器设置与获取.默认使用当前线程中的类加载器
  c, 为了类型匹配,搞个临时类加载器.好在一般情况为null,使用上面定义的标准加载器  
  d, 是否需要缓存bean metadata,比如bean difinition 和 解析好的classes.默认开启缓存
  e, 定义用于解析bean definition的表达式解析器
  f, 类型转化器
  g, 属性编辑器
  h,&BeanFactory用来转换bean属性值或者参数值的自定义转换器
  i,string值解析器(想起mvc中的ArgumentResolver了)
  j,大boss BeanPostProcessor用于增强bean初始化功能 
  k,作用域定义
  l,访问权限控制
  m, 合并其他ConfigurableBeanFactory的配置,包括上面说到的BeanPostProcessor,作用域等
  n, bean定义处理
  o, bean创建状态控制.在解决循环依赖时有使用
  p, 处理bean依赖问题
  q, bean生命周期管理-- 销毁bean
6. ConfigurableListableBeanFactory
&提供bean definition的解析,注册功能,再对单例来个预加载(解决循环依赖问题).&
貌似我们一般开发就会直接定义这么个接口了事.而不是像Spring这样先根据使用情况细分那么多,到这边再合并
  a, 设置忽略的依赖关系,注册找到的特殊依赖
    void ignoreDependencyType(Class&?& type); // 忽略类型
    void ignoreDependencyInterface(Class&?& ifc); // 忽略接口
    void registerResolvableDependency(Class&?& dependencyType, Object autowiredValue);
    boolean isAutowireCandidate(String beanName, DependencyDescriptor descriptor)&throws NoSuchBeanDefinitionE
  b, 获取bean定义 (可以访问属性值跟构造方法的参数值)
    BeanDefinition getBeanDefinition(String beanName) throws NoSuchBeanDefinitionE
  c, 锁定配置信息.在调用refresh时会使用到.
    void freezeConfiguration();
    boolean isConfigurationFrozen();
  d, 预加载不是懒加载的单例.用于解决循环依赖问题
    void preInstantiateSingletons() throws BeansE
附录--ConfigureableBeanFactory中定义的api:
  a, 父容器设置.而且一旦设置了就不让修改
    void setParentBeanFactory(BeanFactory parentBeanFactory) throws IllegalStateE
  b, 类加载器设置与获取.默认使用当前线程中的类加载器
    void setBeanClassLoader(ClassLoader beanClassLoader);
    ClassLoader getBeanClassLoader();
  c, 为了类型匹配,搞个临时类加载器.好在一般情况为null,使用上面定义的标准加载器  
    void setTempClassLoader(ClassLoader tempClassLoader);
    ClassLoader getTempClassLoader();
  d, 是否需要缓存bean metadata,比如bean difinition 和 解析好的classes.默认开启缓存
    void setCacheBeanMetadata(boolean cacheBeanMetadata);
    boolean isCacheBeanMetadata();
  e, 定义用于解析bean definition的表达式解析器
    void setBeanExpressionResolver(BeanExpressionResolver resolver);
    BeanExpressionResolver getBeanExpressionResolver();
  f, 类型转化器
    void setConversionService(ConversionService conversionService);
    ConversionService getConversionService();
  g, 属性编辑器
    void addPropertyEditorRegistrar(PropertyEditorRegistrar registrar);
    void registerCustomEditor(Class&?& requiredType, Class&? extends PropertyEditor& propertyEditorClass);
    void copyRegisteredEditorsTo(PropertyEditorRegistry registry);
  h,&BeanFactory用来转换bean属性值或者参数值的自定义转换器
    void setTypeConverter(TypeConverter typeConverter);
    TypeConverter getTypeConverter();
  i,string值解析器(想起mvc中的ArgumentResolver了)
    void addEmbeddedValueResolver(StringValueResolver valueResolver);
    String resolveEmbeddedValue(String value);
  j,大boss BeanPostProcessor用于增强bean初始化功能
    void addBeanPostProcessor(BeanPostProcessor beanPostProcessor);
    int getBeanPostProcessorCount();    
  k,作用域定义
    void registerScope(String scopeName, Scope scope);
    String[] getRegisteredScopeNames();
    Scope getRegisteredScope(String scopeName);
  l,访问权限控制
    AccessControlContext getAccessControlContext();
  m, 合并其他ConfigurableBeanFactory的配置,包括上面说到的BeanPostProcessor,作用域等
    void copyConfigurationFrom(ConfigurableBeanFactory otherFactory);
  n, bean定义处理
    void registerAlias(String beanName, String alias) throws BeanDefinitionStoreE // 注册别名
    void resolveAliases(StringValueResolver valueResolver);
    BeanDefinition getMergedBeanDefinition(String beanName) throws NoSuchBeanDefinitionE // 合并bean定义,包括父容器的
    boolean isFactoryBean(String name) throws NoSuchBeanDefinitionE // 是否是FactoryBean类型
  o, bean创建状态控制.在解决循环依赖时有使用
    void setCurrentlyInCreation(String beanName, boolean inCreation);
    boolean isCurrentlyInCreation(String beanName);
  p, 处理bean依赖问题
    void registerDependentBean(String beanName, String dependentBeanName);
    String[] getDependentBeans(String beanName);
    String[] getDependenciesForBean(String beanName);
  q, bean生命周期管理-- 销毁bean
    void destroyBean(String beanName, Object beanInstance);
    void destroyScopedBean(String beanName);
    void destroySingletons();
阅读(...) 评论()}

我要回帖

更多关于 spring bean生命周期 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信