Spring参考手册-第三章 IoC容器-3.2 基本概念-容器和Beans(豆子)

 

为什么叫做Bean
使用‘bean’这个名字的原因是因为在Spring框架中已经使用了‘componet’和‘object’这些基本概念名称,另外也是由于EJB的复杂性,所以在类似的起了这个名字。

 在Spring里,组成你应用的核心对象是由IoC容器管理的,被称作beans。一个bean就是一个实例化的、装配好的,且由Spring IoC容器管理的对象;除此之外,关于bean没有什么其他特别的特性。这些bean以及它们之间的依赖由容器的配置元数据来反映(configuration metadata)。
3.2.1 容器
org.springframework.beans.factory.BeanFactory Spring IoC 容器的实际界面,它实际负责包含和管理 bean
BeanFactory 接口是 Spring IoC 容器的核心。它的作用包括实例化和初始化应用对象,配置对象和组装对象的依赖。
  有很多 BeanFactory 的接口实现。最常用的是 XmlBeanFactory 类,它让你以 XML 方式配置组成应用的对象和这些对象间确定的依赖。 XmlBeanFactory 获取 XML 配置元数据并且按照配置来创建一个完整的系统和应用。
Spring IoC 容器示意图
3.2.1 .1 配置元数据( Configuration metadata
 从上面的图片可以看出来,Spring IoC容器使用了一些形式的元数据;配置元数据也就是告诉Spring容器,怎样实例化,配置和装配应用对象。配置元数据的形式为简单、直观的XML格式。当使用基于XML的配置元数据时,你需要把那些需要容器管理的bean的定义文件写好,然后让容器去做剩下的事情。
注意:
XML基础的元数据是到目前为止最常用的配置元数据方式。然后它不是唯一被支持的方式。
Spring容器降低了对于配置元数据的表达格式要求。
在写配置的时候,你可以以XML、Java数据属性格式或者编程方式(利用Spring的公共API)来配置文件。然后XML配置方式是相对简单易用的方式,所以,本章的后面部分将使用XML配置格式来介绍Spring容器的关键概念和特性。

资源:
了解了Spring IoC容器之后,了解“第四章,资源”所介绍的关于Spring的资源抽象(resources abstract)概念是什么必要的。提供给 ApplicationContext 构造器的位置路径实际上是资源串,它用来告诉容器从外部资源加载配置元数据,如本地的文件系统或者是 Java Classpath 等。

 请记住,在大多数的应用情况下,Spring IoC容器是不需要用户代码来实例化的。例如,在典型的J2EE应用中,大约只需要8行左右的XML配置信息即可(web.xml)。
 在最基本的情况下,Spring IoC容器配置信息需要包含至少一个bean的定义,实际上大多数情况下都超过一个。当使用XML配置方式时,关于bean的配置内容包含在<bean/>和<beans>元素内。
 对应于实际对象的这些bean应用组织起你的应用。一般情况下,你需要定义的bean包括服务层对象,数据访问对象(DAOs),表现层对象(例如Structs Action实例),基础底层对象( Hibernate SessionFactory 实例),JMS序列( Queue)引用等。(当然,还有很多其他的可能需要配置的信息,这取决于你的应用复杂度)。
 下面就是一个XML配置的典型例子。
 
 
 
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd">
 <bean id="..." class="...">
    <!-- collaborators and configuration for this bean go here -->
 </bean>
 <bean id="..." class="...">
    <!-- collaborators and configuration for this bean go here -->
 </bean>
 <!-- more bean definitions go here... -->
</beans>
3.2.2 初始化容器
 初始化Spring容器十分方便;参看下面的例子。
例1:
Resource resource = new FileSystemResource("beans.xml");
BeanFactory factory = new XmlBeanFactory(resource);
例2:
 
ClassPathResource resource = new ClassPathResource("beans.xml");
BeanFactory factory = new XmlBeanFactory(resource);
例3:
ApplicationContext context = new ClassPathXmlApplicationContext(
        new String[] {"applicationContext.xml", "applicationContext-part2.xml"});
// of course, an ApplicationContext is just a BeanFactory
BeanFactory factory = (BeanFactory) context;
3.2.2 .1 组织 XML 配置文件
 将容器配置文件分解成多个XML配置文件是什么有用的。加载多个XML文件的方法之一是利用应用上下文(application context)的构造器来读取多个资源(Resource)位置。利用bean factory,一个bean的定义读取器(reader)可以在读取每个配置文件的时候重复使用。
 一般来说,Spring团队推荐上面的方法,因为这种方法使得配置文件的读取对于容器是透明的。另外一个替代的方法是在定义文件中使用<import>元素来定义其他的bean定义文件。<import/>元素必须放置在<bean/>元素之前。参看下面的例子:
<beans>
    <import resource="services.xml"/>
    <import resource="resources/messageSource.xml"/>
    <import resource="/resources/themeSource.xml"/>
    <bean id="bean1" class="..."/>
    <bean id="bean2" class="..."/>
</beans>
本例中,外部的bean定义从 s ervices.xml messageSource.xml themeSource.xml 三个文件中加载。所有的位置路径是相对于定义文件的,因此 s ervices.xml 和定义文件必须在相同的路径,而 messageSource.xml themeSource.xml 是在相对路径的 resources 目录下面。可以看出,路径开头的 / 已经被省略,这些路径被认为是相对路径,或许这是种更好的方式。
  导入的配置文件内容必须符合包含在定义文件头部的 Schema 或者 DTD 的合法性验证。
3.2.3 Beans
 正如前面所述,Spring IoC容器管理一个或者多个Bean。容器按照定义的配置元数据(典型的为XML的bean定义文件)来创建bean。
 在容器内部,这些bean的定义被表示成 BeanDefinition 对象,其中包含以下的元数据:
l         一个类名(包含包定义):这实际上是这个bean的实现类。然而,如果这个bean是通过调用静态的工厂方法创建的(而不是通过正常的构造器创建的),这个实际上是这个工厂类的名字。
l         Bean的行为配置元素,用来告诉容器bean在容器中的行为(如原型、单例、自装配模式、依赖检查模式以及初始化(initialization)和消除(destruction)方法)。
l         新创建的bean的构造器参数和属性值。例如bean中用来管理的连接池数量(可以作为属性指定,也可以作为构造器参数),或者连接池大小。
l         Bean正常运行所需要的其他的bean说明,例如合作者(或者叫依赖)。
上面提到的概念在定义文件中对应于bean定义的属性集合。下面给出了一些属性的详细文档链接。
 3.1. bean 定义
Feature
Explained in...
class
name
scope
constructor arguments
properties
autowiring mode
dependency checking mode
lazy-initialization mode
initialization method
destruction method
 除了通过bean定义文件来创建bean以外,某些 BeanFactory 实现也允许注册那些已经在工厂之外创建的对象(通过用户代码创建)。 DefaultListableBeanFactory 类就支持 registerSingleton(..) 方法。然而,典型的应用一般还是通过 bean 定义的方式来实现 bean 的创建和管理。
3.2.3 .1 命名 Beans

Bean 的命名规范:
Bean的命名规范(至少在Spring开发团队中是这样)是使用标准的Java命名规范。具体规范如下,bean的名字以小写字母开头,并且是camel-cased。例如: 'accountManager' , 'accountService' , 'userDao' , 'loginController' 等等。按照统一的方式来命名 bean ,将会使得你的配置内容更易于阅读和理解;采用这样的命名规范并不困难,采用 Spring AOP 框架的时候,它可以在 bean 的命名方面给与很多提示和建议。

每个bean都有一个或者多个标识(也叫标识符,或者名字;这些指的都是同样的东西)。这些标识符在容器中必须是唯一的。通常bean只有一个标识,但当bean有超过一个标识时,其他的标识可以看作是别名。
使用XML配置文件时,使用 'id' 或者 'name' 来指定 bean 的标识。 'id' 属性允许你指定一个 bean ID ,由于这是 XML 元素的 ID 属性, XML 解析器能够在别的元素引用这个 ID 的时候做完全的验证。然而, XML 规范限制了 XML ID 中使用的字符类型。通常这不会造成影响,但如果你需要使用特定的 XML 字符,或者为 bean 取别名的时候,你可以在 'name' 属性中指定多个标识,标识之间以逗号( , ),分号( ; )或者空格分隔。
注意,你并不一定要为 bean 命名。如果没有命名,容器将会为 bean 创建一个唯一的名字。不命名 bean 的目的将会在后面讨论(一种情况是内部 bean-inner beans )。
3.2.3 .1.1 Bean 别名
bean 定义中,你可以通过 ID 属性指定 bean 的名字,然后再通过 alias 属性来指定 bean 的别名。所有的名字指向同一个 bean ,这在有些情况下很有用,允许应用的组件使用与组件名字有关的 bean 别名来引用 bean
然后,在 bean 定义的时候,就必须要指定所有的别名似乎不太合适。有的时候为在其他地方定义的 bean 来定义一个别名是什么必要的。在 XML 配置方式中,可以通过独立( standalone )的 <alias/> 元素来实现这点。例如:
<alias name="fromName" alias="toName"/>
上面的例子中,在同一容器的 bean 叫做 'fromName' ,在使用上面的别名定义之后,可以用 'toName' 来引用这个 bean
举个具体的例子,例如组件 A 在它的 XML 配置中定义了一个 DataSource bean 叫做 componentA-dataSource 。组件 B 希望在它的配置中用 componentB-dataSource 来引用这个 bean 。同时,主应用 MyApp 则定义了自己的 XML 配置,并且装配了来自三个不同 XML 配置的应用上下文,要用 myApp-dataSource 来引用 bean 。对于这种情况可以在用下面的配置方式很方便的实现:
<alias name="componentA-dataSource"
 alias="componentB-dataSource"/>
<alias name="componentA-dataSource" alias="myApp-dataSource" />
现在每个组件,包括主应用都以一个不会和其他定义发生冲突的名字来应用这个 dataSource 了。
3.2.3 .2 初始化 bean
Spring IoC 容器中, bean 的定义配置是创建一个或者多个实际对象的依据。容器参照 bean 定义并且使用配置数据来定义和创建一个实际的对象。本章关注的是对于作为开发者的你来说,怎样去告知 Spring IoC 容器要初始化的对象类型是什么,怎样去初始化对象。
如果你使用 XML 配置方式,你可以用 ’class’ 属性来指定对象的类型。 ’class’ 属性(在容器的 BeanDefinition 实例中表示为 Class 属性)是必须的(参照第 3.2.3 .2.2- “使用实例工厂方法来初始化”和第 3.6 - Bean 定义继承”),并且有两个目的。大多数情况下, Class 属性告知容器去哪儿以反射方式调用构造器来创建 bean 实例(类似于 java ’new’ 方法)。
在调用静态工厂方法创建 bean 的情况下, class 属性指定的是包含静态工厂方法的类(返回的对象类型可能是同一个类,也可能是另外的类,这无关紧要)。
3.2.3 .2.1 使用 constructor 实例化 bean
当使用构造器来创建 bean 的时候, Spring 支持对于大多数的常规的类的创建。也就是说,这些类不需要实现特定的接口,或者要求以特定的方式来编码。只要指定 bean 的类就可以。然后,依赖于 IoC 容器的类型,你可能需要一个默认(空的)构造器。
Spring IoC 容器除了管理 JavaBean 以外,也可以虚拟地管理你要管理的任何类。大多数使用 Spring 的人更细化将真正的 JavaBean (有默认的(无参数)构造器,并且有合适的 setter getter 方法)放到容器中,当然,也可以将“非 bean 类型”( non-bean-style )的类放在容器中。例如,当你要使用一个完全不符合 JavaBean 规范的连接池对象的时候, Spring 同样可以很好的管理。
XML 配置中,可以用如下的方式来定义 bean
<bean id="exampleBean" class="examples.ExampleBean"/>
<bean name="anotherExample" class="examples.ExampleBeanTwo"/>
如何指定构造器参数(如果需要的话),或者如何设置对象实例的属性,这些将稍后描述。
3.2.3 .2.2 使用静态工厂方法( static factory method )实例化 bean
当使用静态工厂方法来定义 bean 时, class 属性指定包含静态工厂方法的类, factory-method 属性用来指定工厂方法名。 Spring 调用工厂方法(调用可选的参数列表,后面介绍)然后返回一个活动的对象,在外面看来和利用构造器方法创建 bean 实例一样。这种创建方法的一个用处是在代码中调用静态工厂方法。
下面的例子说明了通过工厂方法来创建 bean 的定义文件。注意下面的定义并没有指定返回对象的类型,只指定了工厂方法。例子中的 createInstance() 方法必须是一个静态方法。
<bean id="exampleBean"
      class="examples.ExampleBean2"
      factory-method="createInstance"/>
静态工厂方法的参数(可选)制定方法和对象实例的属性设置方法( setter )将在后面说明。
3.2.3 .2.3 使用实例工厂方法( instance factory method )实例化 bean
有点类似于静态工厂方法,实例工厂方法是通过调用容器中存在的 bean 实例的工厂方法来创建新的 bean
要用这个方法创建 bean ’class’ 属性必须为空,而 ’factory-bean’ 属性必须指定当前容器(或者父容器)中包含了工厂方法的 bean 的名字。而工厂方法的名字同过 ’factory-method’ 属性指定。(参看下面的例子)
<!-- the factory bean, which contains a method called createInstance() -->
<bean id="myFactoryBean" class="...">
 ...
</bean>
 
<!-- the bean to be created via the factory bean -->
<bean id="exampleBean"
      factory-bean="myFactoryBean"
      factory-method="createInstance"/>
尽管这种方法设置 bean 属性的机制当前仍然在讨论,但一个可能的好处是工厂 bean 自身可以被管理,同时可以用依赖注射( DI )的方式来配置它。
3.2.4 使用容器
BeanFactory 只不过是一个能够维护不同的 bean 以及它们之间关系的注册的高级工厂的接口。 BeanFactory 使得你可以读取 bean 定义文件并且访问它们。当只使用 BeanFactory 的时候,你需要创建一个 BeanFactory ,并且读取 Bean XML 定义文件。例如:
InputStream is = new FileInputStream("beans.xml");
BeanFactory factory = new XmlBeanFactory(is);
上面基本就是创建容器要做的一切。利用 getBean(String) 方法,你可以检索 bean 的实例; BeanFactory 的客户端接口相当简单,仅仅有六个供客户代码调用的接口:
l        boolean containsBean(String) :如果 BeanFactory 包含匹配参数的 bean 定义或者 bean 实例,则返回 true
l        Object getBean(String) :按照指定的参数返回 bean 实例。依据当前 bean BeanFactory 中配置的不同,可能返回单例(共享实例),或者是一个新创建的 bean 实例。如果 bean 不存在,或者正在被初始化,那么方法将返回一个 BeansException 异常(前者将会返回 NoSuchBeanDefinitionException 异常)。
l        Object getBean(String, Class) :然会一个指定参数的 bean 实例,同时将返回的 bean 强制转换为指定的 Class 类型。如果当前 bean 不能被转换,那么将抛出 BeanNotOfRequiredTypeException 异常。此外,所有 getBeans(String) 的规范也同样适用本方法。
l        Class getType(String name) :返回指定名称的 bean Class 类型。同样,如果没有找到 bean ,抛出 NoSuchBeanDefinitionException 异常。
l        boolean isSingleton(String) :判断当前 bean 是否是单例(后面将解释单例)。如果没有找到 bean ,抛出 NoSuchBeanDefinitionException 异常。
l        String[] getAliases(String) :返回在 bean 定义文件中定义的别名数组。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值