Spring随笔

Spring简介:

Spring是一个IOC(DI)和AOP容器框架:

  • 轻量级:Spring是非侵入性的,基于开发的应用中的对象可以不依赖与Spring的API
  • 依赖注入(DI - Dependency injection、IOC)
  • 面向切面编程(AOP - aspect oriented programming)
  • 容器:Spring是一个容器,因为其包含并且管理应用对象的生命周期
  • 框架:Spring实现了使用简单的组建配置组合成一个复杂的应用,在Spring中可以使用XML和Java注解组合这些对象
  • 一站式:在IOC和AOP的基础上可以整个各种企业应用的开源框架和优秀的第三方类库(Spring自身提供了展现层SpringMVC与持久层Spring JDBC)

Spring模块:

Spring

搭建Spring开发环境:

  • 导入jar包:
commons-logging.jar(Spring依赖的jar包)
spring-beans.RELEASE.jar
spring-context-RELEASE.jar
spring-core.RELEASE.jar
spring-expression.RELEASE.jar
spring-aop.RELEASE.jar
  • Spring的配置文件:一个典型的spring文件项目需要创建一个或多个Bean配置文件,这些配置文件用于在SpringIOC容器里配置Bean.Bean的配置文件可以放在classpath下,也可以放在其他目录下

Spring的设置基本步骤:

  • 类路径下创建配置文件:applicationContext.xml(配置bean)
<bean id="customer" class="com.djh.demo.Customer">
     <property name="cusName" value="Tom"></property>
</bean>
  • 在java Code中加入以下步骤注入bean:
    • 创建Spring的IOC的容器对象
    ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
    
    • 从IOC容器中获取Bean的实例
    Customer customer = ctx.getBean("customer");
    

Spring Bean的配置

  • 配置形式:
    • 基于XML文件的方式
    • 基于注解的方式
  • Bean的配置方式:
    • 通过全类名(反射)
    • 通过工厂方法(静态工厂方法&实例工厂方法)
    • FactoryBean
  • IOC容器BeanFactory & ApplicationContext概述
  • 依赖注入的方式:
    • 属性注入
    • 构造器注入
    • 注入属性值细节
    • 自动专配
  • bean之间的关系:
    • 继承
    • 依赖
  • bean的作用域:
    • singleton
    • prototype
    • WEB环境作用域
  • 使用外部属性文件
  • 在Spring的IOC容器里配置Bean:
    • 在xml文件中通过bean节点来配置bean
    <bean id="customer" class="com.djh.demo.Customer">
         <property name="cusName" value="Tom"></property>
    </bean>
    
    • id:Bean的名称
    • 在IOC容器中必须是唯一的
    • 若id没有指定, Spring自动将权限定性类名作为Bean的名字
    • id可以指定多个名字,之间用逗号、分号或空格分隔
  • Spring提供的两种类型的IOC容器实现:
    • BeanFactory:IOC容器的基本实现
    • ApplicationContext:提供了更多的高级特性,为BeanFactory的子接口
  • ApplicationContext的主要实现类:
    • ClassPathXmlApplicationContext:从类路径下加载配置文件
    • FileSystemXmlApplicationContext:从文件系统中加载配置文件
    • ApplicationContext在初始化上下文时就实例化所有单例的Bean
  • 依赖注入的方式(3种):
    • 属性注入(即setter方法),属性注入使用<property>元素,使用name属性执行Bean的属性名称,value属性或<value>子节点指定属性值
      如:
<bean id="customer" class="com.djh.demo.Customer">
     <property name="cusName" value="Tom"></property>
</bean>
  • 构造器注入
    在<constructor-arg>元素里声明,<constructor-arg>中没有name属性
<bean id="customer" class="com.djh.demo.Customer">
     <!-- index参数决定Bean的构造方法中第几个参数,type决定其参数类型 -->
     <constructor-arg value="Tom" index="0" type="java.lang.String"></constructor-arg>
</bean>
  • 工厂方法注入
    对于注入的值包含特殊字符,如:<, >等,需要使用<![CDTAT[xxx]]>来表示
  • 引用其他的Bean:
    在Bean的配置文件中,可以通过<ref>元素或ref属性为Bean的属性或构造器参数指定对Bean的作用
    也可以在属性或构造器里包含Bean的声明,这样的Bean称为内部Bean,不能被外部引用
    • 注入null值与级联属性:
      可以使用<null/>元素标签为Bean的字符串或其他对象类型的属性注入null值
  • SSH均支持级联属性的配置,如:
