逍遥游

一直在想,怎样路好走一点,一直想,一直在崎岖中徘徊。
  首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

[转]Spring笔记

Posted on 2007-09-12 09:25  逍遥游  阅读(506)  评论(0编辑  收藏  举报
 本文档适用于使用过Spring的开发者,该文章有助于他们重新梳理一下对Spring的认识。
       这篇文章是本人在项目开发中使用Spring的总结,这里只是归纳了我们在开发中经常要用到的Spring的特性,Spring的其他特性或者使用起来比较复杂,或者很少有机会在实际开发中使用将不再本文中做介绍。
      
一、背景,为什么我们需要Spring?
Martin Flower提出了IoC(Inversion of Control),反转的是什么样的控制?
以前我们在一个java对象中要使用另外一个java对象,即定义两个java bean之间的依赖关系,通常通过以下三种方式建立:
(1) Bean自己实例化另外一个bean。
(2) 在bean的构造函数中指定依赖关系。
(3) 使用类似service locator模式来获得另外一个bean。
这三种方式都是由bean自己自主控制依赖关系。
现在我们通过IoC容器来创建bean并注入它们之间的依赖关系。这样对象的创建和依赖关系的定义就由专门的IoC容器来实现,而不是由对象本身。这样就是我们所说的控制的翻转。好处:bean自己不再负责对象的依赖关系,从而降低对象之间的耦合。同时让开发者把精力放在业务逻辑的编写上。
 
这种控制翻转更确切的说是Dependency Injection(依赖注入),依赖关系通过容器来注入实现的。我们通过接口的方式实现它,这也符合DIP的原则,即Dependency Inversion Principle(依赖倒转原则:面对对象编程的基本原则)。
 
spring最新版本:
Spring Framework 2.0 (current production version 2.0.3)
我们公司大多数使用的
Spring Framework 1.2 (current production version 1.2.8)
       Spring就是一个轻量级的IoC容器。IoC容器最主要的功能就是帮助我们管理对象,并建立他们的依赖关系。
 
 
 
二、Spring框架介绍


         Core封装包是框架最基础的部分,提供IoC和依赖注入特性。
DAO提供了JDBC的抽象和封装,方便我们使用JDBC的方式访问数据库,同时提供了声明式事务管理的功能。
ORM提供了常用的ORM Mapping API(JPA, JDO, Hibernate, iBatis.)的集成。我们公司目前采用Spring提供的ibatis集成。
AOP提供了面向方面的编程实现,让我们可以方便的定义方法拦截器和切点。
WEB提供了针对web层开发的集成特性。
 
三、Core
org.springframework.beans 和org.springframework.context是spring IoC容器的基础。
org.springframework.beans.factory.BeanFactory初始化和配置Bean,装配它们之间的依赖关系。
ApplicationContext 是扩展了BeanFactory ,提供了更多的功能,在使用中Spring作者推荐是使用ApplicationContext。
几个重要的知识点:
(1) spring注入的方式:Setter注入和构造器注入。如果采用Setter方法注入,别忘了在类定义的时候加上setter方法,这一点开发者常常会忘掉,导致NullPointerException。
(2)    自动装配:Spring提供多种自动装配的功能,其中byName是最好用、最常用的。可以大大简化bean的定义。例子
<beans default-autowire="byName">
比如我们定义了一个bean 类,它包含了master属性,并且含有setMaster方法,那么spring会自动在IoC容器中寻找名为master的bean,然后调用setMaster将master对象赋值给master。
 
(3)Bean的作用域
Singleton
Spring容器只存在一个共享的bean实例,默认的配置。
<bean id="example" class="com.yz.bean.Example"/>
Prototype
每次对bean的请求都会创建一个新的bean实例。
<bean id="example" class="com.yz.bean.Example" singleton=”false”/>
 
两者如何选择?原则:所有有状态的bean都使用Prototype作用域,而对无状态的bean则应该使用singleton作用域。
 
(4) 熟悉Spring的配置文件xml中bean的定义,有助于我们灵活地定义bean。
Bean的定义的格式基本如下:
<bean id="example" class="com.yz.bean.Example"/>
id唯一标识该bean,要使用某个bean,只需在容器中通过id获得之,就可以获得它的一个实例。
 
Bean的属性定义如:<properyt name=””>
 
其属性值可以为:
l         其它bean:
ref bean=
ref local=
l         集合
<list> <set> <map> <props>
l         数字,字符串。
 
 
(6) bean定义中的继承关系,使用这种继承关系同样可以简化bean的定义,实际开发中经常被使用。
如果你希望你的java bean的实例能继承另外一个java bean的配置信息。那么你在定义该bean的时候要使用parent属性。
<bean id="childExample" class="com.yz.bean.ChildExample" parent="example"></bean>
尽管这两个bean实际上没有类的继承关系,也可以使用parent属性。这种parent属性的方式实际上提供了模板的形式。
 
(7)  PropertyPlaceholderConfigure
用途:将spring中分布在不同的xml文件的一些属性值统一到一个文件来维护。这样可以提高我们程序的维护性,我们在实际开发中经常使用它。
      
 
   <bean id="placeholderConfig" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
       <property name="location" value="/com/yz/bean/common.properties"/>
    </bean>
    <bean id="datasource" class="org.apache.commons.dbcp.BasicDataSource">
        <property name="driverClassName" value="${jdbc.driverClassName}"/>
        <property name="url" value="${jdbc.url}"/>
        <property name="username" value="${jdbc.username}"/>
        <property name="password" value="${jdbc.password}"/>
    </bean>
 
(8) 资源读取。
       Spring来读取配置文件是按照以下的规则进行的:
前缀
例子
说明
classpath:
classpath:com/myapp/config.xml
classpath中载入。
file:
file:/data/config.xml
从文件系统载入。
http:
http://myserver/logo.png
作为URL载入。
(none)
/data/config.xml
取决于当前的ApplicationContext
      
 
四、AOP
1、背景
AOP(Aspect-Oriented Programming)是对Object-Oriented Programming (OOP)的补充,
OOP通过类的继承实现功能的重用,如果某个功能是多个不同类型的类都需要具有的话,OOP就解决不了这个问题,这样就需要AOP来帮助我们
AOP通过切面来达到我们的实现可以跨越不同对象和类型。
Spring中的AOP主要用于:
(1)       提供声明式企业服务,比如声明的事务管理
(2)       允许使用者实现定制的aspects, 这是对OOP的补充。
 
2、概念
Joinpoint(连接点):程序执行过程中的某个特定的点。比如某个方法的调用或者异常。
通常我们希望在这个joinpoint上执行某个特殊的功能。Spring的AOP目前只支持连接点为方法的调用。
Aspect(切面):横切多个对象的关注点的模块化。比如事务处理,我们有多个对象都需要实现事务处理的功能,Aspect就是我们将多个对象共同关注的功能抽出独立出来。
Advice(通知):在某个特定的Joinpoint上切面执行的动作。通常我们通过拦截器interceptor或者advisor来实现,
Pointcut(切入点):符合某种规则的连接点。
目标对象:被代理的对象。
AOP代理:AOP框架创建的对象,用来代理我们的目标对象。
 
Spring缺省使用j2se动态代理来作为AOP的代理,如果要代理的类没有继承任何接口,spring使用CGLIB代理。Spring使用org.springframework.aop.framework.ProxyFactoryBean来产生代理对象。
 
3、简化代理定义
在实际开发中常常有许多相似的代理定义,那么我们可以创建一个模板bean,这个bean本身不会初始化,每个需要创建的代理都定义为这个bean的子bean。
 
 
五、spring的DAO
1、JDBC封装包
涉及spring的包:core, dataSource, object, and support。
org.springframework.jdbc.core由JdbcTemplate类以及相关的回调接口组成。
org.springframework.jdbc.datasource提供了简化DataSource访问的工具类。
org.springframework.jdbc.object提供了一些处理查询、更新、存储过程的类。
org.springframework.jdbc.support提供了SQLException的转换类和相关的工具类。
Spring将所有jdbc处理中抛出的异常转换为spring dao包中定义的异常,这些异常是unchecked exception,我们可以对这些异常有选择的捕获。这也是Spring提供的一个很重要的特性。
看例子:
2、DataSource可以JNDI,或者apache提供的dbcp,或者spring自带的DriverManagerDataSource。
3、需要了解的知识:
(1)    JdbcTemplate是线程安全的。
(2)   我们如果要获得connection,需要调用DataSourceUtils.getConncetion(),这个类会把SQLException的异常转换为spring的unchecked Exception,并且如果我们使用DataSourceTransactionManager的话,该connection会绑定到当前线程中。
JdbcTemplate就是通过这种方式获得数据库连接的。
 
六、spring的ORM
Spring的ORM提供了对常用ORM Mapping工具的封装,包括Hibernate、JDO、ibatis
等,ibatis由于使用和jdbc sql的访问方式相似,同时sql语句可控,便于DBA优化,所以深受普遍欢迎。
 
 
 
批量操作:
public class SqlMapAccountDao extends SqlMapClientDaoSupport implements AccountDao {
 
    public void insertAccount(Account account) throws DataAccessException {
        getSqlMapClientTemplate().execute(new SqlMapClientCallback() {
            public Object doInSqlMapClient(SqlMapExecutor executor) throws SQLException {
                executor.startBatch();
                executor.update("insertAccount", account);
                executor.update("insertAddress", account.getAddress());
                executor.executeBatch();
            }
        });
    }
}
 
七、Spring的事务管理
1、全局事务和本地事务
如果我们的应用涉及到多个事务性资源的参与(比如多个数据库),我们就需要使用全局事务,全局事务是由应用服务器管理的,我们它使用JTA。
本地事务是指只涉及单个事务资源(比如一台数据库)。应用服务器不涉及事务管理,不能跨越多个资源。
 
2、spring的事务
    Spring使用PlatformTransactionManager来管理事务。定义如下:
<bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
 
3、声明式事务管理
    声明式事务管理,开发者不用编写事务代码就可以实现事务处理。
    Spring的事务管理是通过spring AOP来实现的。
    我们通过TransactionProxyFactoryBean设置Spring事务代理,然后将目标对象包装在事务代理中。当定义TransactionProxyFactoryBean时,必须提供一个相关的PlatformTransactionManager的引用和事务属性。
<bean id="petStoreTarget">
</bean>
<bean id="petStore"
    class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">
    <property name="transactionManager"><ref bean="transactionManager"/></property>
    <property name="target"><ref bean="petStoreTarget"/></property>
    <property name="transactionAttributes">
        <props>
            <prop key="insert*">PROPAGATION_REQUIRED,-MyCheckedException</prop>
            <prop key="update*">PROPAGATION_REQUIRED</prop>
            <prop key="*">PROPAGATION_REQUIRED,readOnly</prop>
        </props>
    </property>
</bean>
 
4、编程式事务管理
Object result = transactionTemplate.execute(new TransactionCallback() {
 
    public Object doInTransaction(TransactionStatus status) {
        updateOperation1();
 
        return resultOfUpdateOperation2();
    }
 
});