spring学习笔记

来源:互联网 发布:数据库审计是干什么 编辑:程序博客网 时间:2024/06/05 04:33

10:56 2012/4/5
spring概念
Spring是一个开源大的控制反转(Inversion of Control,IOC)和面向切面(AOP)的容器框架,它的主要目的是简化企业开发。
******************************************************************************************************************

10:58 2012/4/5
IOC控制反转
public class PersonServiceBean{
    private PersonDao personDao = new PersonDaoBean();
    
    public void save(Person person){
        personDao.save(person);
    }
}
PersonDaoBean是在应用程内部创建及维护的。所谓控制反转就是应用本身不负责依赖对象的创建及维护,依赖对象的创建及维护是由外部容器负责的。这样控制权就由应用转移到了外部容器,控制权的转移就是所谓反转。
******************************************************************************************************************

11:07 2012/4/5
依赖注入(Dependency Injection)
当我们把依赖对象交给外部容器负责创建,那么PersonServiceBean类可以改成如下:
public class PersonServiceBean{

    private PersonDao personDao;
    //通过构造器参数,让容器把创建好的依赖对象注入进P而宋ServiceBean,当然也可以使用setter方法进行注入。
    public PersonServiceBean(PersonDao personDao){
        this.personDao = personDao
    }
    public void save(Person person){
        personDao.save(person);
    }
}
所谓依赖注入就是指:在运行期,由外部容器动态地将依赖对象注入到组件中。

注入方法:
1、使用构造器注入
2、使用属性setter方法注入
3、使用field注入(用于注解方式)

注入依赖对象可以采用手工装配或自动装配,在实际应用中建议使用手工装配,因为自动装配会产生未知情况,开发人员无法预见最终的装配结果。

1、手工装配依赖对象
2、自动装配依赖对象
******************************************************************************************************************

11:13 2012/4/5
为何要使用Spring
1、降低组件之间的耦合度,实现软件各层之间的解耦。
Controller ——→ Service ——→ DAO

2、可以使用容器提供的众多服务,如:事务管理服务、消息服务等等。当我们使用容器管理事务时,开发人员就不再需要手工控制事务,也不需处理复杂的事务传播。

3、容器提供单例模式支持,开发人员不再需要自己编写实现代码。

4、容器提高AOP技术,利用它很容易实现如权限拦截、运行期监控等功能。

5、容器提供的众多辅助作类,使用这些类能够加快应用的开发,如:jdbcTemplate、HibernateTemplate。

6、Spring对于主流的应用框架提供了集成支持,如:集成Hibernate、JPA、Struts等,这样更便于应用的开发。
******************************************************************************************************************

16:15 2012/4/5
使用spring的好处
容器
    事务管理服务    JMS服务        Spring core核心服务    持久化服务    其它
        |    |            |            |    |
----------------|-------|---------------------|-|-----------------------|-------|---
                          |
                    简单java对象


******************************************************************************************************************

16:32 2012/4/5
轻量级与重量级概念的划分
经常会有同学问到spring属于轻量级框架还是重量级框架?其实划分一个应用是否属于轻量级还是重量级,主要看它使用了多少服务。使用的服务越多,容器要为普通java对象做的工作就越多,必然会影响到应用的发布时间或者是运行性能。
对于Spring容器,它提供了很多服务,但这些服务并不是默认为应用打开的,应用需要某种服务,还需要指明使用该服务,如果应用使用的服务很少,如:只是用了spring核心服务,那么我们可以认为此时应用属于轻量级,如果应用使用了spring提供的大部分服务,这是应用就属于重量级。目前EJB容器就因为它默认为应用提供了EJB规范中所有功能,所以它属于重量级。
******************************************************************************************************************

16:38 2012/4/5
使用spring需要的jar
到http://www.springsource.org/download下载spring,然后进行解压缩,在解压缩目录中找到下面jar文件,拷贝到类路径下