<property name="customer.cusName" value="Michael" />

对于集合类型的属性,使用list、set或map标签方式,如下:

<property name="customers">
<list>
<ref bean="customer1" />     //或<value>Jacky</value>
<ref bean="customer2" />
</list>
</property>

<map>标签里可以有多个<entry>子标签,每个条目包含一个key与value,简单常量使用key与value来定义,Nean引用通过key-ref与value-ref属性定义
使用<props>定义java.util.Properties,该标签使用多个<prop>作为子标签,每个<prop>标签必须定义key属性

Spring自动装配:

  • Spring IOC容器可以自动装配Bean,需要做的仅仅是在<bean>的autowire属性里指定自动装配的模式
    • byType(根据类型自动装配):Spring IOC 容器中不能有多个与目标Bean类型一致的Bean
    • byName(根据名称自动装配):必须将目标Bean的名称和属性名设置的完全相同
  • Bean的名称与setter方法的名称一致的,如:
    • Person Bean:
class Person{
     private String personName;
     private Address address;
     //Getter and Setter method
}
  • Address Bean:
class Address{
     private String street;
     //Getter and Setter method
}
  • configure file:
<bean id="address" class="com.djh.demo.Address">
     <property name="street" value="TianHe" />
</bean>
<bean id="person" class="com.djh.demo.Person" autowire="byType">
     <property name="personName" value="Michael" />
</bean>

constructor(通过构造器自动装配)

  • Spring的Bean之间的关系:
    • 继承(parent属性),如:Customer{String:custName, int:age}
    <bean id="customer" class="com.djh.demo.Customer">
    <property name="age" value="20" />
    <property name="custName" value="Lucy" />
    </bean>
    <bean id="customer2" parent="customer">
    <property name="custName" value="Michael" />
    </bean>
    
    • 依赖(depends-on属性)
      Spring允许通过depeds-on属性设定Bean前置依赖的Bean,前置依赖的Bean会在本Bean实例化之前创建好
      如果前置依赖于多个Bean,则可以通过逗号、空格的方式配置Bean的名称
  • Spring中Bean的作用域,使用scope属性进行配置,作用域有以下四个,默认为singleton
    • prototype:容器初始化时不会创建Bean实例,而是在每次请求创建Bean的实例时返回
    • request
    • session
    • singleton:创建IOC容器(ApplicationContext)时就创建了Bean实例,单例的
    • 如:
<bean id="customer" class="com.djh.demo.Customer" scope="prototype">
<property name="custName" value="djh" />
</bean>
  • 使用外部属性文件:
    Spring提供了一个PropertyPlaceholderConfigurer的BeanFactory后置处理器,该处理器允许用户将Bean的部分内容移到属性文件中,可以在Bean配置文件中使用形式为${var}的变量,PropertyPlaceholderConfigurer从属性文件里加载属性,并使用这些属性来替换变量
    Spring还允许在属性文件中使用${propName},以实现属性之间的相互引用
  • 注册PropertyPlaceholderConfigurer
    • Spring2.0:
<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="location" value="classpath:database.properties" />
</bean>
  • Spring2.5:
    通过<context:property-placeholder>元素
    <beans>中添加context Schema定义,即加入context的Namespaces
    在配置文件中加入如下配置:
//导入配置文件
<context:property-placeholder location="classpath:database.properties" />
//导入后可以使用${key}的形式访问配置文件中对应的value

