spring
@(JAVAWEB)
介紹(基于spring 4.2.4)
對(duì)象的容器遭笋,spring負(fù)責(zé)管理項(xiàng)目中的所有對(duì)象测暗,可以看成是整個(gè)項(xiàng)目的管家
spring是一站式的框架
正因?yàn)槭侨萜髦屎停萜髦醒b了狠多對(duì)象比如web操作的對(duì)象瘫想,service的對(duì)象,dao的對(duì)象
spring搭建
- 1.導(dǎo)包
這幾個(gè)包,是spring的核心包(core)
導(dǎo)包之后并沒(méi)有完成需要 創(chuàng)建xml文件
一般命名為applicationContext.xml
然后需要添加xml約束
接下來(lái)是將類放入Spring的容器中
-新建User類
@Component("user")
//相當(dāng)于xml文件中的an配置
//最好用下面幾種方式
//@Service("user")
//@Controller("user")
//@Repository("user")
//@Scope(scopeName = "prototy")//此屬性來(lái)設(shè)置user類是否是單例還是多例默認(rèn)單例。
public class User {
@Value("vv")//也可以添加到set方法上,在屬性上面是通過(guò)反射的field進(jìn)行賦值洞拨,而方法上是通過(guò)set方法賦值
private String name;
private int age;
@Autowired //自動(dòng)裝配,前提是car類需要進(jìn)行component等注解歹河。
//Autowired會(huì)有一問(wèn)題當(dāng)spring容器中有多個(gè)car類型的對(duì)象時(shí)衅澈,如car1经备,car2時(shí)可以使用下面兩種注解
//@Qualifier("car2") 不推薦此種需要和Autowired一起配合使用
//@Resource(name = "car2")建議這種方式,當(dāng)容器中有多個(gè)引用對(duì)象的時(shí)候
private Car car;
public User() {
System.out.println("空參構(gòu)造");
}
public Car getCar() {
return car;
}
public void setCar(Car car) {
this.car = car;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return "User{" +
"name='" + name + '\'' +
", age=" + age +
", car=" + car +
'}';
}
@PostConstruct //在對(duì)象創(chuàng)建之后調(diào)用等同于 init-method
public void init() {
System.out.println("我是初始化方法");
}
@PreDestroy //在銷毀前調(diào)用
public void destroy() {
System.out.println("我是銷毀方法");
}
}
2.到applicationContext.xml中配置
IDEA會(huì)自己生成Spring得約束XML文件
代碼測(cè)試
測(cè)試結(jié)果
spring概念
IOC (Inverse Of Control) 概念:
將我們創(chuàng)建對(duì)象的方式反轉(zhuǎn),一千對(duì)象的創(chuàng)建由我們開(kāi)發(fā)人員自己維護(hù),包括依賴關(guān)系也是自己注入.
使用了Spring之后,對(duì)象的創(chuàng)建和依賴關(guān)系可以由Spring完成創(chuàng)建以及注入.
簡(jiǎn)單來(lái)說(shuō)就是:反轉(zhuǎn)了對(duì)象的創(chuàng)建方式,有自己創(chuàng)建變?yōu)榱顺绦蚩刂?
DI(dependency Injection):實(shí)現(xiàn)IOC思想需要DI支持
注入方式:
- 1.set方式
- 2.構(gòu)造方法注入
- 3.字段注入
注入類型:
- 值類型注入:基本數(shù)據(jù)類型
- 引用類型注入:將依賴對(duì)象注入
applicationContext和anfactory
BeanFactory
Spring原始接口的實(shí)現(xiàn)類功能單一
anFactory接口實(shí)現(xiàn)類的容器部默,特點(diǎn)是每次在獲得對(duì)象時(shí)才會(huì)創(chuàng)建對(duì)象侵蒙。
applicationContext
特點(diǎn):每次容器啟動(dòng)時(shí)就會(huì)創(chuàng)建容器中配置的所有對(duì)象。
提供了更多功能傅蹂。
從類路勁下加載配置文件:classPathXMLApplicationContext
從硬盤(pán)絕對(duì)路勁下加載配置文件FilePathXMLApplicationContext
web開(kāi)發(fā)中使用applicationContext,在資源匱乏的環(huán)境可以使用anFactory镐躲。
spring配置詳解
Bean元素
Spring創(chuàng)建對(duì)象方式
1.空參構(gòu)造方式
靜態(tài)工廠方式
動(dòng)態(tài)工廠方式
an元素晉級(jí)
scope屬性
singleton(默認(rèn))單例對(duì)像,spring容器中只會(huì)存在一個(gè)實(shí)例
prototype(多例):每次獲得時(shí)都會(huì)創(chuàng)建對(duì)象。和struts2使用時(shí)必須配置為多例缅刽。
request:web環(huán)境下對(duì)象魚(yú)request對(duì)象生命周期一樣
session:web環(huán)境下雨session聲明周期一致
生命周期屬性:配置一個(gè)方法作為聲明周期初始化方法。spring會(huì)在對(duì)象創(chuàng)建之后首先調(diào)用
配置一個(gè)而方法作為生命周期的銷毀方法笼痹,spring會(huì)在結(jié)束前調(diào)用該方法。
spring的分模塊化配置
Spring屬性注入:set方法
在user中添加car屬性
加上car對(duì)象
兩個(gè)都要重寫(xiě)toStirng方法
目錄結(jié)構(gòu)
xml中配置
測(cè)試代碼
測(cè)試結(jié)果
構(gòu)造函數(shù)注入
或者
p名稱空間注入
spel注入
復(fù)雜類型注入(了解)
用注解配置xml
在原來(lái)的lib上添加
步驟
1.為主配置文件引入新的命名空間(約束)
通添加xml約束一樣肝断。
2.開(kāi)啟注解配置文件
3.在類中使用注解井联。
1)類注解
2)值注入
3)引用類型注入
4)初始化细燎、銷毀注入
spring與junit整合
首先導(dǎo)包
spring中的AOP
思想:橫向重復(fù),縱向抽取迂苛。
對(duì)目標(biāo)對(duì)象中的方法進(jìn)行增強(qiáng).
具體還清楚
spring中的aop原理
動(dòng)態(tài)代理(優(yōu)先)
被代理的對(duì)象必須要實(shí)現(xiàn)接口,才能產(chǎn)生代理對(duì)象偎漫,如果沒(méi)有接口將不能使用動(dòng)態(tài)代理及技術(shù)
cglib
第三方代理技術(shù),cglib代理可以對(duì)任何類生成代理,代理的原理是對(duì)目標(biāo)對(duì)象進(jìn)行繼承代理,如果目標(biāo)對(duì)象唄final修飾红竭,那么該類無(wú)法被cglib代理。
aop名詞
joinpoint(連接點(diǎn)):目表對(duì)象中喘落,所有增強(qiáng)的方法茵宪。
pointcut(切入點(diǎn)):目標(biāo)對(duì)象中,已經(jīng)增強(qiáng)的方法瘦棋。
advice(通知/增強(qiáng)):增強(qiáng)的代碼稀火。
Target(目標(biāo)對(duì)象):被代理對(duì)象,代碼中的UserSevviceImpl
Weaving(織入):將通知應(yīng)用到切入的點(diǎn)的過(guò)程
Proxy:將通知織入大目標(biāo)對(duì)象后赌朋,形成代理對(duì)象凰狞。
aspect(切面):切入點(diǎn)+通知。
Spring中的aop演示
1.導(dǎo)包4+2+2+2:
2.準(zhǔn)備目標(biāo)對(duì)象
/**
* Created by Bove_shu on 2017/6/9.
*/
public class UserServiceImp implements UserService {
@Override
public void save() {
System.out.println("保存用戶");
}
@Override
public void delete() {
System.out.println("刪除用戶");
}
@Override
public void update() {
System.out.println("更新用戶");
}
@Override
public void find() {
System.out.println("查找用戶");
}
}
3.準(zhǔn)備通知
import org.aspectj.lang.ProceedingJoinPoint;
/**
* 通知類
* Created by Bove_shu on 2017/6/9.
*/
public class MyAdvice {
//前置通知
// |-目標(biāo)方法運(yùn)行之前調(diào)用
//后置通知(如果出現(xiàn)異常不會(huì)調(diào)用)
// |-在目標(biāo)方法運(yùn)行之后調(diào)用
//環(huán)繞通知
// |-在目標(biāo)方法之前之后都調(diào)用
//異常攔截通知
// |-如果出現(xiàn)異常沛慢,就會(huì)調(diào)用
//后置通知
// |-目標(biāo)方法調(diào)用之后
//前置通知
public void fore() {
System.out.println("這是前置通知");
}
//后置通知
public void afterReturning() {
System.out.println("這是后置通知(如果出現(xiàn)異常不會(huì)調(diào)用)");
}
//環(huán)繞通知
public Object around(ProceedingJoinPoint pjp) throws Throwable {
System.out.println("這是環(huán)繞前置通知");
Object proceed = pjp.proceed();//調(diào)用目標(biāo)方法
System.out.println("這是環(huán)繞后置通知(如果出現(xiàn)異常不會(huì)調(diào)用)");
return proceed;
}
//異常通知
public void afterException() {
System.out.println("出事啦杭攻!");
}
//后置通知
public void after() {
System.out.println("這是后置通知出現(xiàn)異常也會(huì)調(diào)用");
}
}
4.配置進(jìn)行織入狮腿,將通知織入目標(biāo)對(duì)象。
Spring中的Aop配置(xml配置)
<?xml version="1.0" encoding="UTF-8"?>
<ans xmlns="http://www.springframework.org/schema/ans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/ans
http://www.springframework.org/schema/ans/spring-ans.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-4.0.xsd">
<!--aop配置主要是上面兩行-->
<!--指定掃描an包下的所有類中的注解,an下所有包都要掃描-->
<!--//目標(biāo)配置對(duì)象-->
<an name="userServiceTarget" class="Service.UserServiceImp"></an>
<!--配置通知對(duì)象-->
<an name="myAdvice" class="Aspect.MyAdvice"></an>
<!--配置將通知織入目標(biāo)對(duì)象-->
<aop:config>
<!--配置切入點(diǎn)-->
<!--
void Service.UserServiceImp.save() 表示對(duì)修飾符不受限制
* Service.UserServiceImp.save() 標(biāo)識(shí)對(duì)修飾符和返回值不做限制
* Service.UserServiceImp.*() 表示對(duì)UserServiceImp類下所有的空參方法進(jìn)行增強(qiáng).
* Service.UserServiceImp.*(..) 表示對(duì)UserServiceImp類下所有的方法進(jìn)行增強(qiáng).
* Service.*ServiceImp.*(..) 表示從service包下找以ServiceImp的所有類.
* Service..*ServiceImp.*(..)表示從service包下找以ServiceImp的所有類(包括子包)
-->
<aop:pointcut id="pc" expression="execution(* Service..*ServiceImp.*(..))"/>
<aop:aspect ref="myAdvice">
<aop:fore method="fore" 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>
</ans>
Spring中的Aop配置(注解配置)
前兩步步和上面一樣
- 準(zhǔn)備通知對(duì)象
/**
* 通知類
* Created by Bove_shu on 2017/6/9.
*/
@Aspect
//標(biāo)識(shí)該類是通知類
public class MyAdvice {
//前置通知
// |-目標(biāo)方法運(yùn)行之前調(diào)用
//后置通知(如果出現(xiàn)異常不會(huì)調(diào)用)
// |-在目標(biāo)方法運(yùn)行之后調(diào)用
//環(huán)繞通知
// |-在目標(biāo)方法之前之后都調(diào)用
//異常攔截通知
// |-如果出現(xiàn)異常辣垒,就會(huì)調(diào)用
//后置通知
// |-目標(biāo)方法調(diào)用之后
@Pointcut("execution(* Service..*ServiceImp.*(..))")
public void pc(){
}
//前置通知
@fore("MyAdvice.pc())")
public void fore() {
System.out.println("這是前置通知");
}
//后置通知
@AfterReturning("MyAdvice.pc())")
public void afterReturning() {
System.out.println("這是后置通知(如果出現(xiàn)異常不會(huì)調(diào)用)");
}
//環(huán)繞通知
@Around("MyAdvice.pc())")
public Object around(ProceedingJoinPoint pjp) throws Throwable {
System.out.println("這是環(huán)繞前置通知");
Object proceed = pjp.proceed();//調(diào)用目標(biāo)方法
System.out.println("這是環(huán)繞后置通知(如果出現(xiàn)異常不會(huì)調(diào)用)");
return proceed;
}
//異常通知
@AfterThrowing("MyAdvice.pc())")
public void afterException() {
System.out.println("出事啦豆拨!");
}
//后置通知
@After("MyAdvice.pc())")
public void after() {
System.out.println("這是后置通知出現(xiàn)異常也會(huì)調(diào)用");
}
}
- 將通知織入目標(biāo)對(duì)象
<?xml version="1.0" encoding="UTF-8"?>
<ans xmlns="http://www.springframework.org/schema/ans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/ans
http://www.springframework.org/schema/ans/spring-ans.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-4.0.xsd">
<!--aop配置主要是上面兩行-->
<!--指定掃描an包下的所有類中的注解源葫,an下所有包都要掃描-->
<!--//目標(biāo)配置對(duì)象-->
<an name="userServiceTarget" class="Service.UserServiceImp"></an>
<!--配置通知對(duì)象-->
<an name="myAdvice" class="AnnotationAspect.MyAdvice"></an>
<!--開(kāi)啟注解完成織入-->
<aop:aspectj-autoproxy></aop:aspectj-autoproxy>
</ans>
Spring整合JDBC
spring中提供了一個(gè)可以操作數(shù)據(jù)庫(kù)的對(duì)象,對(duì)象封裝了JDBC技術(shù).
JDBCTemplate JDBC模板
- 準(zhǔn)備工作(4+2)
- Spring-test包+spring-aop包 jdbc驅(qū)動(dòng) 連接池c3p0 spring-jdbc spring-tx(事務(wù))
- jdbc驅(qū)動(dòng) 連接池c3p0
代碼(沒(méi)用用spring配置的代碼):
- 需要一個(gè)springJDBC模板(該類是接口)定義該類的方法
/**
* Created by Bove_shu on 2017/6/11.
*/
public interface UserDao {
//增
void save(TUser user);
// 刪
void update(TUser user);
// 改
void delete(int id);
TUser getById(int id);
// 查
int getTotalCount();
//查
List<TUser> getAll();
}
2.模板的實(shí)現(xiàn)類.具體些數(shù)據(jù)庫(kù)操作.
/**
* Created by Bove_shu on 2017/6/11.
*/
public class UserDaoImpl implements UserDao {
private JdbcTemplate jt;
public JdbcTemplate getJt() {
return jt;
}
public void setJt(JdbcTemplate jt) {
this.jt = jt;
}
@Override
public void save(TUser user) {
String sql = "insert into t_user values(null,?)";
jt.update(sql, user.getName());
}
@Override
public void update(TUser user) {
String sql = "UPDATE t_user SET NAME =? WHERE id=?";
jt.update(sql, user.getName(), user.getId());
}
@Override
public void delete(int id) {
String sql = "delete from t_user where id=?";
jt.update(sql, id);
}
@Override
public TUser getById(int id) {
String sql = "SELECT * from t_user where id=?";
//這里使用new RowMapper來(lái)進(jìn)行查找 第一個(gè)參數(shù)resultSet是查詢結(jié)果的集合,從set中抽取結(jié)果放入TUser類中
// 第二個(gè)參數(shù)是方法調(diào)用了幾次,就是幾.
jt.queryForObject(sql, (resultSet, i) -> {
TUser u = new TUser();
u.setId(resultSet.getInt("id"));
u.setName(resultSet.getString("name"));
return u;
}, id);
return null;
}
@Override
public int getTotalCount() {
String sql = "SELECT count(*) from t_user where id=?";
// 返回個(gè)數(shù)就用下面的這行代碼
Integer count = jt.queryForObject(sql, Integer.class);
return count;
}
@Override
public List<TUser> getAll() {
String sql = "SELECT * from t_user ";
//放回集合是下面的代碼,這不需要list.add的方法,你只需要做對(duì)Tuser的賦值即可.
List<TUser> list = jt.query(sql, new RowMapper<TUser>() {
@Override
public TUser mapRow(ResultSet resultSet, int i) throws SQLException {
TUser u = new TUser();
u.setId(resultSet.getInt("id"));
u.setName(resultSet.getString("name"));
return u;
}
});
return list;
}
}
- 測(cè)試代碼
@Test
public void test() throws PropertyVetoException {
//準(zhǔn)備連接池
ComboPooledDataSource dataSource = new ComboPooledDataSource();
dataSource.setDriverClass("com.mysql.jdbc,Driver");
dataSource.setJdbcUrl("jdbc:mysql:///spring-jdbc");
dataSource.setUser("root");
dataSource.setPassword("root");
//1 創(chuàng)建JDBC模板對(duì)象
JdbcTemplate jt = new JdbcTemplate();
jt.setDataSource(dataSource);
//2書(shū)寫(xiě)sql執(zhí)行
String sql="insert into t_user values(null,'vv')";
jt.update(sql);
}
使用spring配置寫(xiě)代碼
- 首先要將用到的類放到容器中,從最底層的開(kāi)始放入容器中(那個(gè)類是最底層可以參考上面的測(cè)試代碼)
<?xml version="1.0" encoding="UTF-8"?>
<ans xmlns="http://www.springframework.org/schema/ans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/ans
http://www.springframework.org/schema/ans/spring-ans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">
<!--指定掃描an包下的所有類中的注解雄坪,an下所有包都要掃描-->
<!--<context:component-scan base-package="an"></context:component-scan>-->
<!--將連接池放入spring容器-->
<an name="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
<property name="user" value="root"></property>
<property name="password" value="root"/>
<property name="driverClass" value="com.mysql.jdbc,Driver"/>
<property name="jdbcUrl" value="jdbc:mysql:///spring-jdbc"/>
</an>
<!--將JDbcTemplate放入容器-->
<an name="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
<property name="dataSource" ref="dataSource"></property>
</an>
<!--將userDao放入容器-->
<an name="userDao" class="SpringJDBC.UserDaoImpl">
<property name="jt" ref="jdbcTemplate"/>
</an>
</ans>
dao的實(shí)現(xiàn)類不變(模板的實(shí)現(xiàn)類不變)
使用sping測(cè)試
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:applicationContext.xml")
public class jdbcTest {
@Autowired
UserDao userDao;
@Test
public void test() throws PropertyVetoException {
//準(zhǔn)備連接池
ComboPooledDataSource dataSource = new ComboPooledDataSource();
dataSource.setDriverClass("com.mysql.jdbc,Driver");
dataSource.setJdbcUrl("jdbc:mysql:///spring-jdbc");
dataSource.setUser("root");
dataSource.setPassword("root");
//1 創(chuàng)建JDBC模板對(duì)象
JdbcTemplate jt = new JdbcTemplate();
jt.setDataSource(dataSource);
//2書(shū)寫(xiě)sql執(zhí)行
String sql="insert into t_user values(null,'vv')";
jt.update(sql);
}
@Test
public void save() throws PropertyVetoException {
TUser u=new TUser();
u.setName("bove");
userDao.save(u);
}
@Test
public void update() throws PropertyVetoException {
TUser u=new TUser();
u.setName("bove");
u.setId(2);
userDao.update(u);
}
}
另一種方式
繼承JDBCDaoSupport
我只寫(xiě)了一種方式其他方法我就不完善了. 之前的jt用getJdbcTemplate()代替 ,
并且容器中也不需要再配置.
xml配置
<ans xmlns="http://www.springframework.org/schema/ans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/ans
http://www.springframework.org/schema/ans/spring-ans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">
<!--指定掃描an包下的所有類中的注解,an下所有包都要掃描-->
<!--<context:component-scan base-package="an"></context:component-scan>-->
<!--將連接池放入spring容器-->
<an name="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
<property name="user" value="root"></property>
<property name="password" value="root"/>
<property name="driverClass" value="com.mysql.jdbc,Driver"/>
<property name="jdbcUrl" value="jdbc:mysql:///spring-jdbc"/>
</an>
<!--將JDbcTemplate放入容器-->
<!--<an name="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">-->
<!--<property name="dataSource" ref="dataSource"></property>-->
<!--</an>-->
<!--將userDao放入容器-->
<an name="userDao" class="SpringJDBC.UserDao2">
<!--<property name="jt" ref="jdbcTemplate"/>-->
<property name="dataSource" ref="dataSource"/>
</an>
</ans>
代碼
public class UserDao2 extends JdbcDaoSupport implements UserDao {
@Override
public void save(TUser user) {
String sql = "insert into t_user values(null,?)";
//這里
getJdbcTemplate().update(sql, user.getName());
}
@Override
public void update(TUser user) {
}
@Override
public void delete(int id) {
}
@Override
public TUser getById(int id) {
return null;
}
@Override
public int getTotalCount() {
return 0;
}
@Override
public List<TUser> getAll() {
return null;
}
}
Spring中的事務(wù)
事務(wù):要么成功要么失敗.
事務(wù)特性:acid
(原子性,一致性,持久性,隔離性)
事務(wù)的并發(fā)問(wèn)題:臟讀
,幻讀
,不可重復(fù)讀
.
事務(wù)的隔離級(jí)別:
1讀未提交
2讀已提交
4可重復(fù)度
8串行化
spring封裝了事務(wù)管理代碼
事務(wù)操作
打開(kāi)事務(wù)
提交事務(wù)
回滾事務(wù)
事務(wù)操作
事務(wù)操作對(duì)象
因?yàn)樵诓煌脚_(tái),操作事務(wù)的代碼各不相同,springs提供了一個(gè)接口.
PlatformTransactionManager接口,這個(gè)接口是spring中最重要的對(duì)象
JDBCTransactionManager
HirbateTransactionManager
spring管理事務(wù)的屬性介紹
事務(wù)的隔離級(jí)別
是否只讀
事務(wù)的傳播行為
事務(wù)傳播行為
spring管理事務(wù)的方式
編碼式(不推薦)
1.蔣核心事務(wù)管理器配置到容器中
<ans xmlns="http://www.springframework.org/schema/ans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/ans
http://www.springframework.org/schema/ans/spring-ans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">
<!--指定掃描an包下的所有類中的注解匹厘,an下所有包都要掃描-->
<!--<context:component-scan base-package="an"></context:component-scan>-->
<!--事務(wù)核心管理器,封裝了所有事務(wù)操作,依賴于連接池.-->
<an name="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"/>
</an>
<!--事務(wù)模板-->
<an name="transactionTemplate" class="org.springframework.transaction.support.TransactionTemplate">
<property name="transactionManager" ref="transactionManager"/>
</an>
<!--將連接池放入spring容器-->
<an name="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
<property name="user" value="root"></property>
<property name="password" value="root"/>
<property name="driverClass" value="com.mysql.jdbc,Driver"/>
<property name="jdbcUrl" value="jdbc:mysql:///spring-jdbc"/>
</an>
<an name="accountDao" class="tx.Dao.AccountDaoimpl">
<property name="dataSource" ref="dataSource"/>
</an>
<an name="accountService" class="tx.Service.AccountServiceImpl">
<property name="dao" ref="accountDao"/>
<property name="tt" ref="transactionTemplate"/>
</an>
</ans>
2.代碼中使用
public class AccountServiceImpl implements AccountService {
private AccountDao dao;
private TransactionTemplate tt;
public void setTt(TransactionTemplate tt) {
this.tt = tt;
}
public AccountDao getDao() {
return dao;
}
public void setDao(AccountDao dao) {
this.dao = dao;
}
@Override
public void transfer(int from, int to, double money) {
tt.execute(new TransactionCallbackWithoutResult() {
@Override
protected void doInTransactionWithoutResult(TransactionStatus transactionStatus) {
//撿錢
dao.decreaseMoney(from, money);
//加錢
dao.increaseMoney(to, money);
}
});
}
}
aopxml配置
準(zhǔn)備工作導(dǎo)包
導(dǎo)入新的約束
配置通知
xml配置
<?xml version="1.0" encoding="UTF-8"?>
<ans xmlns="http://www.springframework.org/schema/ans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/ans
http://www.springframework.org/schema/ans/spring-ans.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-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/context
http://www.springframework.org/schema/context/spring-context.xsd">
<!--指定掃描an包下的所有類中的注解嘀趟,an下所有包都要掃描-->
<!--<context:component-scan base-package="an"></context:component-scan>-->
<!--事務(wù)核心管理器,封裝了所有事務(wù)操作,依賴于連接池.-->
<an name="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"/>
</an>
<!--事務(wù)模板-->
<an name="transactionTemplate" class="org.springframework.transaction.support.TransactionTemplate">
<property name="transactionManager" ref="transactionManager"/>
</an>
<tx:advice id="txAdvice" transaction-manager="transactionManager">
<tx:attributes>
<!--name->代表方法名-->
<!--isolation->代表隔離級(jí)別-->
<!--propagation->傳播行為-->
<!--read-only->是否只讀-->
<tx:method name="transfer" isolation="DEFAULT" propagation="REQUIRED" read-only="false"/>
</tx:attributes>
</tx:advice>
<!--將通知織入目標(biāo)對(duì)象-->
<aop:config>
<aop:pointcut id="txPc" expression="execution(* tx.Service.*AccountServiceImpl.*(..))"></aop:pointcut>
<aop:advisor advice-ref="txAdvice" pointcut-ref="txPc"/>
</aop:config>
<!--將連接池放入spring容器-->
<an name="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
<property name="user" value="root"></property>
<property name="password" value="root"/>
<property name="driverClass" value="com.mysql.jdbc,Driver"/>
<property name="jdbcUrl" value="jdbc:mysql:///spring-jdbc"/>
</an>
<an name="accountDao" class="tx.Dao.AccountDaoimpl">
<property name="dataSource" ref="dataSource"/>
</an>
<an name="accountService" class="tx.Service.AccountServiceImpl">
<property name="dao" ref="accountDao"/>
<property name="tt" ref="transactionTemplate"/>
</an>
</ans>
當(dāng)需要開(kāi)啟事務(wù)的方法有很多的時(shí)候,可以用下面的方法進(jìn)行
*表示通配符
注解配置
準(zhǔn)備工作導(dǎo)包
導(dǎo)入新的約束
開(kāi)啟注解管理事務(wù)
首先需要到xml中配置
<?xml version="1.0" encoding="UTF-8"?>
<ans xmlns="http://www.springframework.org/schema/ans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/ans
http://www.springframework.org/schema/ans/spring-ans.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-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/context
http://www.springframework.org/schema/context/spring-context.xsd">
<!--指定掃描an包下的所有類中的注解,an下所有包都要掃描-->
<!--<context:component-scan base-package="an"></context:component-scan>-->
<!--事務(wù)核心管理器,封裝了所有事務(wù)操作,依賴于連接池.-->
<an name="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"/>
</an>
<!--事務(wù)模板-->
<an name="transactionTemplate" class="org.springframework.transaction.support.TransactionTemplate">
<property name="transactionManager" ref="transactionManager"/>
</an>
主要是這行
<tx:annotation-driven/>
<!--將連接池放入spring容器-->
<an name="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
<property name="user" value="root"></property>
<property name="password" value="root"/>
<property name="driverClass" value="com.mysql.jdbc,Driver"/>
<property name="jdbcUrl" value="jdbc:mysql:///spring-jdbc"/>
</an>
<an name="accountDao" class="tx.Dao.AccountDaoimpl">
<property name="dataSource" ref="dataSource"/>
</an>
<an name="accountService" class="tx.Service.AccountServiceImpl">
<property name="dao" ref="accountDao"/>
<property name="tt" ref="transactionTemplate"/>
</an>
</ans>
代碼層
//代表類中的所有方法都采用此事務(wù),當(dāng)個(gè)別不一樣的時(shí)候在方法上面加此注解就行了
@Transactional(isolation = Isolation.REPEATABLE_READ ,propagation = Propagation.REQUIRED,readOnly = false)
public class AccountServiceImpl implements AccountService {
private AccountDao dao;
private TransactionTemplate tt;
public void setTt(TransactionTemplate tt) {
this.tt = tt;
}
public AccountDao getDao() {
return dao;
}
public void setDao(AccountDao dao) {
this.dao = dao;
}
// @Override
// public void transfer(int from, int to, double money) {
// tt.execute(new TransactionCallbackWithoutResult() {
// @Override
// protected void doInTransactionWithoutResult(TransactionStatus transactionStatus) {
// //撿錢
// dao.decreaseMoney(from, money);
// //加錢
// dao.increaseMoney(to, money);
// }
// });
//
// }
@Override
//個(gè)別不一樣的時(shí)候在方法上面加此注解就行了
@Transactional(isolation = Isolation.REPEATABLE_READ ,propagation = Propagation.REQUIRED,readOnly = true)
public void transfer(int from, int to, double money) {
//撿錢
dao.decreaseMoney(from, money);
int a=1/0;
//加錢
dao.increaseMoney(to, money);
}
}
當(dāng)前的事務(wù)管理用到的類
目錄結(jié)構(gòu)
AccountDao類
public interface AccountDao {
//價(jià)錢
void increaseMoney(int id,Double money);
//撿錢
void decreaseMoney(int id,Double money);
}
AccountDaoimpl類
public class AccountDaoimpl extends JdbcDaoSupport implements AccountDao {
@Override
public void increaseMoney(int id, Double money) {
getJdbcTemplate().update("UPDATE t_account SET money=money+? WHERE id=?",money,id);
}
@Override
public void decreaseMoney(int id, Double money) {
getJdbcTemplate().update("UPDATE t_account SET money=money-? WHERE id=?",money,id);
}
}
AccountService類
public interface AccountService {
//轉(zhuǎn)賬方法
void transfer(int from,int to,double money);
}
AccountServiceImpl類
//代表類中的所有方法都采用此事務(wù),當(dāng)個(gè)別不一樣的時(shí)候在方法上面加此注解就行了
@Transactional(isolation = Isolation.REPEATABLE_READ ,propagation = Propagation.REQUIRED,readOnly = false)
public class AccountServiceImpl implements AccountService {
private AccountDao dao;
private TransactionTemplate tt;
public void setTt(TransactionTemplate tt) {
this.tt = tt;
}
public AccountDao getDao() {
return dao;
}
public void setDao(AccountDao dao) {
this.dao = dao;
}
// @Override
// public void transfer(int from, int to, double money) {
// tt.execute(new TransactionCallbackWithoutResult() {
// @Override
// protected void doInTransactionWithoutResult(TransactionStatus transactionStatus) {
// //撿錢
// dao.decreaseMoney(from, money);
// //加錢
// dao.increaseMoney(to, money);
// }
// });
//
// }
@Override
//個(gè)別不一樣的時(shí)候在方法上面加此注解就行了
@Transactional(isolation = Isolation.REPEATABLE_READ ,propagation = Propagation.REQUIRED,readOnly = true)
public void transfer(int from, int to, double money) {
//撿錢
dao.decreaseMoney(from, money);
int a=1/0;
//加錢
dao.increaseMoney(to, money);
}
}
測(cè)試類
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:applicationContext.xml")
public class Test {
@Autowired
private AccountService as;
@org.junit.Test
public void test(){
as.transfer(1,2,200);
}
}