spring学习(一)________核心概念

---------来自 <<Spring 开发指南 >>------夏昕

近来终于开始学习spring了第一本书夏昕所写的 <<Spring 开发指南 >> ,不敢妄谈自己对spring中这些核心概念的理解,下面摘抄的书中的对一些概念的诠释及例子,我相信看了这些就已经对spring有个感性认识了,我看过好几次每次总会有不同的理解,当然是理解得深些了,所以拿出来跟大家一起分享,建议大家照着本书看看!!
  •       Spring是一个从实际项目开发经验中抽取的,可高度重用的应用框架
  •      何谓控制反转(IoC = Inversion of Control),何谓依赖注入(DI = Dependency Injection)?

IoC,用白话来讲,就是由容器控制程序之间的关系,而非传统实现中,由程序代码直接操控。这也就是所谓“控制反转”的概念所在:控制权由应用代码中转到了外部容器,控制权的转移,是所谓反转。

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

依赖注入的目标并非为软件系统带来更多的功能,而是为了提升组件重用的概率,并为系统搭建一个灵活、可扩展的平台。

  •        依赖注入实现类型:

1、  接口注入

public   class  ClassA  {

private InterfaceB clzB;

public doSomething() {

Ojbect obj 
=Class.forName(Config.BImplementation).newInstance();

clzB 
= (InterfaceB)obj;

clzB.doIt()

}


……

}

2、  设值注入:诸如javabean 的设值方法

3、  构造子注入

public   class  DIByConstructor  {

private final DataSource dataSource;

private final String message;

public DIByConstructor(DataSource ds, String msg) {

this.dataSource = ds;

this.message = msg;

}


……

}

设值注入的优势

1 对于习惯了传统JavaBean开发的程序员而言,通过setter方法设定依赖关系显得更加直观,更加自然。

2 如果依赖关系(或继承关系)较为复杂,那么Type3模式的构造函数也会相当庞大(我们需要在构造函数中设定所有依赖关系),此时Type2模式往往更为简洁。

       3 对于某些第三方类库而言,可能要求我们的组件必须提供一个默认的构造函数(如Struts中的Action),此时Type3类型的依赖注入机制就体现出其局限性,难以完成我们期望的功能。

 

 

构造子注入的优势:

1、“在构造期即创建一个完整、合法的对象”,对于这条Java设计原则,Type3无疑是最好的响应者。

2 避免了繁琐的setter方法的编写,所有依赖关系均在构造函数中设定,依赖关系集中呈现,更加易读。

3 由于没有setter方法,依赖关系在构造时由容器一次性设定,因此组件在被创建之后即处于相对“不变”的稳定状态,无需担心上层代码在调用过程中执行setter方法对组件依赖关系产生破坏,特别是对于Singleton模式的组件而言,这可能对整个系统产生重大的影响。

4 同样,由于关联关系仅在构造函数中表达,只有组件创建者需要关心组件内部的依赖关系。对调用者而言,组件中的依赖关系处于黑盒之中。对上层屏蔽不必要的信息,也为系统的层次清晰性提供了保证。

5 通过构造子注入,意味着我们可以在构造函数中决定依赖关系的注入顺序,对于一个大量依赖外部服务的组件而言,依赖关系的获得顺序可能非常重要,比如某个依赖关系注入的先决条件是组件的DataSource及相关资源已经被设定。

 

  •           Bean Wrapper

提供一个设置JavaBean属性的通用方法(Apache BeanUtils 类库中提供了大量针对Bean的辅助工具,如果有兴趣可以下载一份源码加以研读)。Spring BeanWrapper基于同样的原理,提供了一个更加完善的实现。看看如何通过Spring BeanWrapper操作一个JavaBean

Object obj  =  Class.forName( " net.xiaxin.beans.User " ).newInstance();

BeanWrapper bw 
=   new  BeanWrapperImpl(obj);

bw.setPropertyValue(
" name " " Erica " );

System.out.println(
" User name=> " + bw.getPropertyValue( " name " ));

  •       Bean Factory

负责创建并维护Bean实例。

Bean Factory负责根据配置文件创建Bean实例,可以配置的项目有:

1 Bean属性值及依赖关系(对其他Bean的引用)

2 Bean创建模式(是否Singleton模式,即是否只针对指定类维持全局唯一的实例)

3 Bean初始化和销毁方法

4 Bean的依赖关系

< beans >

< description > Spring Bean Configuration Sample </ description >

< bean

id ="TheAction"  ⑴

class
="net.xiaxin.spring.qs.UpperAction"  ⑵

singleton
="true"  ⑶

init-method
="init"  ⑷

destroy-method
="cleanup"  ⑸

depends-on
="ActionManager"  ⑹

>  

< property  name ="message" >

< value > HeLLo </ value >  ⑺

</ property >

< property  name ="desc" >

< null />

</ property >

< property  name ="dataSource" >

< ref  local ="dataSource" />  ⑻

</ property >

</ bean >

< bean  id ="dataSource"

class
="org.springframework.jndi.JndiObjectFactoryBean" >

< property  name ="jndiName" >

< value > java:comp/env/jdbc/sample </ value >

</ property >

</ bean >

 

id

Java BeanBeanFactory中的唯一标识,代码中通过BeanFactory获取

JavaBean实例时需以此作为索引名称。

class

Java Bean 类名

singleton

指定此Java Bean是否采用单例(Singleton)模式,如果设为“true”,则在

BeanFactory作用范围内,只维护此Java Bean的一个实例,代码通过BeanFactory

获得此Java Bean实例的引用。反之,如果设为“false”,则通过BeanFactory获取

Java Bean实例时,BeanFactory每次都将创建一个新的实例返回。

init-method

初始化方法,此方法将在BeanFactory创建JavaBean实例之后,在向应用层返回引

用之前执行。一般用于一些资源的初始化工作。

destroy-method

销毁方法。此方法将在BeanFactory销毁的时候执行,一般用于资源释放。

depends-on

Bean依赖关系。一般情况下无需设定。Spring会根据情况组织各个依赖关系的构建工作(这里

示例中的depends-on属性非必须)。

只有某些特殊情况下,如JavaBean中的某些静态变量需要进行初始化(这是一种Bad

Smell,应该在设计上应该避免)。通过depends-on指定其依赖关系可保证在此Bean

载之前,首先对depends-on所指定的资源进行加载。

<value>

通过<value/>节点可指定属性值。BeanFactory将自动根据Java Bean对应的属性

类型加以匹配。

下面的”desc”属性提供了一个null值的设定示例。注意<value></value>代表一

个空字符串,如果需要将属性值设定为null,必须使用<null/>节点。

<ref>

指定了属性对BeanFactory中其他Bean的引用关系。示例中,TheActiondataSource

性引用了iddataSourceBeanBeanFactory将在运行期创建dataSource bean实例,并将其

引用传入TheAction BeandataSource属性。

 

下面的代码演示了如何通过BeanFactory获取Bean实例:

InputStream is  =   new  FileInputStream( " bean.xml " );

XmlBeanFactory factory 
=   new  XmlBeanFactory(is);

Action action 
=  (Action) factory.getBean( " TheAction " );

联合上面关于BeanWrapper的内容,我们可以看到,BeanWrapper实现了针对单个Bean的属性设定操作。而BeanFactory则是针对多个Bean的管理容器,根据给定的配置文件,BeanFactory从中读取类名、属性名/值,然后通过Reflection机制进行Bean加载和属性设定。

  •         ApplicationContext

ApplicationContext覆盖了BeanFactory的所有功能,并提供了更多的特性。此外,

ApplicationContext为与现有应用框架相整合,提供了更为开放式的实现(如对于Web应用,我们可以在

web.xml中对ApplicationContext进行配置)。

相对BeanFactory而言,ApplicationContext提供了以下扩展功能:

1 国际化支持

我们可以在Beans.xml文件中,对程序中的语言信息(如提示信息)进行定义,将程序中的提示

信息抽取到配置文件中加以定义,为我们进行应用的各语言版本转换提供了极大的灵活性。

2 资源访问

支持对文件和URL的访问。

3 事件传播

事件传播特性为系统中状态改变时的检测提供了良好支持。

4 多实例加载