SpEL

  • 一个支持运行时查询和操作对象的表达式语言
    语法类似于EL,使用#{xxx}作为定界符,所有在大括号中的字符都被认为是SpEL
  • SpEL为bean的属性进行动态复制提供了便利
  • SpEL可以实现如下功能:
    • 通过bean的id对bean进行引用
    • 调用方法以及引用对象中的属性
    • 计算表达式的值
    • 正则表达式的匹配
  • SpEL字面量:
    • 整数:
      <property name="count" value="#{5}" />
    • 小数:
      <property name="frequency" value="#{88.2}" />
    • 科学计数法:
      <property name="capacity" value="#{1e4}" />
    • String可以使用单引号或者双引号作为字符串的定界符:
    <property name="name" value="#{'djh'}" />
    <property name="count" value='#{"Lucy"}' />
    
    • Boolean:
    <property name="display" value="#{true}" />
    
  • SpEL引用Bean、属性与方法:
    • 引起其他对象(Bean):
    <!-- 通过value属性与SpEL配置的ean之间的应用关系 -->
    <property name="prefix" value="#{prefixGenerator}" />
    
    • 引用其他对象的属性:
    <property name="stuffix" value="#{prefixGenerator.stuffix}" />
    
    • 通过其他方法,还可以链式操作:
    <!-- 通过value属性和SpEL配置stuffix属性值为另一个Bean的方法的返回值 -->
    <property name="stuffix" value="#{prefixGenerator.toString()}" />
    <!-- 方法的连缀 -->
    <property name="stuffix" value="#{prefixGenerator.toString().toUpperCase()}" />
    
    • 调用静态方法或静态属性:通过T()调用一个类的静态方法,返回一个类对象
    <property name="initValue" value="#{T(java.lang.Math).PI}" />
    

Spring工厂方法配置Bean

  • 调用静态工厂方法创建Bean是将对象创建的过程封装到静态方法中
  • 要声明通过静态方法创建的Bean,需要在Bean的class属性里指定拥有该工厂方法的类,同时在factory-method属性里指定工厂方法的名称,最后使用<constructor-arg>元素为该方法传递方法参数
    • FactoryBean(接口):
    • getObject():返回bean对象
    • getObjectType():返回bean的类型
    • isSingleton():返回bean是否单例

注解配置Bean:

  • 在classpath中扫描组件
    Spring能够从classpath下自动扫描,侦测和实例化具有特定注解的组件
  • 特定组件包括以下几个:
    • @Component:基本注解,标识了一个受Spring管理的组件
    • @Repository:标识持久层组件
    • @Service:标识服务层(业务层)组件
    • @Controller:标识表现层组件
  • 对于扫描到的组件,Spring有默认的命名策略,使用非限定类名,第一个字母小写,也可以在注解中通过value属性值标识组件的名称
  • 当在组件类上使用了特定的注解之后,还需要在Spring的配置文件中声明<context:component-scan>:
    base-package属性指定一个需要扫描的基类包,Spring容器将会扫描这个基类包里及其子包中的所有类
  • 当需要扫描多个包时,可以使用逗号分隔
  • 如果仅希望扫描特定的类而非基包下的所有类,可使用resource-pattern属性过滤特定的类,如:
<context:component-scan
     base-package="com.djh.demo.spring.beans"
     resource-pattern="autowire/*.class" />     <!-- 表示指定扫描com.djh.demo.spring.beans.autowire下的所有类 -->
  • 如下所示:
    • 结构:


      Structor
    • 配置文件:


      Configuration
    • 各个类的注解:
      Person.java:


      Annotation

      MockController.java:


      Annotation

      DataBaseMockImp.java:
      Annotation

      ServiceMock.java:
      Annotation

      测试结果:


      result
    • <context:include-filter>子节点表示要包含的目标类,需要将<context:component-scan>use-default-filters属性的值设置为false.
    • <context:exclude-filter>子节点表示要排除在外的目标类
    • <context:component-scan>下可以拥有若干个<context:include-filter><context:exclude-filter>子节点
  • 使用注解装配Bean与Bean之间的关联关系(组件装配):
    <context:component-scan>元素会自动注册AutowiredAnnotationBeanPostProcessor实例,该实例可以自动装配具有@Autowired@Resource@Inject注解的属性
    • 如:


      Autowire

      Autowire
    • 测试结果:


      result
    • @AutoWired自动装具有兼容类型的单个Bean属性:
      • 构造器,普通字段(即使非public),一切具有参数的方法都可以应用@Autowired注解
      • 默认情况下,所有使用@Autowired注解的属性都需要被设置,当Spring找不带匹配的Bean装配属性时,会抛出异常,若某一属性允许不被设置,可以设置@Autowired注解的required属性为false.
  • @Resource注解要求一个Bean名称的属性,若该属性为空,则自动采用标注处的变量或方法名作为Bean的名称

