Spring 学习的笔记

阅读更多
 

Spring 开发指南笔记

 

Spring 基础语义

 何谓控制反转(IoC = Inversion of Control),何谓依赖注入(DI = Dependency Injection)?概念所在:控制权由应用代码中转到了外部容器,控制权的转移,是所谓反转。

相对IoC 而言,“依赖注入”的确更加准确的描述了这种古老而又时兴的设计理念。从名字上理解,所谓依赖注入,即组件之间的依赖关系由容器在运行期决定,形象的来说,即由容器动态的将某种依赖关系注入到组件之中。

所谓依赖注入,即在运行期由容器将依赖关系注入到组件之中。讲的通俗点,就是在运行期,由Spring根据配置文件,将其他对象的引用通过组件的提供的setter方法进行设定。

 

 依赖注入的几种实现类型

Ø         Type1 接口注入

我们常常借助接口来将调用者与实现者分离。如:

public class ClassA {

private InterfaceB clzB;

public doSomething() {

Ojbect obj =

Class.forName(Config.BImplementation).newInstance();

clzB = (InterfaceB)obj;

clzB.doIt()

}

……

}

上面的代码中,ClassA依赖于InterfaceB的实现,如何获得InterfaceB实现类的实例?传统的方法是在代码中创建InterfaceB实现类的实例,并将起赋予clzB

而这样一来,ClassA在编译期即依赖于InterfaceB的实现。为了将调用者与实现者在编译期分离,于是有了上面的代码,我们根据预先在配置文件中设定的实现类的类名(Config.BImplementation),动态加载实现类,并通过InterfaceB强制转型后为ClassA所用。这就是接口注入的一个最原始的雏形。

 

而对于一个Type1型IOC容器而言,加载接口实现并创建其实例的工作由容器完成。

如下面这个类:

public class ClassA {

private InterfaceB clzB;

public Object doSomething(InterfaceB b) {

clzB = b;

return clzB.doIt();

}

……

}

在运行期,InterfaceB实例将由容器提供。

 

Ø         Type2 设值注入 (setter)

在各种类型的依赖注入模式中,设值注入模式在实际开发中得到了最广泛的应用(其中很大一部分得力于Spring框架的影响)。在笔者看来,基于设置模式的依赖注入机制更加直观、也更加自然。Quick Start中的示例,就是典型的设置注入,即通过类的setter方法完成依赖关系的设置。

Ø         Type3 构造子注入

构造子注入,即通过构造函数完成依赖关系的设定,如:

public class DIByConstructor {

private final DataSource dataSource;

private final String message;

public DIByConstructor(DataSource ds, String msg) {

this.dataSource = ds;

this.message = msg;

}

……

}

可以看到,在Type3类型的依赖注入机制中,依赖关系是通过类构造函数建立,容器通过调用类的构造方法,将其所需的依赖关系注入其中。

 

 

Spring Bean封装机制

Spring 从核心而言,是一个DI 容器,其设计哲学是提供一种无侵入式的高扩展性框架。即无需代码中涉及Spring专有类,即可将其纳入Spring容器进行管理。

作为对比,EJB则是一种高度侵入性的框架规范,它制定了众多的接口和编码规范,要求实现者必须遵从。侵入性的后果就是,一旦系统基于侵入性框架设计开发,那么之后任何脱离这个框架的企图都将付出极大的代价。为了避免这种情况,实现无侵入性的目标。Spring 大量引入了Java Reflection机制,通过动态调用的方式避免硬编码方式的约束,并在此基础上建立了其核心组件BeanFactory,以此作为其依赖注入机制的实现基础。

org.springframework.beans包中包括了这些核心组件的实现类,核心中的核心为BeanWrapperBeanFactory类。这两个类从技术角度而言并不复杂,但对于Spring 框架而言,却是关键所在,如果有时间,建议对其源码进行研读,必有所获。

所谓依赖注入,即在运行期由容器将依赖关系注入到组件之中。讲的通俗点,就是在运行期,由Spring根据配置文件,将其他对象的引用通过组件的提供的setter方法进行设定。

 

Bean相关包

Spring 的核心是org.springframework.beans 包,为使用JavaBeans 技术、按名检索对象及管理对象间的关系而设计。beans包及其子包提供的功能为使用JavaBeans 技术的项目指定了一个基础设施。

关于beans 包,有三个重要的概念。首先,它提供了设置/读取Javabeans 属性功能的BeanWrapper接口。第二个重要概念是Bean 工厂。BeanFactory 是一个泛化工厂,具有实例化对象和管理不同对象间关系的能力。BeanFactory 可以管理几种不同类型的bean,并且支持串行化及其他生命周期方法。BeanFactory 是按照bean 定义(BeanDefinition)来实例化对象的。BeanDefinition,顾名思义,是你对bean 的定义。BeanDefinition 不仅定义了bean 的类结构、实例化的方式,还定义了bean 在运行时的合作者。这是第三个概念。这三个概念( BeanFactory, BeanWrapper and BeanDefinition)将在下文详细讨论。

