基于XML和注解的声明式事物控制

基于xml

  1. 配置pom.xml文件
  2. 构建业务代码
  3. 配置ApplicationContext.xml文件

1 pom.xml文件中需要添加的依赖

  <!--spring-context.jar
这个jar 文件为Spring 核心提供了大量扩展。可以找到使用Spring ApplicationContext特性时所需的全部类,JDNI 所需的全部类,instrumentation组件以及校验Validation 方面的相关类。
外部依赖spring-beans, (spring-aop)。-->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>5.3.3</version>
        </dependency>
<!--C3P0的作用是获取数据库连接,对象为一个类型为DataSource的数据库连接池-->
        <dependency>
            <groupId>c3p0</groupId>
            <artifactId>c3p0</artifactId>
            <version>0.9.1.2</version>
        </dependency>
 <!--JAVA通过jdbc访问mySQL数据库时需要该包支持-->
        <dependency>
          <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>8.0.22</version>
        </dependency>
 <!--提供JdbcTemplate类-->
         <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-jdbc</artifactId>
            <version>5.3.3</version>
        </dependency>
        <!--进行事物管理 提供相当于aop中Aspect的增强通知-->
      <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-tx</artifactId>
            <version>5.3.3</version>
        </dependency>
        <!--是实现IOC-->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-beans</artifactId>
            <version>5.3.3</version>
        </dependency>

2 构建业务代码 :通过经典案例 转账来测试

2.1 dao层(持久层):DAO层主要是做数据持久层的工作,负责与数据库进行联络的一些任务都封装在此。
package com.lxh.dao.Impl;

import com.lxh.dao.AccountWage;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;

/**
 * @author lxh
 * @date 2021/1/17-22:12
 */
public class AccountWageImpl implements AccountWage {

  //  @Autowired  (换做在 xml 文件中 set配置)
    private JdbcTemplate jdbcTemplate;

    public void setJdbcTemplate(JdbcTemplate jdbcTemplate) {
        this.jdbcTemplate = jdbcTemplate;
    }

    @Override
    public void out(String outMan, int price) {
           jdbcTemplate.update("update wage set price = price - ? where name = ?",price,outMan);
    }
    @Override
    public void in(String inMan, int price) {
          jdbcTemplate.update("update wage set price = price + ? where name = ?",price,inMan);
    }
}

2.2  service层(服务层):Service层主要负责业务模块的逻辑应用设计。
package com.lxh.service.Impl;

import com.lxh.dao.AccountWage;
import com.lxh.service.AccountService;

/**
 * @author lxh
 * @date 2021/1/17-22:25
 */
public class AccountServiceImpl implements AccountService {

    private AccountWage accountWage;

    public void setAccountWage(AccountWage accountWage) {
        this.accountWage = accountWage;
    }

    @Override
    public void transfer(String outMan, String inMan, int price) {
        accountWage.out(outMan,price);
        int i = 1/0;
        accountWage.in(inMan,price);
    }
}

2.3 	 controller层(控制层):Controller层负责具体的业务模块流程的控制,在此层里面要调用Serice层的接口来控制业务流程。
package com.lxh.controller;

import com.lxh.dao.Impl.AccountWageImpl;
import com.lxh.service.AccountService;
import com.lxh.service.Impl.AccountServiceImpl;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

/**
 * @author lxh
 * @date 2021/1/17-22:28
 */
public class AccountController {
    public static void main(String[] args) {
        ApplicationContext app = new ClassPathXmlApplicationContext("ApplicationContext.xml");
        AccountService accountService = app.getBean(AccountService.class);
        accountService.transfer("Jack","Lengwa",500);
    }
}

3 配置ApplicationContext.xml文件

在我看来对于事物的管理思想就是AOP,而其中对于切点加强的通知是由Spring-tx来进行提供。在将这些通知织入到我们到加强的方法之前,还需要得配置平台事物管理器DataSourceTransactionManager

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:tx="http://www.springframework.org/schema/tx"
       xmlns:aop="http://www.springframework.org/schema/aop"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
       http://www.springframework.org/schema/beans/spring-beans.xsd
       http://www.springframework.org/schema/context
       https://www.springframework.org/schema/context/spring-context.xsd
       http://www.springframework.org/schema/tx
       http://www.springframework.org/schema/tx/spring-tx.xsd
       http://www.springframework.org/schema/aop
       http://www.springframework.org/schema/aop/spring-aop.xsd ">

   <!--加载properties文件-->
      <context:property-placeholder location="classpath:jdbc.properties"/>
    
    <!--配置DataSource-->
      <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource" >
          <property name="jdbcUrl" value="${jdbc.url}"></property>
          <property name="driverClass" value="${jdbc.driver}"></property>
          <property name="user" value="${jdbc.username}"></property>
          <property name="password" value="${jdbc.password}"></property>
      </bean>

    <!--配置模板-->
    <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
        <property name="dataSource" ref="dataSource"></property>
    </bean>

    <bean id="accountWage" class="com.lxh.dao.Impl.AccountWageImpl">
        <property name="jdbcTemplate" ref="jdbcTemplate"/>
    </bean>

  <!--配置声明式事务控制-->

    <!--目标对象 内部方法就是要增强的对象-->
    <bean id="AccountService" class="com.lxh.service.Impl.AccountServiceImpl">
        <property name="accountWage" ref="accountWage"></property>
    </bean>

    <!--配置平台事务管理器-->
    <bean id="transaction" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="dataSource"></property>
    </bean>

    <!--通知事务增强-->
    <tx:advice id="txAdvice" transaction-manager="transaction">
        <tx:attributes>
            <tx:method name="*"/>
        </tx:attributes>
    </tx:advice>

    <!--事务的织入-->
    <aop:config>
        <aop:advisor advice-ref="txAdvice" pointcut="execution(* com.lxh.service.Impl.*.*(..))"></aop:advisor>
    </aop:config>