Spring AOP:

  • AOP(Aspect-Oriented-Programming)
    • 解决日志以及代码的混乱问题
    • AOP:面向切面编程,是一种新的方法论,是对传统的OOP的补充
    • AOP的主要编程对象是切面,而切面模块化切关注点
    • AOP的优点:
      • 每个事物逻辑位于一个位置,代码不分散,便于维护和升级
      • 业务模块更简洁,只包含核心业务代码
  • 动态代理的方式处理日志:
    • 被代理对象:


      Object
    • 被代理对象实现类:


      Object implement class
    • 代理类:


      Proxy class
    • 测试类:


      Test class
  • AOP分析:


  • AOP关键词:
    • 切面(Aspect):横切关注点被模块化的特殊对象
    • 通知(Advice):切面必须要完成的工作
    • 目标(Target):被通知的对象
    • 代理(Proxy):向目标对象应用通知之后创建的对象
    • 连接点(Joinpoint):程序执行的某个特定位置,如某个方法调用前、调用后、抛出异常等
    • 切点(pointcut):每个类都拥有多个连接点。AOP通过切点定位到特定的连接点,一个切点可对应多个连接点
  • AspectJ(Spring2.0以上)为Java社区中最完整最流行的AOP框架,配置方式有以下两种:
    • 基于注解
    • 基于XML
    • 基于注解AspectJ注解支持:
      • 必须在classpath下包含AspectJ类库: aopalliance.jar、aspectj.weaver.jar、spring-aspects.jar
      • 将aop Schema添加到<beans>根元素中
      • 要在Spring IOC容器中启用AspectJ注解支持,只要在Bean配置文件中定义一个空的XML元素<aop:aspectj-autoproxy>
      • 必须要在Bean配置文件中配置需要的Bean,通过<context:component-scan/>元素
  • 当Spring IOC容器侦测到Bean配置文件中的<aop:aspectj-autoproxy>元素时,会自动为与AspectJ切面匹配的Bean创建代理
  • 使用注解声明一个切面需要两步:
    • 把相应的类加到IOC容器中
    • 声明该类为一个切面
    • 声明执行的位置
  • 在配置文件中加入:
    <!-- 使AspectJ注解起作用, 自动为匹配的类生成代理对象 -->
    <aop:aspectj-autoproxy></aop:aspectj-autoproxy>
    
  • 如:
    • 结构:


      structure
    • 注解:


      annotation
    • 配置:


      configuration
    • 测试结果:


      Test result
  • 在AspectJ注解中,切面只是一个带有@Aspect注解的Java类
  • 通知就是标注有某种注解的简单的Java方法
  • AspectJ支持5种类型的通知注解:
    • @Before:前置通知,在方法执行之前执行
      annotation
    • @After:后置通知,在方法执行之后执行,无论是否发生异常都会执行
      annotation
    • @AfterRunning:返回通知,在方法返回结果之后执行
      annotation
    • @AfterThrowing:异常通知,在方法抛出异常之后会执行
      annotation
    • @Around:环绕通知,围绕着方法执行
  • 切面优先级的指定:
    • 通过加入注解@Order(number), number值越小,优先级越高
  • 重用切入点表达式:
    • 通过定义一个声明的方法


    • 对于非当前类的其他类中的方法,可以使用如下形式:(包名+类名+方法名)


  • 基于XML配置文件的方式来配置AOP:
    • 结构:


      Structure
    • 切面类:


      Aspect
    • 配置文件:


      Config
    • 测试结果:


      TR