对于org.springframework.beans 包遵循Sun 公司发布的JavaBeans 标准。所谓“JavaBean”其实就是一个Java 类。不过,它必须拥有默认无参数构造器,并按照既定规则来命名属性——属性prop对应一个设置器setProp(…)和读取器getProp(…)。更多的关于JavaBeans 的信息请查阅Sun 公司网站(java.sun.com/products/javabeans[http://java.sun.com/products/javabeans/]).

 

Bean Definitions

Bean definitions 是你的bean 的详细描述。Bean 就是一些提供某些特定功能的普通类,

BeanFactory 接口如何管理你的bean 以及它们是怎样配置的,都是在一个bean definition 中规定的。以下就是bean definition 实际模型,这个模型使得bean definition 能够实例化bean。

 

 

第一个例子以IoC 类型2(使用设置器)方式使用BeanFactory。下面是指定bean definition

的部分XML 文件片断。你同样可以通过适当的设置器声明找到真正的bean。

 

applicationContext.xml片断:

1

 

public class ExampleBean {

private AnotherBean beanOne;

private YetAnotherBean beanTwo;

private int i;

public void setBeanOne(AnotherBean beanOne) {

this.beanOne = beanOne;

public void setBeanTwo(YetAnotherBean beanTwo) {

this.beanTwo = beanTwo;

public void setIntegerProperty(int i) {

this.i = i;

正如你所看到的,声明的设置器在XML 文件中被指定为一个相应的属性。(XML 文件中的属性直接与RootBeanDefinition 中定义的PropertyValues 相联系)。

 

客户端与factory 的交互

客户端介面惊人的简单――BeanFactory 接口只有4 个方法与客户端交互

Ø         Object getBean(String):按名返回一个已注册bean 的实例。取决于该bean 在BeanFactory 中的配置,将返回一个共享的唯一的bean 实例或者是一个重新创建的bean 实例。当无法找到bean的定义(此时将引发一个NoSuchBeanDefinitionException 异常)或者在进行实例化和初始化bean 时引发了一个异常,都将引起一个BeansException 异常被抛出。

Ø         Object getBean(String,Class): 按名返回一个已注册bean 的实例。这个bean 实例的Class 类型必须和给出的Class 类型参数相匹配,否则相应的异常将会被抛出

BeanNotOfRequiredTypeException 异常)将会被抛出。此外,这个方法的其他的行为和

getBean(String)方法相同。(请参考getBean(String)方法)

Ø         boolean isSingleton(String):按名检测已注册的beandefinition 是被设定为singleton 模式还是prototype 模式。如果给定的beandefinition 没有找到, 则抛出一个异常(NoSuchBeanDefinitionException 异常)

Ø         String[] getAliases(String):返回某个已配置bean 的别名(TODO:这意味着什么?)

 

BeanFactory 的实现

 

XML 中指定bean 定义(XmlBeanFactory)

BeanFactory 接口的一个实现是XmlBeanFactory 类(位于

org.springframework.beans.factory.xml 包中)。正如它的名字所告诉你的,它为你提供了在XML文件中指定bean 定义的能力。Spring 提供了相应的DTD,使校验bean 定义XML 文件合法性的工作变得简单些。

Spring XML bean 定义文档的根元素是元素可以包含一个或多个bean 定义。我们通常指定每个bean 定义的类和属性。同时,我们也必须指定id――这是bean 的名字,我们将在代码中以这个名字使用这个bean。

我们将使用Jakarta Commons DBCP 项目中的BasicDataSource 类。这个

类(和其他很多早已存在的类一样)可以在Spring 轻松地使用,因为它提供了JavaBean 风格的配置方式。此类的实例在销毁前需要调用close 方法。这个方法通过Spring 的“destroy-method”attribute 在BeanFactory 中进行注册,而无需实现任何Spring 接口(否则你就需要实现早前在“生命周期特性”一节中提到的DisposableBean 接口)。

class="org.apache.commons.dbcp.BasicDataSource"

destroy-method="close">

com.mysql.jdbc.Driver

jdbc:mysql://localhost:3306/mydb

root

 

就像使用destroy-method attribute 指定一个析构方法,我们可以使用init-method attribute指定一个初始化方法。

 

指定多个灵活属性,像list, properties 对象,或者Map 会出现两种可能。下面的例子展示了这种行为:

 

 

 

 

 

 

 

 

 

 

 

你可能感兴趣的:(Spring,Bean,F#,配置管理,IOC)