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) {
                //撿錢
                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)行

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) {
//                //撿錢
//                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)

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

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);
    }
}

end

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末愈诚,一起剝皮案震驚了整個(gè)濱河市去件,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌扰路,老刑警劉巖尤溜,帶你破解...
    沈念sama閱讀 222,590評(píng)論 6 517
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異汗唱,居然都是意外死亡宫莱,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 95,157評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門(mén)哩罪,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)授霸,“玉大人巡验,你說(shuō)我怎么就攤上這事〉舛” “怎么了显设?”我有些...
    開(kāi)封第一講書(shū)人閱讀 169,301評(píng)論 0 362
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)辛辨。 經(jīng)常有香客問(wèn)我捕捂,道長(zhǎng),這世上最難降的妖魔是什么斗搞? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 60,078評(píng)論 1 300
  • 正文 為了忘掉前任指攒,我火速辦了婚禮,結(jié)果婚禮上僻焚,老公的妹妹穿的比我還像新娘允悦。我一直安慰自己,他們只是感情好虑啤,可當(dāng)我...
    茶點(diǎn)故事閱讀 69,082評(píng)論 6 398
  • 文/花漫 我一把揭開(kāi)白布隙弛。 她就那樣靜靜地躺著,像睡著了一般狞山。 火紅的嫁衣襯著肌膚如雪全闷。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 52,682評(píng)論 1 312
  • 那天铣墨,我揣著相機(jī)與錄音室埋,去河邊找鬼办绝。 笑死伊约,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的孕蝉。 我是一名探鬼主播屡律,決...
    沈念sama閱讀 41,155評(píng)論 3 422
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼降淮!你這毒婦竟也來(lái)了超埋?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 40,098評(píng)論 0 277
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤佳鳖,失蹤者是張志新(化名)和其女友劉穎霍殴,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體系吩,經(jīng)...
    沈念sama閱讀 46,638評(píng)論 1 319
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡来庭,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,701評(píng)論 3 342
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了穿挨。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片月弛。...
    茶點(diǎn)故事閱讀 40,852評(píng)論 1 353
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡肴盏,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出帽衙,到底是詐尸還是另有隱情菜皂,我是刑警寧澤,帶...
    沈念sama閱讀 36,520評(píng)論 5 351
  • 正文 年R本政府宣布厉萝,位于F島的核電站恍飘,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏冀泻。R本人自食惡果不足惜常侣,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 42,181評(píng)論 3 335
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望弹渔。 院中可真熱鬧胳施,春花似錦、人聲如沸肢专。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 32,674評(píng)論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)博杖。三九已至椿胯,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間剃根,已是汗流浹背哩盲。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,788評(píng)論 1 274
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留狈醉,地道東北人廉油。 一個(gè)月前我還...
    沈念sama閱讀 49,279評(píng)論 3 379
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像苗傅,于是被迫代替她去往敵國(guó)和親抒线。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,851評(píng)論 2 361

推薦閱讀更多精彩內(nèi)容

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