Spring对JDBC的支持:

  • 使用JdbcTemplate更新数据库
    • 用sql语句和参数更新数据库(update)
      public int update(String sql, Object ... args) throw DataAccessException
    • 批量更新数据库(batchUpdate)
      public int[] batchUpdate(String sql, List<Object[]> batchArgs)
    • 查询多行(query)
      public <T> List<T> query(String sql, ParameterizedRowMapper<T> rm, Object... args)throws DataAccessException
    • 单值查询(queryForObject)
      public <T> T queryForObject(String sql, Class<T> requiredType, Object... args) throw DataAccessException
  • 配置文件获取数据库连接信息:
    • 结构:


    • springContext.xml
    <!-- 导入资源文件 -->
    <context:property-placeholder location ="classpath:db.properties" />
    <!-- 配置C3p0数据源 -->
    <bean id ="dataSource" class = "com.mchange.v2.c3p0.ComboPooledDataSource">
      <property name = "user" value = "${user}"></property>
      <property name = "password" value = "${password}"></property>
      <property name = "driverClass" value = "${driverClass}"></property>
      <property name = "jdbcUrl" value = "${jdbcUrl}"></property>
      <property name = "maxPoolSize" value = "${maxPoolSize}" ></property>
      <property name = "initialPoolSize" value = "${initialPoolSize}"></property>
      </bean>
    
    • db.properties:
    user = root
    password = java
    driverClass = com.mysql.jdbc.Driver
    jdbcUrl = jdbc:mysql://localhost:3306/spring
    maxPoolSize = 10
    initialPoolSize = 5
    
    • JdbcTemplate的配置,配置信息如下:
    <!-- 配置Spring的JdbcTemplate -->
    <bean id = "jdbcTemplate" class = "org.springframework.jdbc.core.JdbcTemplate">
      <property name = "dataSource" ref = "dataSource" ></property>
    </bean>
    
    • 测试结果:


  • JdbcTemplate的单批更新插入与批量插入:
    • 方法:


      Implement
    • 测试结果:


      TR
  • JdbcTemplate的查询:(queryForObject、queryForList用于获取某一列的值)
    • 方法:


      Implement
    • 测试结果:


      TR
  • JdbcTemplate不支持级联属性
    • JdbcTemplate是线程安全的,故可以在IOC容器中声明它的单个实例,并将这个实例注入到所有的DAO实例中,如:
    • DAO类:


      DAO
    • 配置DAO依赖注入JdbcTemplate:


    • 测试结果:


      TR
  • spring JDBC框架还提供了一个JdbcDaoSupport类来简化DAO实现,该类声明了jdbcTemplate属性,它可以从IOC容器中注入.或者从数据源中创建
  • Spring使用NamedParameterJdbcTemplate
    • 经典JDBC中,SQL参数使用占位符(?)表示
    • 在Spring JDBC框架中,绑定SQL参数的另一种方式是使用具名参数(named parameter),也即是绑定变量(bind variable)
    • 具名参数只在NamedParameterJdbcTemplate中得到支持
    • 配置形式:
    <!-- 配置具名参数 -->
    <bean id = "namedParameterJdbcTemplate" class ="org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate">  
    <constructor-arg ref = "jdbcTemplate"></constructor-arg>  <--NamedParameterJdbcTemplate没有无参构造器,必须提供参数-->
    </bean>
    
    • 如:


  • 使用具名参数可以传递对象进行操作,如:


Spring事物管理

  • 用于确保数据的完整性与一致性
  • 事物的四个关键属性(ACID)
    • 原子性(automicity)
    • 一致性(consistency)
    • 隔离性(isolation)
    • 持久性(durability)
  • Spring中的事物管理:
    • Spring既支持编程式事物管理,也支持声明式事物管理
      • 编程式事物管理:将事物管理代码嵌入到业务方法中来控制事物的提交和回滚
      • 声明式事物管理:将事物管理代码从业务方法中分离出来,以声明的方式来实现事物管理,可以通过AOP方法模块化,Spring通过Spring AOP框架支持声明式事物管理
  • Spring的核心事物管理抽象是Interface PlatformTransactionManager,管理封装了一组独立于技术的方法
  • Spring中的事物管理器的不同实现:
  • Class DataSourceTransactionManager:在应用程序中只需要处理一个数据源,且通过JDBC存取
  • Class JtaTransactionManager:在JavaEE应用服务器上用JTA(Java Transaction API)进行管理
  • Class HibernateTransactionManager:用Hibernate框架存取数据库
    ...
  • 事物管理器以普通的Bean形式声明在Spring IOC容器中
  • 声明式事物:
    • 配置事物管理器:
    <!-- 配置事物管理器 -->
    <bean id= "dataSourceTransactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">      
    <property name="dataSource" ref="dataSource"></property>
    </bean>
    <!-- 使用注解事物时,需要启用事物注解 -->
    <tx:annotation-driven transaction-manager = "dataSourceTransactionManager"/>
    
    • 事物注解,使用@Transactional,如:
  • Spring事物的传播行为:
    • 当事物方法被另一个事物方法调用时,必须指定事物应该如何传播
    • 事物的传播行为可以由传播属性指定
    • Spring支持的事物传播行为有以下几种:
      • REQUIRED(默认的传播行为,即使用调用方法的事物)
      • REQUIRED_NEW
      • SUPPORTS
      • NOT_SUPPORTED
      • MANDATORY
      • NEVER
      • NESTED
    • 使用propagation指定传播行为,如:
    @Transactional
    (propagation=Propagation.REQUIRED)
    
  • Spring通过注解设置事物隔离级别、回滚、只读、过期:
  • 使用isolation指定事物的隔离级别
    • 回滚:默认情况下,Spring的声明式事物对所有的运行时异常进行回滚,可以通过以下属性设置,一般不做设置:
      • noRollbackFor
      • rollbackFor
      • rollbackForClassName
    • 只读:该属性通过readOnly设置,取值为true或false,表示这个事物只读取数据但不更新数据,这样可以帮助数据库引擎优化事物
    • 过期(超时):使用timeout指定强制回滚之前事物可以占用的时间,单位为秒(S),如ATM机的取款倒计时
      • 如:


  • Spring通过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:tx = "http://www.springframework.org/schema/tx"   
        xmlns:aop = "http://www.springframework.org/schema/aop"
        xsi:schemaLocation = "http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.0.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.0.xsd">