dist\spring.jar
lib\jakarta-commons\commons-logging.jar
如果使用了切面编程(AOP),还需要下列jar文件
lib\aspectj\aspectjweaver.jar和aspectjrt.jar
lib\cglib\cglib0nodep-2.1_3.jar
如果使用了JSR-250中的注解,如@Resource/@PostConstruct/@PerDestroy,还需要下列jar文件
lib\j2ee\commons-annotations.jar
******************************************************************************************************************

17:04 2012/4/5
spring的配置文件模板
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
           http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">

  <bean id="..." class="...">
    <!-- collaborators and configuration for this bean go here -->
  </bean>

  <bean id="..." class="...">
    <!-- collaborators and configuration for this bean go here -->
  </bean>

  <!-- more bean definitions go here -->

</beans>
该配置模板可以从spring的参考手册或spring的例子中得到。配置文件的取名可以任意,文件可以存放在任何目录下,但考虑到通用性,一般放在类目录下。
******************************************************************************************************************

17:24 2012/4/5
实例化spring容器
实例化spring容器常用的两种方式:
方法一:
在类路径下寻找配置文件来实例化容器
ApplicationContext ctx = new ClassPathXmlApplicationContext(new String[]{"beans.xml"});

方法二:
在文件系统路径下寻找配置文件来实例化容器
ApplicationContext ctx = new FileSystemXmlApplicationContext(new String[]{"d:\\beans.xml"});
Spring的配置文件可以指定多个,可以通过string数组传入。
******************************************************************************************************************

22:30 2012/4/5
三种实例化bean的方式
1、使用类构造器实例化
<bean id="orderService" class="cn.flame.OrderServiceBean" />
2、使用静态工厂方法实例化
<bean id="personService" class="cn.flame.service.OrderFactory" factory-method="createOrder" />
public class OrderFactory{
    public static OrderServiceBean createOrder(){
        return new OrderServiceBean();
    }
}
3、使用实例工厂实例化:
<bean id="personServiceFactory" class="cn.flame.service.OrderFactory" />
<bean id="personService" factory-bean="personServiceFactory" factory-method="createOrder" />
public class OrderFactory{
    public OrderServiceBean createOrder(){
        return new OrderServiceBean();
    }
}
******************************************************************************************************************

23:03 2012/4/5
Bean的作用域
.singleton
在每个spring Ioc容器中一个bean定义只有一个对象实例。默认情况下会在容器启动时初始化bean,但我们可以指定Bean节点的lazy-init="true"来延迟初始化bean,这时候,只有第一次获取bean才会初始化bean。如:
<bean id="xxx" class="cn.flame.OrderServiceBean" lazy-init="true" />
如果想对所有bean都应用延迟初始化,可以再根节点beans设置default-lazy-init="true",如下:
<beans default-lazy-init="true" .../>

.prototype
每次从容器获取bean都是新对象。
<bean id="personService" class="cn.flame.service.impl.PersonServiceBean" scope="prototype" />

.request

.session

.globalession
******************************************************************************************************************

23:14 2012/4/5
指定Bean的初始化方法和销毁方法
<bean id="xxx" class="cn.flame.OrderServiceBean" init-method="init" destroy-method="close" />
******************************************************************************************************************

23:26 2012/4/5
注入依赖对象
基本类型对象注入
<bean id="orderService" class="cn.flame.service.OrderServiceBean" >
    <constructor-arg index="0" type="java.lang.String" value="xxx" />//构造器注入
    <property name="name" value="zhao" />//属性setter方法注入
</bean>

注入其他bean:
方式一:
<bean id="orderDao" class="cn.flame.service.OrderDaoBean" />
<bean id="orderService" class="cn.flame.service.OrderServiceBean">
    <property name="orderDao" ref="orderDao" />
</bean>

方式二:
<bean id="orderService" class="cn.flame.service.OrderServiceBean" >
    <property name="orderDao">
        <bean class="cn.flame.service.OrderDaoBean" />
    </property>
</bean>
******************************************************************************************************************

7:38 2012/4/6
集合类型的装配
public class OrderServiceBean{

    private Set<String> sets = new HashSet<String>();
    private List<String> lists = new ArrayList<String>();
    private Properties properties = new Properties();
    private Map<String,String> maps = new HashMap<String,String,>();
    .
    .
    .//这里省略属性的getter和setter方法
}
******************************************************************************************************************

