BeanFactory简单介绍

一、 BeanFactory

  BeanFactory,以Factory结尾,表示它是一个工厂类(接口), 它负责生产和管理bean的一个工厂。在Spring中,BeanFactory是IOC容器的核心接口,它的职责包括:实例化、定位、配置应用程序中的对象及建立这些对象间的依赖。

      BeanFactory只是个接口,并不是IOC容器的具体实现,但是Spring容器给出了很多种实现,如 DefaultListableBeanFactory、XmlBeanFactory、ApplicationContext等,其中XmlBeanFactory就是常用的一个,该实现将以XML方式描述组成应用的对象及对象间的依赖关系。XmlBeanFactory类将持有此XML配置元数据,并用它来构建一个完全可配置的系统或应用。   

     它为其他具体的IOC容器提供了最基本的规范,例如DefaultListableBeanFactory,XmlBeanFactory,ApplicationContext 等具体的容器都是实现了BeanFactory,再在其基础之上附加了其他的功能。

     原始的BeanFactory无法支持spring的许多插件,如AOP功能、Web应用等。ApplicationContext接口,它由BeanFactory接口派生而来。现在一般使用ApplicationnContext,其不但包含了BeanFactory的作用,同时还进行更多的扩展。  

     BeanFactory实际上是实例化,配置和管理众多bean的容器。 这些bean通常会彼此合作,因而它们之间会产生依赖。 BeanFactory使用的配置数据可以反映这些依赖关系中,一个BeanFactory可以用接口org.springframework.beans.factory.BeanFactory表示, 这个接口有多个实现。 最常使用的的简单的BeanFactory实现是org.springframework.beans.factory.xml.XmlBeanFactory。 

      几乎所有被BeanFactory管理的用户代码都不需要知道BeanFactory, 但是BeanFactory还是以某种方式实例化。如我们执行了以下代码:

InputStream is = new FileInputStream("beans.xml");
XmlBeanFactory factory = new XmlBeanFactory(is);

//或者

ClassPathResource res = new ClassPathResource("beans.xml");
XmlBeanFactory factory = new XmlBeanFactory(res);

//或者

ClassPathXmlApplicationContext appContext = new ClassPathXmlApplicationContext(
        new String[] {"applicationContext.xml", "applicationContext-part2.xml"});
// of course, an ApplicationContext is just a BeanFactory
BeanFactory factory = (BeanFactory) appContext;

很多情况下,用户代码不需要实例化BeanFactory, 因为Spring框架代码会做这件事。

二、生命周期接口

     Spring提供了一些标志接口,用来改变BeanFactory中的bean的行为。 它们包括InitializingBean和DisposableBean。 实现这些接口将会导致BeanFactory调用前一个接口的afterPropertiesSet()方法, 调用后一个接口destroy()方法,从而使得bean可以在初始化和析构后做一些特定的动作。

1、 InitializingBean / init-method

        实现org.springframework.beans.factory.InitializingBean 接口允许一个bean在它的所有必须的属性被BeanFactory设置后, 来执行初始化的工作。InitializingBean接口仅仅制定了一个方法:

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
    }
}

2、DisposableBean / destroy-method

     实现org.springframework.beans.factory.DisposableBean接口允许一个bean, 可以在包含它的BeanFactory销毁的时候得到一个回调。DisposableBean也只指定了一个方法:

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)
    }
}

三、其他类介绍

1. BeanFactoryAware

对于实现了org.springframework.beans.factory.BeanFactoryAware接口的类, 当它被BeanFactory创建后,它会拥有一个指向创建它的BeanFactory的引用。这允许bean可以以编程的方式操控创建它们的BeanFactory,但是一般来说它应该避免使用,因为它使代码与Spring耦合在一起。

2、获得一个FactoryBean而不是它生成的bean

       有些时候我们需要向BeanFactory请求实际的FactoryBean实例本身, 而不是它生产出来的bean。在调用BeanFactory (包括ApplicationContext)的getBean方法的时候, 在传入的参数bean id前面加一个“&”符号,就可以做到这一点。所以,对于一个id为getBean的FactoryBean, 在BeanFactory上调用getBean("myBean")将会返回FactoryBean的产品,而调用getBean("&myBean")将会返回这个FactoryBean实例本身。

3、介绍ApplicationContext

Context包的基础是位于org.springframework.context包中的ApplicationContext接口。它是由BeanFactory接口集成而来,提供BeanFactory所有的功能。为了以一种更向面向框架的方式工作,context包使用分层和有继承关系的上下文类,包括:

  • MessageSource, 提供对i18n消息的访问

  • 资源访问, 比如URL和文件

  • 事件传递给实现了ApplicationListener接口的bean

  • 载入多个(有继承关系)上下文类,使得每一个上下文类都专注于一个特定的层次,比如应用的web层

    因为ApplicationContext包括了BeanFactory所有的功能,所以通常建议先于BeanFactory使用,除了有限的一些场合比如在一个Applet中,内存的消耗是关键的,每kb字节都很重要。接下来的章节将叙述ApplicationContext在BeanFactory的基本能力上增建的功能。