<!-- 注解方式自动配置Bean -->     
<!-- 
 <context:component-scan base-package="com.djh.spring.transaction"></context:component-scan>
-->
<!-- 导入资源文件 -->      
<context:property-placeholder location = "classpath:db.properties"/>
<!-- 配置C3p0数据源 -->     
<bean id = "dataSource" class = "com.mchange.v2.c3p0.ComboPooledDataSource">
     <property name = "user" value = "${user}" ></property>           
    <property name = "password" value = "${password}"></property>        
    <property name = "driverClass" value = "${driverClass}"></property>     
    <property name = "jdbcUrl" value = "${jdbcUrl}" ></property>      
    <property name = "maxPoolSize" value = "${maxPoolSize}"></property>        
    <property name = "initialPoolSize" value = "${initialPoolSize}"></property>
</bean>
<!-- 配置Spring的JdbcTemplate -->  
<bean id = "jdbcTemplate" class = "org.springframework.jdbc.core.JdbcTemplate">
  <property name = "dataSource" ref = "dataSource" ></property> 
</bean>   
<!-- 配置具名参数 -->    
<bean id = "namedParameterJdbcTemplate" class = "org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate">         
  <constructor-arg ref = "jdbcTemplate" ></constructor-arg> 
</bean>
<!-- 配置事物管理器 -->     
<bean  id = "dataSourceTransactionManager" class = "org.springframework.jdbc.datasource.DataSourceTransactionManager">          
  <property name = "dataSource" ref = "dataSource"></property>
</bean>
<!-- 配置Bean -->      
<bean id = "bookShopDAO" class = "com.djh.spring.transaction.BookShopDaoImp">
  <property name = "jdbcTemplate" ref = "jdbcTemplate"></property>  
</bean>   
<bean id = "bookShopService" class = "com.djh.spring.transaction.BookShopServiceImp">        
  <property name = "bookShopDao" ref = "bookShopDAO" ></property>     
</bean>  
<!-- 配置事物属性 -->    
<tx:advice id = "txAdvice" transaction-manager = "dataSourceTransactionManager">
  <tx:attributes>                
    <!-- 根据方法名配置 -->                   
    <tx:method name = "service" propagation = "REQUIRES_NEW" />                       
    <tx:method name = "*" />           
  </tx:attributes>   
</tx:advice>  
<!-- 配置事物切入点,将事物切入点与事物属性关联 -->   
<aop:config>          
  <aop:pointcut expression = "execution(* com.djh.spring.transaction.BookShopDao.*(..))" id = "txPointCut" />
  <aop:advisor advice-ref = "txAdvice" pointcut-ref = "txPointCut"/>  
</aop:config>
<!-- 注解的方式,启用事物注解 -->  
<!-- 
<tx:annotation-driven transaction-manager="dataSourceTransactionManager"/>
-->
</beans>
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,080评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,422评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,630评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,554评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,662评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,856评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,014评论 3 408
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,752评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,212评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,541评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,687评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,347评论 4 331
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,973评论 3 315
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,777评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,006评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,406评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,576评论 2 349

推荐阅读更多精彩内容