8:16 2012/4/6
依赖注入-手工装配
1、在xml配置文件中,通过bean节点下配置,如:
<bean id="orderService" class="cn.flame.service.OrderServiceBean" >
    <constructor-arg index="0" type="java.lang.String" value="xxx" />//构造器注入
    <property name="name" value="zhao" />//属性setter方法注入
</bean>

2、在java代码中使用@Autowired或@Resource注解方式进行装配。但我们需要在xml配置文件中配置以下信息:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"  
       xsi:schemaLocation="http://www.springframework.org/schema/beans
           http://www.springframework.org/schema/beans/spring-beans-2.5.xsd"
            http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd">
</beans>
这个配置隐式注册了多个对注解进行解析处理的处理器:AutowiredAnnotationBeanPostProcessor,
CommonAnnotationBeanPostProcessor,PersistenceAnnotationBeanPostProcessor,RequiredAnnotationBeanPostProcessor
注:@Resource注解在spring安装目录lib\j2ee\common-annotations.jar

在java代码中使用@Autowired或@Resource注解方式进行装配,这两个注解的区别是:
@Autowired默认按类型装配,@Resource默认按名称装配,当找不到与名称匹配的bean才回按类型装配。
@Autowired
private PersonDao personDao;//用于字段上
@Autowired
public void setOrderDao(OrderDao orderDao){//用于属性的setter方法上
    this.orderDao = orderDao;
}
@Autowired注解是按类型装配依赖对象,默认情况下它要求依赖对象必须存在,如果允许null值,可以设置它required属性为false。如果我们想使用按名称装配,可以结合@Qualifier注解一起使用。如下:
@Autowired @Qualifier("personDaoBean")
private PersonDao personDao;

@Resource注解和@Autowired一样,也可以标注在字段或属性的setter方法上,但它默认按名称装配。名称可以通过@Resource的name属性指定,如果没有指定name属性,当注解标注在字段上,即默认去字段的名称作为bean名称寻找依赖对象,当注解标注在属性的setter方法上,即默认取属性名作为bean名称寻找依赖对象。
@Resource(name="personDaoBean")
private PersonDao personDao;//用于字段上

注意:如果没有指定name属性,并且按照默认的名称仍然找不到依赖对象时,@Resource注解会回退到按类型装配。但一旦指定了name属性,就只能按名称装配了。
******************************************************************************************************************

11:36 2012/4/6
依赖注入--自动装配依赖对象
对于自动装配,大家了解一下就可以了,是在不推荐大家使用。例子:
<bean id="..." class="..." autowire="byType" />
autowire属性取值如下:

1、byType:按类型装配,可以根据属性的类型,在容器中寻找跟该类型匹配的bean。如过发现多个,那么将会抛出异常。如果没有找到,即属性值为null。

2、byName:按名称装配,可以根据属性的名称,在容器中寻找跟该属性名相同的bean,如果没有找到,即属性值为null。

3、constructor与byType的方式类似,不同之处在于它应用于构造参数。如果在容器中没有找到与构造参数类型一致的bean,那么将会抛出异常。

4、autodetect:通过bean类的自省机制(introspection)来决定是使用constructor还是byType方式进行自动装配。如果发现默认的构造器,那么将使用byType方式。
******************************************************************************************************************

11:55 2012/4/6
通过classpath自动扫描方式把组件纳入spring容器中管理
前面的例子我们都是XML的bean定义来配置组件。在一个稍大的项目中,通常会有上百个组件,如果这些组件采用XML的bean定义配置,显然会增加配置文件的体积,查找及维护起来也不方便。spring2.5为我们引入了组件自动扫描机制,他可以在类路径底下寻找标注@Component、@Service、@Controller、@Repository注解的类,并把这些类纳入进spring容器中管理。它的作用和在xml文件中使用bean节点配置组件是一样的。要使用自动扫描机制,我们需要打开以下配置信息:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"  
       xsi:schemaLocation="http://www.springframework.org/schema/beans
           http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
           http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd">
    <context:component-scan base-package="cn.flame" />
