Spring
- spring是一个容器
- spring是一个分层的java ee/(一站式)轻量级开源框架
- 它不排斥其他框架,还帮其他框架管理对象
- aop支持
- ioc思想
- spring jdbc
- aop事务
- junit支持
Spring框架搭建
步骤:
-
导包
-
创建一个对象
-
书写配置,注册对象到容器(配置文件的位置、名称任意,建议方法哦src下,名字为applicationContext.xml);约束引入
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://www.springframework.org/schema/beans" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.2.xsd ">
<!-- 将User对象交给Spring容器管理 --> <bean name="user" class="com.rabbit.bean.User"></bean> </beans>
-
代码测试
public void fun1() { //创建容器对象 ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml"); //向容器“要对象” User u = (User) ac.getBean("user"); //打印user对象 System.out.println(u); }
约束引入:
D:\JavaStdNotes\java框架学习\SSH\Spring\spring-day01\spring-day01\video\03-spring项目搭建-约束引入_.flv
Spring概念
思想 :IOC DI
IOC:Inverse Of Control
- 将我们创建对象的方式反转;以前是对象的创建是由我们开发人员自己维护。包括依赖关系也是自己人注入;
- 使用了Spring之后,对象的创建以及对象中的依赖关系,可以由Spring完成创建以及注入;
- 反转控制就是反转了创建对象的方式,从我们自己创建反转给了(程序)Spring;
DI:Dependency Injection (依赖注入)
- 实现IOC之前需要DI支持;
- 注入方式:
- set方法注入
- 构造方法注入
- 字段注入
- 注入类型:
- 值类型注入:8大基本数据类型
- 引用类型注入:将依赖对象注入
applicationContext&BeanFactory
BeanFactory接口:
- Spring 原始接口,针对原始接口的实现功能较为单一
- BeanFactory接口实现类的容器,特点是每次在获得对象时才会创建对象
ApplicationContext:
- 每次容器启动时就会创建容器中配置的所有对象
- 提供了更多功能
- 实现类:
- ClassPathXmlApplicationContext;从类路径下加载配置文件(主要使用)
- FileSystemXMLApplicationContext;从硬盘绝对路径下加载配置文件
结论:在web开发中使用applicationContext;资源匮乏时可以使用BeanFactory
配置文件
Bean元素使用:该元素描述需要搜谱spring容器管理的对象:
- name属性:给被管理的对象起个名字,过得对象时根据名称获得对象
- class属性:被管理的对象完整路径名
- id属性:与name属性一模一样。名称不可重复,并且不能使用特殊字符
三种对象创建方式:
-
空参构造创建(常用):
<!-- 将User对象交给Spring容器管理 空参构造创建--> <bean name="user" class="com.rabbit.bean.User"></bean>
-
静态工厂创建(了解):
<!-- 2. 静态工创建: 调用UseerFactory的createUser()方法创建名为user2的对象,放入容器--> <bean name="user2" class="com.rabbit.Factory.UserFactory" factory-method="createUser"></bean>
-
实例工厂创建:
<!-- 3. 实例工厂创建--> <bean name="user3" factory-bean="userFactory" factory-method="createUser2"></bean> <bean name="userFactory" class="com.rabbit.Factory.UserFactory"></bean>
Bean元素进阶:scope属性
- singleton(重要):默认值为singleton,单例对象,在spring容器中只会存在一个实例;多用singleton
- prototype(重要):多例原型;被标识为多例的对象每次在获得时才会创建对象;并且每次创建都是一个新的对象;在与struts2整合的时候Action要用prototype;
- request(了解):web环境下对象与request生命周期一致
- session(了解):web环境下,对象与session生命周期一致;
Bean元素进阶:生命周期属性(了解)
- 配置一个方法作为生命周期初始化方法,sprign会在对象创建之后立即调用;init-method
- 配置一个方法作为生命周期销毁方法,spring容器在关闭前销毁所有容器中的对象;destory-method;
spring的分模块配置:
<!-- 引入其他spring配置文件 路径为去src之后的路径-->
<import resource="/applicationContext.xml"/>
spring属性注入
set方法注入(重点):
<!--set方式注入-->
<bean name="user" class="com.rabbit.bean.User">
<!-- 值类型注入:为名为name的属性注入tom作为值 -->
<property name="name" value="tom"></property>
<property name="age" value="18"></property>
<!-- 引用类型注入:注入对象 ref;为car属性注入上方的car -->
<property name="car" ref="car"></property>
</bean>
<!-- 将Car对象配置到容器中 -->
<bean name="car" class="com.rabbit.bean.Car">
<property name="name" value="兰博基尼"></property>
<property name="color" value="橘色"></property>
</bean>
构造函数注入(掌握):
<!-- 构造函数注入 -->
<bean name="user2" class="com.rabbit.bean.User">
<!-- User 构造函数public User(String name, Car car) -->
<!-- index为构造函数里面属性所在的索引位置 -->
<!-- type为构造函数里面属性的类型 -->
<constructor-arg name="name" value="jerry" index="0" type="java.lang.String"></constructor-arg>
<constructor-arg name="car" ref="car"></constructor-arg>
</bean>
p名称空间注入(了解):
-
导入p名称空间:xmlns:p=“http://www.springframework.org/schema/p”
-
使用p:属性完成注入:
<!-- p名称空间注入 --> <bean name="user3" class="com.rabbit.bean.User" p:name="jack" p:age="20" p:car-ref="car"></bean>
spel注入:(了解)
<!--spel(Spring expression Language sping)表达式语言注入 -->
<bean name="user4" class="com.rabbit.bean.User">
<property name="name" value="#{user.name}"></property>
<property name="age" value="#{user3.age}"></property>
<property name="car" ref="car"></property>
</bean>
复杂类型注入:
```xml
<!-- 复杂类型注入 -->
<!-- array数组注入 -->
<bean name="cbean" class="com.rabbit.bean.CollectionBean">
<!-- 如果数组中只有一个属性 可以直接value |ref即可-->
<!-- 如果数组中有多个属性-->
<property name="arr">
<array>
<value>tom</value>
<value>jerry</value>
<ref bean="user4"/>
</array>
</property>
<!-- list -->
<property name="list">
<list>
<value>red</value>
<value>green</value>
<ref bean="user3"/>
</list>
</property>
<!-- map类型 -->
<property name="map">
<map>
<entry key="url" value="jdbc:mysql:///crm"></entry>
<entry key="user" value-ref="user4"></entry>
</map>
</property>
<!-- properties类型 -->
<property name="prop">
<props>
<prop key="driverClass">com.jdbc.mysql:Driver</prop>
<prop key="username">root</prop>
<prop key="password">admin</prop>
</props>
</property>
让spring容器随项目启动而启动,销毁而销毁:web.xml配置文件配置;导入spring-web-4.2.4.RELEASE.jar
<!-- 让spring容器随项目启动创建,随项目关闭而销毁 -->
<listener>
<listener-class>org.springframework.web.context.ContextLoader</listener-class>
</listener>
<!-- 指定加载配置文件的位置 -->
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:applicationContext.xml</param-value>
</context-param>
获取spring容器:
//获得spring容器==》从application域获得即可
//获得ServletContext对象
ServletContext sc = ServletActionContext.getServletContext();
//从sc中获得ac容器
WebApplicationContext ac = WebApplicationContextUtils.getWebApplicationContext(sc);
//从容器获得CustomerService
CustomerService service = (CustomerService) ac.getBean("customerService");
#使用注解配置spring:导入spring注解依赖包spring-aop-4.2.4.RELEASE.jar #
-
为配置文件导入新的命名空间约束
-
开启注解代替配置文件
<!-- 指定扫面com.rabbit.bean包下的所有类中的注解 注意:扫描包时会扫描指定包下的所有子孙包 --> <context:component-scan base-package="com.rabbit.bean"></context:component-scan>
-
使用注解:
//这4个注解功能没有任何区别 @Component("user")//domain层 //<bean name="user" class="com.rabbit.bean.User"> @Service("user")//用于注册service层 @Controller("user")//web层 @Repository("user")//dao层
-
指定对象作用域:
@Component("user") @Scope(scopeName="prototype")//指定对象的作用域,默认为单例的不用写
-
注解指定值类型:可以写在成员变量上(通过反射赋值),也可以写在set方法上(通过set赋值)
@Component("user") public class User { @Value("tom") private String name; private int age; private Car car; }
-
引用类型注入方式1:
-
首先把该对象加入容器
-
在对象成员变量上加上注解:
@Autowired//自动装配:问题:这种方式如果在容器类有多个对象就无法保证能选取哪一个 private Car car;
-
解决问题:不建议使用
@Autowired @Qualifier("car2")//使用这个注解选择具体的对象在容器中名称 private Car car;
-
-
引用类型注入方式2:推荐使用
@Resource(name="car2")//手动注入,指定哪个名称的对象 private Car car;
-
指定方法为初始化,销毁方法:
@PostConstruct//让该方法为初始化方法;跟配置文件中的init-method一样 public void init() { System.out.println("初始化"); } @PreDestroy//让该方法为销毁时调用的方法 public void destory() { System.out.println("销毁"); }
sts插件:配置文件可以有提示
AOP思想 : 面向切面编程
Spring能够为容器中管理的对象生成动态代理对象:
- spring能够为我们生成代理对象
Spring实现aop原理:
-
动态代理:
- 被代理对象必须要实现接口,如果没有接口将不能实现动态代理
-
cglib代理:
- 带三方代理技术,cglib代理,可以对任何类生成代理。因为代理的原理是对目标对象进行继承代理
AOP名称学习:
- joinpoint(连接点):目标对象中,所有可以曾强的方法
- Pointcut(切入点):目标对象,已经增强的方法
- Advice(通知/增强):增强的代码
- Target(目标对象):被代理对象
- Weaving(织入):将通知织入切入点
- Proxy(代理):将通知织入到目标对象后形成代理对象
- aspect(切面):切入点+通知
Spring中的AOP演示:
- 导包(4+2+2+2)
- 准备目标对象
- 准备通知
//通知类
public class MyAdvice {
//前置通知:目标方法运行之前调用
//后置通知(如果出现异常,将不会调用):在目标方法运行之后调用
//环绕通知:在目标方法之前和之后都调用
//异常拦截通知:如果出现异常,就会调用
//后置通知(无论是否出现异常都会调用):在目标方法运行之后调用
//前置通知
public void before() {
System.out.println("前置通知");
}
//后置通知:如果方法出现异常不调用
public void after() {
System.out.println("后置通知,异常不调用");
}
//环饶通知
public Object around(ProceedingJoinPoint pjp) throws Throwable {
System.out.println("环绕通知之前的部分");
Object proceed = pjp.proceed();//调用目标方法
System.out.println("环绕通知之后的部分");
return proceed;
}
//异常通知
public void afterException() {
System.out.println("出事了之后执行的异常通知");
}
//后置通知
public void after2() {
System.out.println("出现异常也会调用");
}
}
-
配置进行织入,将通知织入目标对象
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://www.springframework.org/schema/beans" xmlns:context="http://www.springframework.org/schema/context" xmlns:aop="http://www.springframework.org/schema/aop" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.2.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.2.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.2.xsd "> <!-- 准备工作:导入aop约束命名空间 --> <!-- 1.配置目标对象 --> <bean name="userServiceTarget" class="com.rabbit.interf.UserServiceImp"></bean> <!-- 2.配置通知类 --> <bean name="myAdvice" class="com.rabbit.spring_aop.MyAdvice"></bean> <!-- 3.配置将通知织入目标对象 --> aop:config <!-- 配置切入点 切入表达式expression="execution(public void com.rabbit.interf.UserServiceImp.save())":只增强save() public是默认的,可以不写 void com.rabbit.interf.UserServiceImp.save() 返回值任意 * com.rabbit.interf.UserServiceImp.save() 任意方法 * com.rabbit.interf.UserServiceImp.*() 任意名为xxxServiceImp的任意方法任意参数 * com.rabbit.interf.ServiceImp.(..) 最终形态 - com.rabbit.interf..ServiceImp.(..) 最终形态 --> <aop:pointcut expression="execution(* com.rabbit.interf.ServiceImp.(..))" id="pc"/> <aop:aspect ref="myAdvice"> <!-- 指定名为before的方法为前置通知 --> <aop:before method="before" pointcut-ref="pc"/> <!-- 后置 --> <aop:after-returning method="afterreturning" pointcut-ref="pc"/> <!-- 环绕 --> <aop:around method="around" pointcut-ref="pc"/> <!-- 异常拦截 --> <aop:after-throwing method="afterException" pointcut-ref="pc"/> <!-- 后置 --> <aop:after method="after" pointcut-ref="pc"/> /aop:aspect /aop:config </beans>
测试:这里使用注解获取容器对象UserService:
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:com/rabbit/spring_aop/applicationContext.xml")
public class Demo1 {
@Resource(name="userService")
private UserService us;
@Test
public void fun1() {
us.save();
}
}
使用注解配置aop(了解):
配置文件:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://www.springframework.org/schema/beans" xmlns:context="http://www.springframework.org/schema/context" xmlns:aop="http://www.springframework.org/schema/aop" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.2.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.2.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.2.xsd ">
<!-- 准备工作:导入aop约束命名空间 -->
<!-- 1.配置目标对象 -->
<bean name="userService" class="com.rabbit.interf.UserServiceImp"></bean>
<!-- 2.配置通知类 -->
<bean name="myAdvice" class="com.rabbit.annotation_aop.MyAdvice"></bean>
<!-- 3.开启使用注解完成织入 -->
<aop:aspectj-autoproxy></aop:aspectj-autoproxy>
</beans>
注解配置:
//通知类
@Aspect
//这个注解表示该类为一个通知类
public class MyAdvice {
//前置通知
@Before("execution(* com.rabbit.interf.*ServiceImp.*(..))")
public void before() {
System.out.println("前置通知");
}
//后置通知:如果方法出现异常不调用
@AfterReturning("execution(* com.rabbit.interf.*ServiceImp.*(..))")
public void afterreturning() {
System.out.println("后置通知,异常不调用");
}
//环饶通知
@Around("execution(* com.rabbit.interf.*ServiceImp.*(..))")
public Object around(ProceedingJoinPoint pjp) throws Throwable {
System.out.println("环绕通知之前的部分");
Object proceed = pjp.proceed();//调用目标方法
System.out.println("环绕通知之后的部分");
return proceed;
}
//异常通知
@AfterThrowing("execution(* com.rabbit.interf.*ServiceImp.*(..))")
public void afterException() {
System.out.println("出事了之后执行的异常通知");
}
//后置通知
@After("execution(* com.rabbit.interf.*ServiceImp.*(..))")
public void after() {
System.out.println("出现异常也会调用");
}
}
spring整合JDBC
-
spring中提供了一个可以操作数据库的对象,对象封装了jdbc技术:JDBCTemplate 模板对象;与DButils中的QueryRunner非常相似;
-
导包:4+2;spring test;spring aop c3p0连接池;jdbc驱动;spring-jdbc;spring-tx;
测试:
准备增删改查的类:
package com.rabbit.jdbctemplate;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.List;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.RowMapper;
//使用jdbc模板实现增删改查
public class UserDaoImp implements UserDao {
private JdbcTemplate jt;
public JdbcTemplate getJt() {
return jt;
}
public void setJt(JdbcTemplate jt) {
this.jt = jt;
}
@Override
public void save(User u) {
String sql = "insert into t_user values(?,?)";
jt.update(sql,u.getId(), u.getName());
}
@Override
public void delete(Integer id) {
String sql = "delete from t_user where id = ?";
jt.update(sql, id);
}
@Override
public void update(User u) {
String sql = "update t_user set name = ? where id = ?";
jt.update(sql,u.getName(),u.getId());
}
@Override
public User getById(Integer id) {
String sql = "select * from t_user where id = ?";
User user = jt.queryForObject(sql, new RowMapper<User>() {
@Override
public User mapRow(ResultSet rs, int arg1) throws SQLException {
User u = new User();
u.setId(rs.getInt("id"));
u.setName(rs.getString("name"));
return u;
}},id);
return user;
}
@Override
public int getTotalCount() {
String sql = "select count(*) from t_user";
Integer count = jt.queryForObject(sql, Integer.class);
return count;
}
@Override
public List<User> getAll() {
String sql = "select * from t_user";
List<User> list = jt.query(sql, new RowMapper<User>() {
@Override
public User mapRow(ResultSet rs, int arg1) throws SQLException {
User u = new User();
u.setId(rs.getInt("id"));
u.setName(rs.getString("name"));
return u;
}});
return list;
}
}
spring容器配置文件配置:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://www.springframework.org/schema/beans" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.2.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.2.xsd ">
<!-- 1.将连接池放入spring容器 -->
<bean name="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
<property name="jdbcUrl" value="jdbc:mysql://localhost:3306/mysqltest?serverTimezone=GMT%2B8"></property>
<property name="driverClass" value="com.mysql.cj.jdbc.Driver"></property>
<property name="user" value="root"></property>
<property name="password" value="admin"></property>
</bean>
<!-- 2.将jdbctemplate放入spring容器 -->
<bean name="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
<property name="dataSource" ref="dataSource"></property>
</bean>
<!-- 3.将UserDao放入Spring容器 -->
<bean name="userDao" class="com.rabbit.jdbctemplate.UserDaoImp">
<property name="jt" ref="jdbcTemplate"></property>
</bean>
</beans>
代码测试:增删改查
package com.rabbit.jdbctemplate;
import javax.annotation.Resource;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import com.mchange.v2.c3p0.ComboPooledDataSource;
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:applicationContext.xml")
public class Demo1 {
@Resource(name="userDao")
private UserDao ud;
@Test
public void fun1() throws Exception {
//准备连接池
ComboPooledDataSource dataSource = new ComboPooledDataSource();
dataSource.setDriverClass("com.mysql.cj.jdbc.Driver");
dataSource.setJdbcUrl("jdbc:mysql://localhost:3306/mysqltest?serverTimezone=GMT%2B8");
dataSource.setUser("root");
dataSource.setPassword("admin");
//创建JDBC模板对象
JdbcTemplate jt = new JdbcTemplate();
jt.setDataSource(dataSource);
//书写sql
String sql = "insert into t_user values(null,'rose')";
//执行
jt.update(sql);
}
@Test
public void fun2() throws Exception {
User u = new User();
u.setId(2);
u.setName("杨丽");
ud.save(u);
}
@Test
public void fun3() throws Exception {
User i = ud.getById(2);
System.out.println(i.toString());
}
@Test
public void fun4() throws Exception {
ud.delete(2);
}
}
使用properties配置文件封装连接池,用spring取读取配置文件获得连接数据库的数据;
properties配置文件:
jdbc.jdbcUrl=jdbc:mysql://localhost:3306/mysqltest?serverTimezone=GMT%2B8
jdbc.driverClass=com.mysql.cj.jdbc.Driver
jdbc.user=root
jdbc.password=admin
修改spring配置文件:
<!-- 指定spring读取db.properties配置 -->
<context:property-placeholder location="classpath:db.properties" />
<!-- 1.将连接池放入spring容器 -->
<bean name="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
<property name="jdbcUrl" value="${jdbc.jdbcUrl}"></property>
<property name="driverClass" value="${jdbc.driverClass}"></property>
<property name="user" value="${jdbc.user}"></property>
<property name="password" value="${jdbc.password}"></property>
</bean>
Spring中的aop事务
-
事务
- 事务特性:acid
- 事务并发问题:脏读,幻读;不可重复读
- 事务的隔离级别:
- 1:读未提交
- 2:读已提交
- 4:可重复度
- 8:串行化
-
spring封装了事务管理代码:
- 事务操作
- 打开事务
- 提交事务
- 回滚事务
- 事务操作对象
- 因为在不同平台操作事务代码各不相同,spring提供了一个接口(PlatformTransactionManager)
- PlatformTransactionManager接口有各平台的实现类:
- DataSourceTransactionManager:jdbc事务管理
- HibernateTransactionManager:Hibernate事务管理
- Spring管理事务的属性介绍:
- 事务的隔离级别:1.2.4.8
- 是否只读:false、true
- 事务的传播行为:有7个供我们选择:基本只会用这个:PROPACATION_REQUIRED(默认):支持当前事务,如果不存在,就新建一个
- 事务操作
spring管理事务方式:
-
编码式(了解):代码里管理事务,缺点,需要修改的时候得去修改原码
-
将核心事务管理器放到spring容器
-
xml配置(常用,开发中用这个):
-
导包
-
导入命名空间约束:xsi,beans:最基本,aop:配置aop,tx:配置事务,context:注解,读取properties配置文件
-
配置文件:
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://www.springframework.org/schema/beans" 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-4.2.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.2.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.2.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.2.xsd "> <!-- 指定spring读取db.properties配置 --> <context:property-placeholder location="classpath:db.properties" /> <!-- 事务核心管理器,封装了所有事务操作. 依赖于连接池 --> <bean name="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager" > <property name="dataSource" ref="dataSource" ></property> </bean> <!-- 事务模板对象 --> <bean name="transactionTemplate" class="org.springframework.transaction.support.TransactionTemplate" > <property name="transactionManager" ref="transactionManager" ></property> </bean> <!-- 配置事务通知 --> <tx:advice id="txAdvice" transaction-manager="transactionManager" > <tx:attributes> <!-- 以方法为单位,指定方法应用什么事务属性 isolation:隔离级别 propagation:传播行为 read-only:是否只读 --> <tx:method name="save*" isolation="REPEATABLE_READ" propagation="REQUIRED" read-only="false" /> <tx:method name="persist*" isolation="REPEATABLE_READ" propagation="REQUIRED" read-only="false" /> <tx:method name="update*" isolation="REPEATABLE_READ" propagation="REQUIRED" read-only="false" /> <tx:method name="modify*" isolation="REPEATABLE_READ" propagation="REQUIRED" read-only="false" /> <tx:method name="delete*" isolation="REPEATABLE_READ" propagation="REQUIRED" read-only="false" /> <tx:method name="remove*" isolation="REPEATABLE_READ" propagation="REQUIRED" read-only="false" /> <tx:method name="get*" isolation="REPEATABLE_READ" propagation="REQUIRED" read-only="true" /> <tx:method name="find*" isolation="REPEATABLE_READ" propagation="REQUIRED" read-only="true" /> <tx:method name="transfer" isolation="REPEATABLE_READ" propagation="REQUIRED" read-only="false" /> </tx:attributes> </tx:advice>
<!-- 配置织入 --> <aop:config > <!-- 配置切点表达式 --> <aop:pointcut expression="execution(* com.rabbit.service.*ServiceImpl.*(..))" id="txPc"/> <!-- 配置切面 : 通知+切点 advice-ref:通知的名称 pointcut-ref:切点的名称 --> <aop:advisor advice-ref="txAdvice" pointcut-ref="txPc" /> </aop:config>
<bean name="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource"> <property name="jdbcUrl" value="${jdbc.jdbcUrl}"></property> <property name="driverClass" value="${jdbc.driverClass}"></property> <property name="user" value="${jdbc.user}"></property> <property name="password" value="${jdbc.password}"></property> </bean>
<!-- 2.Dao--> <bean name="accountDao" class="com.rabbit.dao.AccountDaoImpl" > <property name="dataSource" ref="dataSource" ></property> </bean> <!-- 3.Service--> <bean name="accountService" class="com.rabbit.service.AccountServiceImpl" > <property name="ad" ref="accountDao" ></property> <property name="tt" ref="transactionTemplate" ></property> </bean> </beans>
-
注解配置(常用,开发中用这个):
-
导包
-
导入命名空间约束:xsi,beans:最基本,aop:配置aop,tx:配置事务,context:注解,读取properties配置文件
-
配置文件:
tx:annotation-driven/
添加注解到测试的方法或者类上(类上可以管理所有的方法,但是优先级不如加在方法上面):@Transactional(isolation=Isolation.REPEATABLE_READ,propagation=Propagation.REQUIRED,readOnly=false) public void transfer(Integer from, Integer to, Double money) { //减钱 ad.dereaseMoney(from, money); //int i = 1/0; //价钱 ad.increaseMoney(to, money); }