1.Bean概述
一个Spring IOC容器管理一个或者多个bean。这些bean是根据你提供给容器的配置数据信息创建的,例如XML形式的的定义。
在容器内部,这些bean的定义表示为BeanDefinition对象,这些对象包含下面的元数据信息:
- 一个包含包的类的名字:一般是实际的继承实现类
- Bean行为配置元素,表明bean在容器中的行为(scope, lifecycle callbacks等等)
- bean起作用所需要的其他bean的引用;这些引用也被称为collaborators 或者 dependencies(依赖)。
- 在新的创建的对象中的配置设置,例如,在连接池中使用bean的连接的数目或者是池的数目限制。
这些元数据信息含有的一些力属性集合组成了每一个bean的定义。
(class、name、scope、constructor arguments、properties 、autowiring mode 、lazy-initialization mode、initialization method 、destruction method)
除了包含怎么创建一个具体的bean的定义的信息外,ApplicationContext的实现也是允许用户在容器外部创建的对象进行再注册。这是通过经由返回BeanFactory的实现DefaultListableBeanFactory的getBeanFactory()方法得到ApplicationContext的BeanFactory来实现的。DefaultListableBeanFactory支持这个再注册通过registerSingleton(..)和registerBeanDefinition(..)方法。但是,
一般情况下application但是使用的bean是在bean定义配置文件中。
2.bean的命名
每一个bean有一个或者多个标识符。这些标识符在bean的容器内部必须是唯一的。一个bean一般只会有一个标识符,但是如果它需要多于一个的话,那么额外可以被当做是别名。
在基于XML配置文件中,你可以使用id或者name属性去指明一个bean的标识符。id属性允许你去指明一个唯一的id。按照惯例这些名字是字母数的(myBean, fooService等等),但是也可能包括特殊的字符。如果你想去给bean起一些别名,那么你可以在那么属性中指明,可以用,
和;
以及
空格来分割他们。因为历史的版本,在Spring3.1之前,id属性被定义为xsd:ID
类型,不能是其他的字符。在3.1版本中,它被定义为xsd:string
类型。需要注意的是bean的id尽管不被XML解析器限制了可是仍然被容器中仍然是限制要是唯一的。
你没有被要求去提供一个名字或者id对于一个bean。如果没有显示的提供一个名字,那么容器救赎生成一个唯一性的名字针对这个bean。但是,如果你想去通过使用ref属性或者Service Locator
风格通过名字来引用一个bean,,你必须提供一个名字。不提供一个名字的动机主要和使用内部类和自动注入功能有关。
Bean命名惯例:这个惯例就是当命名bean的时候,使用标准Java实例域的名字。也就是说,bean的名字一个小写字母开头,遵循驼峰命名规则。这样名字的例子可以是 accountManager, accountService,userDao, loginController 等等。
3.在bean的定义的外部引用一个bean
在一个bean自己的定义中,对于每个bean你可以使用一个或者多个名字通过至多一个在id属性里或者任何数量的其他名字在name属性里,这些名字
对于相同的bean都是等价的,在某些情景下还是很有用的。例如,允许在一个应用程序中执行一个共同的依赖的组件中通过使用一个bean名字去指明那个组件。
在bean定义的时候指明所有的依赖并不是总是充分够用的。它只是有事需要去引用一个其他地方定义的bean的依赖。在大的系统中配置是在每一个子系统中都是分开的,每个子系统有自己的对象定义的集合。在基于XML配置中,你可以使用元素来指明他;
<alias name="fromName" alias="toName"/>
在这个例子中,在同一个容器中,一个名字为fromnName的bean,在使用这个依赖定义完成后,就可以引用 toName了。
比如,子系统A的配置通过subsystemA-dataSource的名字引用了一个数据源,子系统B的配置通过subsystemB-dataSource的名字引用了一个数据源。使用了两个子系统组成了主应用通过myApp-dataSource的名字引用了数据源。为了将所有的三个名字指向一个相同的对象,你可以通过下面的依赖定义加入到MyApp的配置中:
<alias name="subsystemA-dataSource" alias="subsystemB-dataSource"/>
<alias name="subsystemA-dataSource" alias="myApp-dataSource" />
现在每一个组件和主程序都可以通过一个唯一的不和塔器定义冲突的名字指向数据源了,也即是说它们指向了同一个bean。
基于Java 的配置:如果你使用java配置,@bean注解被用于提供依赖.
4.bean的实例化
一个bean的定义是创建一个或者多个对象必不可少的。容器在请被请求一个bean的时候货查看这些配置,然后容器会通过提供的配置数据创建一个实际的对象。
如果是你使用基于XML配置,你需要在元素的class属性中指明将要被实例化的对象的类型。class属性在Spring内部会被强制封装到BeanDefinition的Class属性中。你在下面的两种方式之一来使用class属性:
- 一般来说,当容器自己通过调用自己的构造器来直接创建bean的时候需要指明需要被构建的bean的class.,这个在Java代码中使用new操作符是等价的。
- 在包含可以被调用去创建对象的静态工作中指明实际具体的class.这个通过调用静态工长方法返回的对象可能是想通过的class 也可能是另外一个class。
4.1通过构造函数实例化
当年你通过构造器途径来创建一个bean的时候,所有正常的类都是可用的而且和Spring兼容。也就是说,
开发中用到的类是不用实现任何规范的接口。简单的话只需要指明是具体的类就够了。但是,和你使用的IOC容器的类型有关,你可能需要一个缺省的构造函数。
Spring IOC容器能够几乎管理所以他想让它管理的类;它不限制管理镇长的JavaBeans。大部分是Spring用户更偏向于只有一个缺省的构造函数的Javabean而且在属性的后面还有setter和getter方法。你可以在你的容器中有其他更多的非bean风格的类。如果,举个例子
你需要使用一个遗留的连接词但是它完全不符合JavaBean规范,Spring也是可以管理的。
你可以向下面这样来指明你的bean泪的基于XML配置的信息:
<bean id="exampleBean" class="examples.ExampleBean"/>
<bean name="anotherExample" class="examples.ExampleBeanTwo"/>
4.2使用静态工程方法来实例化
当定义一个你通过静态工厂方法来创建的bean时,你使用classs属性来指明具体的类,而且包含了static工厂方法,通过factory-method方法来指明工厂方法的名字。你可以调用这个方法然后返回一个就像是通过构造函数创建的存活的对象一样。
对于这样的bean的定义的使用之一就是在遗留的代码中调用static工厂。
下面的bean定义指明这个bean将会通过调用一个工厂方法来创建。定义没有指明返回对象的类型,只是包含了静态工厂的类。在这个例子中,creativeInstace肯定是静态方法。
<bean id="clientService"
class="examples.ClientService"
factory-method="createInstance"/>
public classClientService {
private staticClientService clientService = newClientService();
privateClientService() {}
public staticClientService createInstance() {
returnclientService;
}
}
4.3通过实例工厂方法来实例化
和通过金泰工厂方法实例化类似,通过一个实例工厂方法调用一个存在的类的非静态的方法从一个从其中去创建一个新的
bean。为了使用这个机制,需要将class属性设置为空,在factory-bean属性中,指明当前容器中bean的名字,它需要
含有被调用创建对象的实例化方法。 用factory-method属性来指明工厂方法。
<!-- the factory bean, which contains a method called createInstance() -->
<bean id="serviceLocator" class="examples.DefaultServiceLocator">
<!-- inject any dependencies required by this locator bean -->
</bean>
<!-- the bean to be created via the factory bean -->
<bean id="clientService"
factory-bean="serviceLocator"
factory-method="createClientServiceInstance"/>
public classDefaultServiceLocator {
private staticClientService clientService = newClientServiceImpl();
privateDefaultServiceLocator() {}
publicClientService createClientServiceInstance() {
returnclientService;
}
}
一个工厂类可以有一个或者多个工厂方法:
<bean id="serviceLocator" class="examples.DefaultServiceLocator">
<!-- inject any dependencies required by this locator bean -->
</bean>
<bean id="clientService"
factory-bean="serviceLocator"
factory-method="createClientServiceInstance"/>
<bean id="accountService"
factory-bean="serviceLocator"
factory-method="createAccountServiceInstance"/>
public classDefaultServiceLocator {
private staticClientService clientService = newClientServiceImpl();
private staticAccountService accountService = newAccountServiceImpl();
privateDefaultServiceLocator() {}
publicClientService createClientServiceInstance() {
returnclientService;
}
publicAccountService createAccountServiceInstance() {
returnaccountService;
}
这种方式表明工厂bean通过DI自己能够管理和注册。