Spring——IoC

org.springframework.beans和org.springframework.context 是spring框架IoC容器的基础。

BeanFactory接口提供了一个预先配置机制,能够有能力管理任何类型的对象。
ApplicationContext是BeanFactory的一个子类接口,集成了spring AOP; 事件管理等。并且还提供了应用层面的特殊的context,如:WebApplicationContext。

Bean:由spring管理的应用程序中得对象都被称为bean。Bean可以是一个初始化,收集等都由spring IoC容器管理的对象,也可以是应用程序中得一个简单对象。Bean和Bean之间的关系都由容器的配置文件指定和映射。


ApplicationContext Overview
ApplicationContext代表了Spring IoC的容器。负责bean的初始化、配置以及收集。容器通过配置元数据来确定对象的创建,配置以及收集。配置元数据可以是xml,java annotation或者java源码。

ApplicationContext的实现有许多中。独立的应用程序通常创建ClassPathXmlApplicationContext或者FileSystemXmlApplicationContext。

初始化容器:构造器参数为需要加载的配置文件的位置。文件路径可以是多个的。

ApplicationContext context =
new ClassPathXmlApplicationContext(new String[] {"services.xml", "daos.xml"}); 



通过 T getBean(String name, Class<T> requiredType )的方法可以取回我们需要的bean对象的实力。

Bean Overview
通常我们使用xml来定义一个bean,成为提供容器创建bean的configuration metadata。

在定义bean时,使用BeanDefinition对象

1. package-qualified class name: bean对应的实际的类名,包括了所在包的名字
2. Bean behavioral配置元素,定义了bean在容器内的表现,如:scope,lifecycle callback等。
3. bean工作时需要用到其他bean的引用。这些引用也被成为合作者或者依赖。
4. 其他配置,如:连接数用来管理bean中的连接池,或者连接池的大小。

ApplicationContext的实现也允许注册在容器外由用户创建的对象。通过访问ApplicationContext的getBeanFactory()方法获得一个BeanFactory对象——DefaultListableBeanFactory。DefaultListableBeanFactory通过registerSingleton(..)和registerBeanDefinition(..)方法来支持这种注册。

bean的命名:当一个bean没有被明确指定一个id或者name时,容器会给这个bean产生一个唯一的名字。但是如果想要引用那个bean,通过ref元素的方式或者service locator的方式,则必须给定一个名字。

Bean可以通过构造函数初始化,此时根据不同的IoC类型,可能需要一个默认构造函数。

bean也可以通过静态工厂方法初始化。这时需要用到class属性来确定包含这个静态工厂方法的类,以及factory-method来指定工厂方法的名称。
例子:
<bean id="clientService"
      class="examples.ClientService"
      factory-method="createInstance”/>
public class ClientService {
private static ClientService clientService = new ClientService(); private ClientService() {}
private ClientService createInstance(){
return clientService;
}
}

Bean也可以使用实例工厂方法(instance factory method)
与静态工厂方法类似,只不过这里使用一个实例工厂方法来调用一个已经存在的bean的非静态的方法来创建一个新的bean。
<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"/>

factory-bean来指明现在已经在容器中且包含创建新对象方法的bean。

Dependency Injection: 一个对象通过构造器参数,工厂方法参数,属性来定义它的依赖类(一起工作的类),并在通过由构造器创建或者工厂方法返回一个对象实例后,这些依赖类被注入给对象实例。

DI分为两种类型 Constructor-based和Setter-based.

Constructor-based DI是通过容器调用构造方法以及一系列参数。每一个参数都代表了一个依赖关系。调用静态工厂方法配合特定的参数来创建bean也是等价的。

Setter-based DI是在通过一个默认构造方法或者无参数静态工厂方法创建了一个bean之后,调用setter方法来注入属性。

创建一个bean会造成一系列的bean被创建,因为这个bean的dependencies以及这些dependencies的dependencies(以此类推)都会被创建。

在使用Constructor injection时可能会造成循环依赖的情况。例如A需要一个B的实例传给构造器,B需要一个A的实例传给构造器。当A与B需要相互注入时,容器就会检测到这个循环引用的关系,抛出BeanCurrentlyInCreationException的异常。
解决方案:让某些属性通过setter来设置。或者不用constructor injection仅仅使用setter injection。


ApplicationContext在创建实例时,会立即创建所有单例的bean,作为初始化过程的一部分。大部分情况下这种预先加载是需要的。因为配置或者环境的错误能够被立即发现。也可以通过设定lazy-initialized来阻止预先实例化一个单例bean。告诉容器在第一次需要被使用时才创建。
<bean id="lazy" class="com.foo.ExpensiveToCreateBean" lazy-init="true"/>
<bean name="not.lazy" class="com.foo.AnotherBean”/>


不设置scope属性,默认为单例。
当一个被设置了lazy-initialized的bean与另一个没有设置lazy-initialized的单例bean之间存在依赖关系时,这个bean也会在start-up阶段被创建。



Method Injection
在一个singleton Bean只会被初始化一次。如果这个bean中包含一个非单例的有合作关系的bean时。有以下几种方法:
1. 放弃反转控制,通过实现ApplicationContextAware接口使得bean A能够感知容器,并通过getBean(”B”)的方法来告诉容器获得一个新的Bean B的实例。
2. 用lookup方法注入。LookUp方法注入通过覆盖container managed bean中的方法,并返回容器中的一个bean。lookup方法通常返回的时一个prototype类型的bean。
Bean的几种Scope类型
1. singleton 单例,整个容器中只有一个实例
2. prototype 原型,一个bean的定义能够对应多个对象实例。
3. request
4. session
5. global session

猜你喜欢

转载自mir-tempo.iteye.com/blog/2230730