</beans>
其中base-package为需要扫描的包(含子包)

@Service用于标注业务层组件、@Controller用于标注控制层组件(如struts中的action)、@Repository用于标注数据访问层,即DAO组件。而@Component泛指组件,当组件不好归类的时候,我们可以用这个注解进行标注。
******************************************************************************************************************

18:39 2012/4/6
AOP--代理对象
一般应用于权限项目里面,对方法进行拦截,然后鉴定权限之后进行放行。
******************************************************************************************************************

23:36 2012/4/6
使用JDK自带的代理proxy实现AOP代理
JDKProxyFactory代码
-----------------------------------------------------------------------------------
public class JDKProxyFactory implements InvocationHandler {
    private Object targetObject;
    
    public Object createProxyIntance(Object targetObject){
        this.targetObject = targetObject;
        return Proxy.newProxyInstance(
                this.targetObject.getClass().getClassLoader(),
                this.targetObject.getClass().getInterfaces(), this);
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args)
            throws Throwable {
        PersonServiceBean bean = (PersonServiceBean) this.targetObject;
        Object result = null;//环绕通知
        if(bean.getUsers() != null){
            //...advice() --->前置通知
            try {
                result = method.invoke(targetObject, args);
                //...afteradvice() --->后置通知
            } catch (Exception e) {
                //...Exceptionavdice() --->异常通知
            }finally{
                //...finallyadvice() --->最终通知
            }
        }
        return result;
    }
}
-----------------------------------------------------------------------------------
Client代码
-----------------------------------------------------------------------------------
public void test() {
    JDKProxyFactory factory = new JDKProxyFactory();
    PersonService service = (PersonService) factory.createProxyIntance(new PersonServiceBean());
    service.save("dfa");
}
******************************************************************************************************************

23:37 2012/4/6
使用spring提供的CGLIB生成代理
CGLIBProxyFactory代码
-----------------------------------------------------------------------------------
public class CGLIBProxyFactory implements MethodInterceptor {
    private Object targetObject;
    
    public Object createProxyIntance(Object targetObject){
        this.targetObject = targetObject;
        Enhancer enhancer = new Enhancer();
        enhancer.setSuperclass(this.targetObject.getClass());
        enhancer.setCallback(this);
        return enhancer.create();
    }

    @Override
    public Object intercept(Object proxy, Method method, Object[] args,
            MethodProxy methodProxy) throws Throwable {
        PersonServiceBean bean = (PersonServiceBean) this.targetObject;
        Object result = null;
        if(bean.getUsers() != null){
            result = methodProxy.invoke(this.targetObject, args);
        }
        return result;
    }
}
-----------------------------------------------------------------------------------
Client代码
-----------------------------------------------------------------------------------
public void test2(){
    CGLIBProxyFactory factory = new CGLIBProxyFactory();
    PersonServiceBean serviceBean = (PersonServiceBean) factory.createProxyIntance(new PersonServiceBean("xxx"));
    serviceBean.save("444");
}
-----------------------------------------------------------------------------------
CGLIB可以生成目标类的子类,并重写父类非final修饰符的方法。
******************************************************************************************************************

23:46 2012/4/6
AOP中的概念
1、Aspect(切面):指横切性关注点的抽象即为切面,它与类相似,知识两者的关注点不一样,类是对无图特征的抽象,而切面是横切性关注点的抽象。

2、joinpoint(连接点):所谓连接点是指那些被拦截到的点。在spring中,这些点指的是方法,因为spring只支持方法类型的连接点,实际上joinpoint还可以是field或类构造器。

3、Pointcut(切入点):所谓切入点是指我们要对那些joinpoint进行拦截的定义。

4、Advice(通知):所谓通知是指拦截到joinpoint之后所要做的事情就是通知。通知分为前置通知,后置通知,异常通知,最终通知,环绕通知。

5、Target(目标对象):代理的目标对象。

6、Weave(织入):指将aspects应用到target对象并导致proxy对象创建的过程称为织入。

