Spring入門(mén)

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)

image.png

導(dǎo)包之后并沒(méi)有完成需要 創(chuàng)建xml文件
一般命名為applicationContext.xml

image.png

然后需要添加xml約束

添加xml約束.png

接下來(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中配置

xml添加約束

IDEA會(huì)自己生成Spring得約束XML文件


代碼測(cè)試

代碼測(cè)試.png

測(cè)試結(jié)果

測(cè)試結(jié)果.png

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元素

Bean元素.png

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屬性

在user中添加car屬性.png

加上car對(duì)象

加上car對(duì)象.png

兩個(gè)都要重寫(xiě)toStirng方法

目錄結(jié)構(gòu)
xml中配置

xml中配置.png

測(cè)試代碼

測(cè)試代碼.png

測(cè)試結(jié)果

測(cè)試結(jié)果.png

構(gòu)造函數(shù)注入

構(gòu)造函數(shù)注入.png
構(gòu)造函數(shù)注入.png

或者

image.png

p名稱空間注入

p名稱空間注入.png

spel注入

spel注入.png

復(fù)雜類型注入(了解)

用注解配置xml
在原來(lái)的lib上添加

在原來(lái)的lib上添加.png

步驟
1.為主配置文件引入新的命名空間(約束)
通添加xml約束一樣。
2.開(kāi)啟注解配置文件

image.png.png

3.在類中使用注解。
1)類注解

類注解.png

2)值注入

值注入.png

3)引用類型注入

引用類型注入.png

4)初始化、銷毀注入

初始化、銷毀注入.png

spring與junit整合
首先導(dǎo)包

導(dǎo)包.png
測(cè)試.png

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:

導(dǎo)包.png

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配置(注解配置)

前兩步步和上面一樣

  1. 準(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)用");
    }

}
  1. 將通知織入目標(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模板

  1. 準(zhǔn)備工作(4+2)
  2. Spring-test包+spring-aop包 jdbc驅(qū)動(dòng) 連接池c3p0 spring-jdbc spring-tx(事務(wù))
  3. jdbc驅(qū)動(dòng) 連接池c3p0
準(zhǔn)備工作.png

代碼(沒(méi)用用spring配置的代碼):

  1. 需要一個(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;
    }
}
  1. 測(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ě)代碼

  1. 首先要將用到的類放到容器中,從最底層的開(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>
  1. dao的實(shí)現(xiàn)類不變(模板的實(shí)現(xiàn)類不變)

  2. 使用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ù)傳播行為

事務(wù)傳播行為.png

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) {
                //撿錢(qián)
                dao.decreaseMoney(from, money);
                //加錢(qián)
                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)行

image.png

*表示通配符

注解配置
準(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) {
//                //撿錢(qián)
//                dao.decreaseMoney(from, money);
//                //加錢(qián)
//                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) {

                //撿錢(qián)
                dao.decreaseMoney(from, money);
                int a=1/0;
                //加錢(qián)
                dao.increaseMoney(to, money);
    }
}

當(dāng)前的事務(wù)管理用到的類

目錄結(jié)構(gòu)

目錄結(jié)構(gòu).png

AccountDao類

public interface AccountDao {
    //價(jià)錢(qián)
    void increaseMoney(int id,Double money);
    //撿錢(qián)
    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) {
//                //撿錢(qián)
//                dao.decreaseMoney(from, money);
//                //加錢(qián)
//                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) {

                //撿錢(qián)
                dao.decreaseMoney(from, money);
                int a=1/0;
                //加錢(qián)
                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);
    }
}

end

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • Spring Cloud為開(kāi)發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見(jiàn)模式的工具(例如配置管理,服務(wù)發(fā)現(xiàn),斷路器,智...
    卡卡羅2017閱讀 136,568評(píng)論 19 139
  • Spring Boot 參考指南 介紹 轉(zhuǎn)載自:https://www.gitbook.com/book/qbgb...
    毛宇鵬閱讀 47,273評(píng)論 6 342
  • 什么是Spring Spring是一個(gè)開(kāi)源的Java EE開(kāi)發(fā)框架。Spring框架的核心功能可以應(yīng)用在任何Jav...
    jemmm閱讀 16,772評(píng)論 1 133
  • 我看著書(shū)桌上平睡的鋼筆,或許正在做一個(gè)關(guān)于文字的夢(mèng)。這種夢(mèng)境或許真實(shí)或許虛假,但終歸是一支鋼筆的夢(mèng)。在夢(mèng)里面它或許...
    刀爺閱讀 500評(píng)論 4 3

友情鏈接更多精彩內(nèi)容