可以在同一个应用中加载多个Context实例。

  •         Web Context

对于Web应用,Spring 提供了可配置ApplicationContext的配置,现在提供的有两种方式,ContextLoaderListenerContextLoaderServlet。这两者在功能上完全等同,只是一个是基于Servlet2.3版本中新引入的Listener接口实现,而另一个基于Servlet接口实现。开发中可根据目标Web容器的实际情况进行选择。

<listener>

<listener-class>

org.springframework.web.context.ContextLoaderListener

</listener-class>

</ listener >

或:

<servlet>

<servlet-name>context</servlet-name>

<servlet-class>

org.springframework.web.context.ContextLoaderServlet

</servlet-class>

<load-on-startup>1</load-on-startup>

</servlet>

通过以上配置,Web容器会自动加载/WEB-INF/applicationContext.xml初始化

<context-param>

<param-name>contextConfigLocation</param-name>

<param-value>/WEB-INF/myApplicationContext.xml</param-value>

</context-param>

ApplicationContext实例,如果需要指定配置文件位置,可通过context-param加以指定:

配置完成之后,即可通过WebApplicationContextUtils.getWebApplicationContext方法在Web应用中获取ApplicationContext引用。

  •        面向切面编程 Aspect Oriented ProgrammingAOP

AOPOOP在字面上虽然非常类似,但却是面向不同领域的两种设计思想。OOP(面向对象编程)针对业务处理过程的实体及其属性和行为进行抽象封装,以获得更加清晰高效的逻辑单元划分。而AOP则是针对业务处理过程中的切面进行提取,它所面对的是处理过程中的某个步骤或阶段,以获得逻辑过程中各部分之间低耦合性的隔离效果。这两种设计思想在目标上有着本质的差异。上面的陈述可能过于理论化,举个简单的例子,对于“雇员”这样一个业务实体进行封装,自然是OOP/OOD的任务,我们可以为其建立一个“Employee”类,并将“雇员”相关的属性和行为封装其中。而用AOP设计思想对“雇员”进行封装将无从谈起。同样,对于“权限检查”这一动作片断进行划分,则是AOP的目标领域。而通过OOD/OOP对一个动作进行封装,则有点不伦不类。

换而言之,OOD/OOP面向名词领域,AOP面向动词领域。

AOPOOD/OOP并不冲突,我们完全可以在一个应用系统中同时应用OOD/OOPAOP设计思想,通过OOD/OOP对系统中的业务对象进行建模,同时通过AOP对实体处理过程中的阶段进行隔离处理。即使不是OOD/OOP,而是在传统的POP(面向过程编程)中 AOP也能起到同样的作用。

AOP还有另外一个重要特点:源码组成无关性。所谓源码组成无关性,体现在具体设计中就是AOP组件必须与应用代码无关,简单来讲,就是应用代码可以脱离AOP组件独立编译。

为了实现源码组成无关性,AOP往往通过预编译方式(如AspectJ)和运行期动态代理

模式(如Spring AOP JBoss AOP)实现。

1、             切面(Aspect

通过切面,我们可以将系统中各个不同层次上的问题隔离开来,实现统一集约式处理。各切面只需集中于自己领域内的逻辑实现。这一方面使得开发逻辑更加清晰,专业化分工更加易于进行;另一方面,由于切面的隔离,降低了耦合性,我们就可以在不同的应用中将各个切面组合使用,从而使得代码可重用性大大增强。

2、 连接点(JoinPoint

程序运行过程中的某个阶段点。如某个方法调用,或者某个异常被抛出。

3、 处理逻辑(Advice

在某个连接点所采用的处理逻辑

(这里的Advice,国内不少文案中翻译为“通知”,估计是源于金山词霸,与实际含义不符,因而这

里采用意译)

处理逻辑的调用模式通常有三种:

i. Around

在连接点前后插入预处理过程和后处理过程。

ii. Before

仅在连接点之前插入预处理过程。

iii. Throw

在连接点抛出异常时进行异常处理。

4、 切点(PointCut

一系列连接点的集合,它指明处理方式(Advice)将在何时被触发。

 

 

 

 

 

 

                                                     
 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值