7、Introduction(引入):在不修改类代码的前提下,Introduction可以再运行期为类动态地添加一些方法或Field。
******************************************************************************************************************

0:31 2012/4/7
使用Spring进行面向切面(AOP)编程
要进行AOP编程,首先我们要在spring的配置文件中引入aop命名空间:

Spring提供了两种切面使用方式,实际工作中我们可以选用其中一种:
1、基于XML配置方式进行AOP开发
2、基于注解方式进行AOP开发。
******************************************************************************************************************

0:36 2012/4/7
基于注解方式声明切面
首先启动对@AspectJ注解的支持
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
     xmlns:aop="http://www.springframework.org/schema/aop"
     xsi:schemaLocation="http://www.springframework.org/schema/beans
         http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
         http://www.springframework.org/schema/aop
         http://www.springframework.org/schema/aop/spring-aop-2.5.xsd">
    <aop:aspectj-autoproxy/>      
</beans>
-----------------------------------------------------------------------------
@Aspect
public class LogPrint{
    @Pointcut("execution(* cn.flame.service..*.*(..))")
    private void anyMethod(){}//声明一个切入点
    @Before("anyMethod() && args(userName)")//定义前置通知
    public void doAccessCheck(String userName){
    }
    @AfterReturning(pointcut="anyMethod()",returning="revalue")//定义异常通知
    public void doExceptionAction(String revalue){
    }
    @AfterThrowing(pointcut="anyMethod()",throwing="ex")//定义异常通知
    public void doExceptionAction(Exception ex){
    }
    @After("anyMethod()")//定义最终通知
    public void doReleseAction(){
    }
    @Around("anyMethod()")//环绕通知
    public Object doBasicProfiling(ProceedingJoinPoint pjp)throws Throwable{
        return pjp.proceed();
    }
}
-----------------------------------------------------------------------------
******************************************************************************************************************

14:12 2012/4/7
Spring+JDBC组合开发
使用Spring+JDBC集成步骤如下:
1、配置数据源,如:
 <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
   <property name="driverClassName" value="${jdbc.driverClassName}"/>
   <property name="url" value="${jdbc.url}"/>
   <property name="username" value="${jdbc.username}"/>
   <property name="password" value="${jdbc.password}"/>
   <!-- 连接池启动时的初始值 -->
   <property name="initialSize" value="1"/>
   <!-- 连接池的最大值 -->
   <property name="maxActive" value="500"/>
   <!-- 最大空闲值,经过一个高峰时间后,连接池可以慢慢将已经用不到的连接慢慢释放一部分,一直减少到MaxIdLe为止 -->
   <property name="maxIdle" value="2"/>
   <!-- 最小空闲值,当空闲的连接数少于阀值时,连接池就会预申请去一些连接,以免洪峰来时来不及申请 -->
   <property name="minIdle" value="1"/>
 </bean>
使用<context:property-placeholder location="jdbc.properties" />属性占位符
2、配置事务。配置事务时,需要在xml配置文件中引入用声明事务的tx命名空间(见下页),事务的配置方式有两种:注解方式和基于XML配置方式。
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:aop="http://www.springframework.org/schema/aop"
       xmlns:tx="http://www.springframework.org/schema/tx"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
           http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
           http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd
           http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd
           http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd">
</beans>
******************************************************************************************************************

14:55 2012/4/7
采用注解方式配置事务
1、采用注解方式
<bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
    <property name="dataSource" ref="dataSource" />
</bean>
<!-- 采用@Transactional注解方式使用事务 -->
<tx:annotation-dirven tarnsaction-manager="txManager" />

@Service @Transactional
public class PersonServiceBean implements PersonService{
}

******************************************************************************************************************