(1)使用MessageSource

ApplicationContext接口继承MessageSource接口,所以提供了messaging功能(i18n或者国际化)同NestingMessageSource一起使用,就能够处理分级的信息,这些是Spring提供的处理信息的基本接口。让我们很快浏览一下这里定义的方法:

  • String getMessage (String code, Object[] args, String default, Locale loc):这个方法是从MessageSource取得信息的基本方法。如果对于指定的locale没有找到信息,则使用默认的信息。传入的参数args被用来代替信息中的占位符,这个是通过Java标准类库的MessageFormat实现的。

  • String getMessage (String code, Object[] args, Locale loc):本质上和上一个方法是一样的,除了一点区别:没有默认值可以指定;如果信息找不到,就会抛出一个NoSuchMessageException。

  • String getMessage(MessageSourceResolvable resolvable, Locale locale):上面两个方法使用的所有属性都是封装到一个叫做MessageSourceResolvable的类中,你可以通过这个方法直接使用它。

当ApplicationContext被加载的时候,它会自动查找在context中定义的MessageSource bean。这个bean必须叫做messageSource。

(2)事件传递

     ApplicationContext中的事件处理是通过ApplicationEvent类和ApplicationListener接口来提供的。如果上下文中部署了一个实现了ApplicationListener接口的bean,每次一个ApplicationEvent发布到ApplicationContext时,那个bean就会被通知。

(3)在Spring中使用资源

     很多应用程序都需要访问资源。资源可以包括文件,以及象web页面或NNTP newsfeeds的东西。Spring提供了一个清晰透明的方案,以一种协议无关的方式访问资源。ApplicationContext接口包含一个方法(getResource(String))负责这项工作。

(4)在ApplicationContext中定制行为

     BeanFactory已经提供了许多机制来控制部署在其中的bean的生命周期(比如象InitializingBean或DisposableBean的标志接口,它们的配置效果和XmlBeanFactory配置中的init-method和destroy-method属性以及bean post-processor是相同的。在ApplicationContext中,这些也同样可以工作,但同时也增加了一些用于定制bean和容器行为的机制。

常用的有ApplicationContextAware标记接口

     所有BeanFactory中可用的标志接口这里也可以使用。ApplicationContext又增加了一个bean可以实现的标志接口:org.springframework.context.ApplicationContextAware。如果一个bean实现了这个接口并且被部署到了context中,当这个bean创建的时候,将使用这个接口的setApplicationContext()方法回调这个bean,为这个bean提供一个指向当前上下文的引用,这个引用将被存储起来以便bean以后与上下文发生交互。

 从一个web应用创建ApplicationContext

     与BeanFactory总是以编程的方式创建相反,ApplicationContext可以通过使用比如ContextLoader声明式地被创建。当然你也可以用ApplicationContext的任一种实现来以编程的方式创建它。首先,我们来看看ContextLoader以及它的实现。

    ContextLoader有两个实现:ContextLoaderListener和ContextLoaderServlet。它们两个有着同样的功能,除了listener不能在Servlet 2.2兼容的容器中使用。自从Servelt 2.4规范,listener被要求在web应用启动后初始化。很多2.3兼容的容器已经实现了这个特性。使用哪一个取决于你自己,但是如果所有的条件都一样,你大概会更喜欢ContextLoaderListener;关于兼容方面的更多信息可以参照ContextLoaderServlet的JavaDoc。

你可以象下面这样用ContextLoaderListener注册一个ApplicationContext:

<context-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>/WEB-INF/daoContext.xml /WEB-INF/applicationContext.xml</param-value>
</context-param>

<listener>
    <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>

<!-- OR USE THE CONTEXTLOADERSERVLET INSTEAD OF THE LISTENER
<servlet>
    <servlet-name>context</servlet-name>
    <servlet-class>org.springframework.web.context.ContextLoaderServlet</servlet-class>
    <load-on-startup>1</load-on-startup>
</servlet>
-->
 

     这个listener需要检查contextConfigLocation参数。如果不存在的话,它将默认使用/WEB-INF/applicationContext.xml。如果它存在,它就会用预先定义的分隔符(逗号,分号和空格)分开分割字符串,并将这些值作为应用上下文将要搜索的位置。ContextLoaderServlet可以用来替换ContextLoaderListener。这个servlet像listener那样使用contextConfigLocation参数。

 

 

二、DefaultListableBeanFactory,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,DefaultListableBeanFactory是Spring注册加载bean的默认实现,它是整个bean加载的核心部分。

     XmlBeanFactory与它的不同点就是XmlBeanFactory使用了自定义的XML读取器XmlBeanDefinitionReader,实现了自己的BeanDefinitionReader读取。 XmlBeanFactory加载bean的关键就在于XmlBeanDefinitionReader。

  • 4
    点赞
  • 24
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值