</beans>

基于注解

  1. 同xml配置pom.xml(这里就不在展示)
  2. 构建业务代码(这里因为使用了注解因此会展示)
  3. 编写Configuration类(同xml中的ApplicationContext.xml文件作用相同)

1 pom.xml跳过
2 业务代码

2.1 dao 这里通过@Component将AccountWageImpl 实例化放入到Spring容器中

package com.lxh.dao.Impl;

import com.lxh.dao.AccountWage;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Repository;

/**
 * @author lxh
 * @date 2021/1/17-22:12
 */
@Component("accountWage")
public class AccountWageImpl implements AccountWage {

    @Autowired
    private JdbcTemplate jdbcTemplate;

    @Override
    public void out(String outMan, int price) {
           jdbcTemplate.update("update wage set price = price - ? where name = ?",price,outMan);
    }
    @Override
    public void in(String inMan, int price) {
          jdbcTemplate.update("update wage set price = price + ? where name = ?",price,inMan);
    }
}

2.2 service 通过@Service将AccountServiceImpl 实例化到Spring容器中,同时@Autowired将,2.1 放到容器中的AccountWage 类型的 类注入到accountWage.
这也是Spring解耦合的一个体现。
package com.lxh.service.Impl;

import com.lxh.dao.AccountWage;
import com.lxh.service.AccountService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Transactional;

/**
 * @author lxh
 * @date 2021/1/17-22:25
 */
@Service("AccountService")
public class AccountServiceImpl implements AccountService {

    @Autowired
    private AccountWage accountWage;

    @Override @Transactional(isolation = Isolation.DEFAULT)
    public void transfer(String outMan, String inMan, int price) {
        accountWage.out(outMan,price);
        accountWage.in(inMan,price);
    }
}

2.3 controller 
public class AccountController {
    public static void main(String[] args) {
        ApplicationContext app = new AnnotationConfigApplicationContext(SpringConfigure.class);
        AccountService accountService = app.getBean(AccountService.class);
        accountService.transfer("Jack","Lengwa",500);
    }
}

3 Configuration类的配置
说明:这里对于jdbcTemplate和事物管理器都要用DataSource,
因此先对Datasource先进行配置。
@EnableTransactionManagement 等价于 <tx:annotation-driven transaction-manager="" />

package com.lxh.ApplicationContext;

import com.mchange.v2.c3p0.ComboPooledDataSource;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.*;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.transaction.annotation.EnableTransactionManagement;

import javax.sql.DataSource;
import java.beans.PropertyVetoException;

/**
 * @author lxh
 * @date 2021/1/17-23:26
 */
@Configuration
@ComponentScan("com.lxh")
//@Import({DataSourceConfigure.class,TransactionManagerConfigure.class,JdbcTemplateConfiguration.class})
@PropertySource("classpath:jdbc.properties")
@EnableTransactionManagement
public class SpringConfigure {
    @Value("${jdbc.driver}")
    private String driver;
    @Value("${jdbc.url}")
    private String url;
    @Value("${jdbc.username}")
    private String name;
    @Value("${jdbc.password}")
    private String password;

    @Bean(name = "dataSource")
    public DataSource getdataSource() throws PropertyVetoException {
        ComboPooledDataSource dataSource = new ComboPooledDataSource();
        dataSource.setDriverClass(driver);
        dataSource.setJdbcUrl(url);
        dataSource.setUser(name);
        dataSource.setPassword(password);
        return dataSource;
    }
    @Bean(name = "TransactionManager")
    public DataSourceTransactionManager transactionManager() throws PropertyVetoException {
        return new DataSourceTransactionManager(getdataSource());
    }

    @Bean(name = "jdbcTemplate")
    public JdbcTemplate getJdbcTemplate() throws PropertyVetoException {
        JdbcTemplate jdbcTemplate = new JdbcTemplate();
        jdbcTemplate.setDataSource(getdataSource());
        return jdbcTemplate;
    }
    
}

补充:
关于jdbc.properties文件
位置:在resources目录下
jdbc.properties文件位置
内容:

jdbc.driver = com.mysql.cj.jdbc.Driver
jdbc.url = jdbc:mysql://localhost:3306/XXXXX
jdbc.username = root
jdbc.password = XXXXXX

已标记关键词 清除标记
©️2020 CSDN 皮肤主题: 深蓝海洋 设计师:CSDN官方博客 返回首页