16:50 2012/4/7
spring+jdbc时bean文件的配置
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:aop="http://www.springframework.org/schema/aop"
       xmlns:tx="http://www.springframework.org/schema/tx"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
           http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
           http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd
           http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd
           http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd">

    <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource"
        destroy-method="close">
        <property name="driverClassName" value="com.microsoft.sqlserver.jdbc.SQLServerDriver" />
        <property name="url"
            value="jdbc:sqlserver://localhost:2644;DatabaseName=JDBCDemo" />
        <property name="username" value="sa" />
        <property name="password" value="123456" />
        <property name="initialSize" value="1" />
        <property name="maxActive" value="500" />
        <property name="maxIdle" value="2" />
        <property name="minIdle" value="1" />
    </bean>
    <bean id="txManager"
        class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="dataSource" />
    </bean>
    <tx:annotation-driven transaction-manager="txManager" />
    <bean id="personService" class="cn.flame.service.impl.PersonServiceBean">
        <property name="dataSource" ref="dataSource"></property>
    </bean>
</beans>

******************************************************************************************************************

20:42 2012/4/7
事务传播属性
REQUIRED:业务方法需要在一个事务中运行。如果方法运行时,已经处在一个事务中,那么加入到该事务,否则为自己创建一个新的事务。

NOT_SUPPORTED:声明方法不需要事务。如果方法没有关联到一个事务,容器不会为它开启事务,如果方法在一个事务中被调用,该事务会被挂起,在方法调用结束后,原先的事务便会恢复执行。

REQUIRESNEW:属性表明不管是否存在事务,业务方法总会为自己发起一个新的事务,如果方法已经运行在一个事务中,则原有事务会被挂起,新的事务会被创建,直到执行方法结束,新事物才算结束,原先的事务才回恢复执行。

MANDATORY:该属性指定业务方法不能再一个已经存在的事务中执行,业务方法成为该事务的一部分。如果业务方法在事务范围外被调用,则方法在没有事务的环境下执行。

SUPPORTS:这一事务表明,如果业务方法在某个事务范围内被调用,则方法成为该事务的一部分。如果业务方法在事务范围外被调用,则方法在没有事务的环境下执行。

Never:指定业务方法绝对不能在事务范围内执行。如果业务方法在某个事务中执行,容器会抛出例外,只有业务方法没有关联到任何事务,才能执行。

NESTED:如果一个活动的事务存在,则运行在一个嵌套的事务中。如果没有活动事务,则按REQUIRED属性执行。它使用了一个单独的事务,这个事务拥有多个可以回滚的保存点。内部事务的回滚不会对外部事务造成影响。它只对DataSourceTransactionManager事务管理器起效。
******************************************************************************************************************

21:41 2012/4/7
数据库系统提供了四种事务隔离级
数据系统提供了四种事务隔离级别供用户选择。不同的隔离级别采用不同的类型来实现,在四种隔离级别中,serializable的隔离级别最高,Read Uncommited的隔离级别最低。大多数数据库默认的隔离级别为Read Commited,如sqlserver,当然也有少部分数据库默认的隔离级别为Repeatable Read,如Mysql
1、Read Uncommited:读为提交数据(会读出脏读,不可重复读和幻读)。
2、Read Commited:读已提交数据(会出现不可重复读和幻读)。
3、Repeatable Read:可重复读(会出现幻读)。
4、Serializable:串行化。

脏读:一个事务读取到另一个事务未提交的更新数据。
不可重复读:在同一个事务中,多次读取同一数据返回的结果有所不同。换句话说就是,后续读取可以读到另一个事务已提交的更新数据。相反,“可重复读”在同一事务中多次读取时,能够保证所读数据一样,也就是,后续读取不能读到另一个事务已提交的更新数据。
幻读:一个事务读取到另一个事务已提交的insert数据。
******************************************************************************************************************

22:05 2012/4/7
采用基于XML方式配置事务
<bean id="txManager"
    class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
    <property name="dataSource" ref="dataSource" />
</bean>

<aop:config>
    <aop:pointcut id="transactionPointcut" expression="execution(*cn.flame.service.*.*(..))" />
    <aop:advisor advice-ref="txAdvice" pointcut-ref="transactionPointcut" />
</aop:config>
<tx:advice id="txAdvice" transaction-manage="txManager" >
    <tx:attributes>
        <tx:method name="get*" read-only="true" propagation="NOT_SUPPORTED" />
        <tx:method name="*"/>
    </tx:attributes>
******************************************************************************************************************