Spring笔记

1.基于XML的配置

1.1 pom文件

 <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>5.0.2.RELEASE</version>
        </dependency>

1.2 创建配置文件并导入头

<?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:aop="http://www.springframework.org/schema/aop"
       xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">

1.3在配置文件中配置类

 <!---配置service -->
 <bean id="accountService" class="com.itheima.service.impl.AccountServiceImpl"> </bean>
 <!-- 配置dao -->
 <bean id="accountDao" class="com.itheima.dao.impl.AccountDaoImpl"></bean>

1.4测试SpringBoot环境是否搭配完成

public static void main(String[] args) { 
    //1.使用ApplicationContext接口,就是在获取spring容器 
   ApplicationContext ac = new ClassPathXmlApplicationContext("bean.xml");
//2.根据bean的id获取对象 IAccountService aService = (IAccountService) ac.getBean("accountService"); System.out.println(aService);    IAccountDao aDao = (IAccountDao) ac.getBean("accountDao"); System.out.println(aDao); }

1.5一些细节

  1 BeanFactory 和ApplicationContext 的区别

      

  2 ApplicationContext 接口的实现类

     

1.6 bean标签

  

1.7 SpringIOC的注入

public class AccountServiceImpl implements IAccountService {
  private String name;
  private Integer age;
  private Date birthday;
  
public AccountServiceImpl(String name, Integer age, Date birthday) {     this.name = name;     this.age = age;     this.birthday = birthday;   }   @Override   public void saveAccount() {     System.out.println(name+","+age+","+birthday);   } }
<!-- 使用构造函数的方式,给 service 中的属性传值
要求:
  类中需要提供一个对应参数列表的构造函数。
涉及的标签:
  constructor-arg
属性:
  index:指定参数在构造函数参数列表的索引位置
  type:指定参数在构造函数中的数据类型
  name:指定参数在构造函数中的名称 用这个找给谁赋值
  =======上面三个都是找给谁赋值,下面两个指的是赋什么值的==============
  value:它能赋的值是基本数据类型和 String 类型
  ref:它能赋的值是其他 bean 类型,也就是说,必须得是在配置文件中配置过的 bean
-->
<bean id="accountService" class="com.itheima.service.impl.AccountServiceImpl">
  <constructor-arg name="name" value="张三"></constructor-arg>
  <constructor-arg name="age" value="18"></constructor-arg>
  <constructor-arg name="birthday" ref="now"></constructor-arg>
</bean>
<bean id="now" class="java.util.Date"></bean>

1.8.set方式注入

public class AccountServiceImpl implements IAccountService {
  private String name;
  private Integer age;
  private Date birthday;
  
public void setName(String name) { this.name = name;   }   public void setAge(Integer age) {   this.age = age;   }   public void setBirthday(Date birthday) {   this.birthday = birthday;   } @Override public void saveAccount() {   System.out.println(name+","+age+","+birthday); } }
<!--通过配置文件给 bean 中的属性传值:使用 set 方法的方式
涉及的标签:
  property
属性:
  name:找的是类中 set 方法后面的部分
  ref:给属性赋值是其他 bean 类型的
  value:给属性赋值是基本数据类型和 string 类型的
实际开发中,此种方式用的较多。
-->
<bean id="accountService" class="com.itheima.service.impl.AccountServiceImpl">
  <property name="name" value="test"></property>
  <property name="age" value="21"></property>
  <property name="birthday" ref="now"></property>
</bean>
<bean id="now" class="java.util.Date"></bean>

1.9注入集合属性

public class AccountServiceImpl implements IAccountService {
  private String[] myStrs;
  private List<String> myList;
  private Set<String> mySet;
  private Map<String,String> myMap;
  private Properties myProps;
  
public void setMyStrs(String[] myStrs) {     this.myStrs = myStrs;   }   public void setMyList(List<String> myList) {     this.myList = myList;   }   public void setMySet(Set<String> mySet) {     this.mySet = mySet;   }   public void setMyMap(Map<String, String> myMap) {     this.myMap = myMap;   }   public void setMyProps(Properties myProps) {     this.myProps = myProps;   }   @Override   public void saveAccount() {     System.out.println(Arrays.toString(myStrs));     System.out.println(myList);     System.out.println(mySet);     System.out.println(myMap);     System.out.println(myProps);   } }
<!-- 注入集合数据
  List 结构的:
    array,list,set
  Map 结构的
    map,entry,props,prop
-->
<bean id="accountService" class="com.itheima.service.impl.AccountServiceImpl">
  <!-- 在注入集合数据时,只要结构相同,标签可以互换 -->
  <!-- 给数组注入数据 -->
  <property name="myStrs">
    <set>
      <value>AAA</value>
      <value>BBB</value>
      <value>CCC</value>
    </set>
  </property>
  <!-- 注入 list 集合数据 -->
  <property name="myList">
    <array>
      <value>AAA</value>
      <value>BBB</value>
      <value>CCC</value>
    </array>
  </property>
  <!-- 注入 set 集合数据 -->
  <property name="mySet">
    <list>
      <value>AAA</value>
      <value>BBB</value>
      <value>CCC</value>
    </list>
  </property>
  <!-- 注入 Map 数据 -->
  <property name="myMap">
    <props>
      <prop key="testA">aaa</prop>
      <prop key="testB">bbb</prop>
    </props>
    </property>
  <!-- 注入 properties 数据 -->
  <property name="myProps">
    <map>
      <entry key="testA" value="aaa"></entry>
      <entry key="testB">
        <value>bbb</value>
      </entry>
    </map>
  </property>
</bean>

2. Spring AOP笔记

 

2.1 使用JDK官方的Proxy代理增强解决数据库事务问题 

public class BeanFactory {

    final TransactionManager txManager = new TransactionManager();

    public static IAccountService getAccountService() throws IllegalAccessException, InstantiationException {
        //1.定义被代理对象
        final IAccountService accountService = new AccountServiceImpl();
        //2.创建代理对象
        IAccountService proxyAccountService = (IAccountService) Proxy.newProxyInstance(accountService.getClass().getClassLoader(),
                accountService.getClass().getInterfaces(),new InvocationHandler() {

                    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                        Object rtValue = null;
                        try {
                            //开启事务
                            TransactionManager.beginTransaction();
                            //执行业务层方法
                            rtValue = method.invoke(accountService, args);
                            //提交事务
                            TransactionManager.commit();
                        }catch(Exception e) {
                            //回滚事务 TransactionManager.rollback();
                            e.printStackTrace();
                        }finally {
                            //释放资源
                            TransactionManager.release();
                        }
                        return rtValue;
                    }
        });
        return proxyAccountService;
    }
}

2.2 基于XML的AOP开发(DUUtils开发)

 1 事前准备:   

   (1)创建连接数据库工具类

/**
 * 连接的工具类,它用于从数据源中获取一个连接,并且实现和线程的绑定
 */
public class ConnectionUtils {

    private ThreadLocal<Connection> tl = new ThreadLocal<Connection>();

    private DataSource dataSource;
    public void setDataSource(DataSource dataSource) {
        this.dataSource = dataSource;
    }
    /**
     * 获取当前线程上的连接
     * @return
     */
    public Connection getThreadConnection() {
        try{
            //1.先从ThreadLocal上获取
            Connection conn = tl.get();
            //2.判断当前线程上是否有连接
            if (conn == null) {
                //3.从数据源中获取一个连接,并且存入ThreadLocal中
                conn = dataSource.getConnection();
                tl.set(conn);
            }
            //4.返回当前线程上的连接
            return conn;
        }catch (Exception e){
            throw new RuntimeException(e);
        }
    }
    /**
     * 把连接和线程解绑
     */
    public void removeConnection(){
        tl.remove();
    }
}

   (2)JDBCProperties文件

jdbc.driverClass=com.mysql.cj.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/account?useUnicode=true&characterEncoding=utf8
jdbc.username=root
jdbc.password=

 2.实体类

create table account(
    id int primary key auto_increment,
    name varchar(40),
    money float
)character set utf8 collate utf8_general_ci;

insert into account(name,money) values('aaa',1000);
insert into account(name,money) values('bbb',1000); insert into account(name,money) values('ccc',1000);
public class Account implements Serializable { private Integer id; private String name; private Float money; public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public Float getMoney() { return money; } public void setMoney(Float money) { this.money = money; } @Override public String toString() { return "Account{" + "id=" + id + ", name='" + name + '\'' + ", money=" + money + '}'; } }

  3. dao层

public interface IAccountDao {

    /**
     * 查询所有
     * @return
     */
    List<Account> findAllAccount();

    /**
     * 查询一个
     * @return
     */
    Account findAccountById(Integer accountId);

    /**
     * 保存
     * @param account
     */
    void saveAccount(Account account);

    /**
     * 更新
     * @param account
     */
    void updateAccount(Account account);

    /**
     * 删除
     * @param acccountId
     */
    void deleteAccount(Integer acccountId);

    /**
     * 根据名称查询账户
     * @param accountName
     * @return  如果有唯一的一个结果就返回,如果没有结果就返回null
     *          如果结果集超过一个就抛异常
     */
    Account findAccountByName(String accountName);
}
/**
 * 账户的持久层实现类
 */
public class AccountDaoImpl implements IAccountDao {

    private QueryRunner runner;
    private ConnectionUtils connectionUtils;

    public void setRunner(QueryRunner runner) {
        this.runner = runner;
    }

    public void setConnectionUtils(ConnectionUtils connectionUtils) {
        this.connectionUtils = connectionUtils;
    }

    public List<Account> findAllAccount() {

        try {
            return runner.query(connectionUtils.getThreadConnection(),"select * from account",
          new BeanListHandler<Account>(Account.class)); } catch (Exception e) { throw new RuntimeException(e); } } public Account findAccountById(Integer accountId) { try { return runner.query(connectionUtils.getThreadConnection(), "select * from account where id = ?",
          new BeanHandler<Account>(Account.class), accountId); } catch (Exception e) { throw new RuntimeException(e); } } public void saveAccount(Account account) { try { runner.update(connectionUtils.getThreadConnection(), "insert into account(name,money) values(?,?)",
          account.getName(),account.getMoney()); }
catch (Exception e) { throw new RuntimeException(e); } } public void updateAccount(Account account) { try { runner.update(connectionUtils.getThreadConnection(), "update account set name = ?,money = ? where id = ?",
            account.getName(),account.getMoney(),account.getId()); }
catch (Exception e) { throw new RuntimeException(e); } } public void deleteAccount(Integer acccountId) { try { runner.update(connectionUtils.getThreadConnection(), "delete from account where id = ?",acccountId); } catch (Exception e) { throw new RuntimeException(e); } } public Account findAccountByName(String accountName) { try{ List<Account> accounts = runner.query(connectionUtils.getThreadConnection(),"select * from account where name = ? ",
          new BeanListHandler<Account>(Account.class),accountName); if(accounts == null || accounts.size() == 0){ return null; } if(accounts.size() > 1){ throw new RuntimeException("结果集不唯一,数据有问题"); } return accounts.get(0); }catch (Exception e) { throw new RuntimeException(e); } } }

  4.Service层

/**
 * 账户的业务层接口
 */
public interface IAccountService {

    /**
     * 查询所有
     * @return
     */
    List<Account> findAllAccount();

    /**
     * 查询一个
     * @return
     */
    Account findAccountById(Integer accountId);

    /**
     * 保存
     * @param account
     */
    void saveAccount(Account account);

    /**
     * 更新
     * @param account
     */
    void updateAccount(Account account);

    /**
     * 删除
     * @param acccountId
     */
    void deleteAccount(Integer acccountId);

    /**
     * 转账
     * @param sourceName        转出账户名称
     * @param targetName        转入账户名称
     * @param money             转账金额
     */
    void transfer(String sourceName, String targetName, Float money);

    //void test();//它只是连接点,但不是切入点,因为没有被增强
}

/**
 * 账户的业务层实现类
 * 事务控制应该都是在业务层
 */
public class AccountServiceImpl2 implements IAccountService{

    private IAccountDao accountDao;

    public void setAccountDao(IAccountDao accountDao) {
        this.accountDao = accountDao;
    }

    public List<Account> findAllAccount() {
            List<Account> accounts = accountDao.findAllAccount();
            return accounts;
    }

    public Account findAccountById(Integer accountId) {
        Account account = accountDao.findAccountById(accountId);

        return account;
    }

    public void saveAccount(Account account) {
        accountDao.saveAccount(account);
    }

    public void updateAccount(Account account) {
        accountDao.updateAccount(account);
    }

    public void deleteAccount(Integer acccountId) {
        accountDao.deleteAccount(acccountId);
    }
    public void transfer(String sourceName, String targetName, Float money) {

            //2.1根据名称查询转出账户
            Account source = accountDao.findAccountByName(sourceName);
            //2.2根据名称查询转入账户
            Account target = accountDao.findAccountByName(targetName);
            //2.3转出账户减钱
            source.setMoney(source.getMoney()-money);
            //2.4转入账户加钱
            target.setMoney(target.getMoney()+money);
            //2.5更新转出账户
            accountDao.updateAccount(source);

            int i=1/0;

            //2.6更新转入账户
            accountDao.updateAccount(target);
    }
}

  5.配置事务管理器

public class TransactionManager {
    
    private ConnectionUtils connectionUtils;

    public void setConnectionUtils(ConnectionUtils connectionUtils) {
        this.connectionUtils = connectionUtils;
    }

    /**
     * 开启事务
     */

    public void beginTransaction(){
        try {
            connectionUtils.getThreadConnection().setAutoCommit(false);
        }catch (Exception e){
            e.printStackTrace();
        }
    }

    /**
     * 提交事务
     */
    public  void commit(){
        try {
            connectionUtils.getThreadConnection().commit();
        }catch (Exception e){
            e.printStackTrace();
        }
    }

    /**
     * 回滚事务
     */
    public  void rollback(){
        try {
            connectionUtils.getThreadConnection().rollback();
        }catch (Exception e){
            e.printStackTrace();
        }
    }

    /**
     * 释放连接
     */
    public  void release(){
        try {
            connectionUtils.getThreadConnection().close();//还回连接池中
            connectionUtils.removeConnection();
        }catch (Exception e){
            e.printStackTrace();
        }
    }
    public Object transactionAround(ProceedingJoinPoint pip){
        Object reValue = null;
        try {
            Object[] args = pip.getArgs();
            beginTransaction();
            //执行方法
            reValue = pip.proceed(args);
            System.out.println(reValue+"----------------------------------");
            commit();
        }catch (Throwable e){
            rollback();
            e.printStackTrace();
        }finally {
            release();
        }
        return reValue;
    }
}

  5.xml配置文件

<?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:aop="http://www.springframework.org/schema/aop"
       xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans 
       http://www.springframework.org/schema/beans/spring-beans.xsd 
       http://www.springframework.org/schema/aop 
       http://www.springframework.org/schema/aop/spring-aop.xsd 
       http://www.springframework.org/schema/context 
       http://www.springframework.org/schema/context/spring-context.xsd">

    <!-- 配置Service -->
    <bean id="accountService" class="com.itheima.service.impl.AccountServiceImpl">
        <!-- 注入dao -->
        <property name="accountDao" ref="accountDao"></property>
        <property name="txManager" ref="txManager"></property>
    </bean>

    <bean id="accountService2" class="com.itheima.service.impl.AccountServiceImpl2">
        <property name="accountDao" ref="accountDao"></property>
    </bean>

    <!--配置Dao对象-->
    <bean id="accountDao" class="com.itheima.dao.impl.AccountDaoImpl">
        <property name="runner" ref="runner"></property>
        <property name="connectionUtils" ref="connectionUtils"></property>
    </bean>

    <!--配置QueryRunner-->
    <bean id="runner" class="org.apache.commons.dbutils.QueryRunner" scope="prototype"/>

    <context:property-placeholder location="classpath:jdbc.properties"/>

    <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
        <!--连接数据库的必备信息-->
        <property name="driverClass" value="${jdbc.driverClass}"></property>
        <property name="jdbcUrl" value="${jdbc.url}"></property>
        <property name="user" value="${jdbc.username}"></property>
        <property name="password" value="${jdbc.password}"></property>
    </bean>

    <!-- 配置Connection的工具类 ConnectionUtils -->
    <bean id="connectionUtils" class="com.itheima.utils.ConnectionUtils">
        <property name="dataSource" ref="dataSource"></property>
    </bean>

    <!-- 配置事务管理器-->
    <bean id="txManager" class="com.itheima.utils.TransactionManager">
        <!-- 注入ConnectionUtils -->
        <property name="connectionUtils" ref="connectionUtils"/>
    </bean>

    <!--作用:用于声明开始aop的配置-->
    <aop:config>
        <aop:aspect id="txAdvice" ref="txManager">
            <aop:pointcut id="pt1" expression="execution(* com.itheima.service.impl.*.*(..))"/>

            <aop:before method="beginTransaction" pointcut-ref="pt1"></aop:before>
            <aop:after-returning method="commit" pointcut-ref="pt1"></aop:after-returning>
            <aop:after-throwing method="rollback" pointcut-ref="pt1"></aop:after-throwing>
            <aop:after method="release" pointcut-ref="pt1"></aop:after>

            <aop:around method="transactionAround" pointcut-ref="pt1"></aop:around>

        </aop:aspect>
    </aop:config>

</beans>

  6.测试类

public class AccountTransactionTest {

    @Test
    public void test(){

        ApplicationContext context = new ClassPathXmlApplicationContext("bean.xml");
        IAccountService accountService = (IAccountService)context.getBean("accountService");
        accountService.transfer("aaa","bbb",100f);
    }

}

2.3 基于注解的AOP开发(DUUtils作为持久层开发)

在Dao层接口的实现中加入 @Repository("accountDao")
在Service层接口实现在中加入@Service("accountService")
1.配置文件
<?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:aop="http://www.springframework.org/schema/aop"
       xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans 
            http://www.springframework.org/schema/beans/spring-beans.xsd
            http://www.springframework.org/schema/aop
            http://www.springframework.org/schema/aop/spring-aop.xsd
            http://www.springframework.org/schema/context
            http://www.springframework.org/schema/context/spring-context.xsd"
> <context:component-scan base-package="com.itheima"/> <!--配置QueryRunner--> <bean id="runner" class="org.apache.commons.dbutils.QueryRunner" scope="prototype"/> <context:property-placeholder location="classpath:jdbc.properties"/> <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource"> <!--连接数据库的必备信息--> <property name="driverClass" value="${jdbc.driverClass}"></property> <property name="jdbcUrl" value="${jdbc.url}"></property> <property name="user" value="${jdbc.username}"></property> <property name="password" value="${jdbc.password}"></property> </bean> <!-- 配置Connection的工具类 ConnectionUtils --> <bean id="connectionUtils" class="com.itheima.utils.ConnectionUtils"> <property name="dataSource" ref="dataSource"></property> </bean> <!--开启aop注解开发--> <aop:aspectj-autoproxy/> </beans>

 2.事务管理器类

/**
 * 和事务管理相关的工具类,它包含了,开启事务,提交事务,回滚事务和释放连接
 */
//@Component("txManager")
//@Aspect
public class TransactionManager2 {

    @Autowired
    private ConnectionUtils connectionUtils;


    @Pointcut("execution(* com.itheima.service.impl.*.*(..))")
    public void pd1(){
    }

    /**
     * 开启事务
     */
   // @Before("pd1()")
    public void beginTransaction(){
        try {
            connectionUtils.getThreadConnection().setAutoCommit(false);
        }catch (Exception e){
            e.printStackTrace();
        }
    }

    /**
     * 提交事务
     */
    //@AfterReturning("pd1()")
    public  void commit(){
        try {
            connectionUtils.getThreadConnection().commit();
        }catch (Exception e){
            e.printStackTrace();
        }
    }

    /**
     * 回滚事务
     */
    //@AfterThrowing("pd1()")
    public  void rollback(){
        try {
            connectionUtils.getThreadConnection().rollback();
        }catch (Exception e){
            e.printStackTrace();
        }
    }

    /**
     * 释放连接
     */
   // @After("pd1()")
    public  void release(){
        try {
            connectionUtils.getThreadConnection().close();//还回连接池中
            connectionUtils.removeConnection();
        }catch (Exception e){
            e.printStackTrace();
        }
    }

    @Around("pd1()")
    public Object transactionAround(ProceedingJoinPoint pip){
        Object reValue = null;

        try {
            Object[] args = pip.getArgs();
            beginTransaction();
            //执行方法
            reValue = pip.proceed(args);
            System.out.println(reValue+"----------------------------------");
            commit();
        }catch (Throwable e){
            rollback();
            e.printStackTrace();
        }finally {
            release();
        }
        return reValue;
    }
}

 3.测试类

public class AccountTransactionTest {
@Test public void test(){ ApplicationContext context = new ClassPathXmlApplicationContext("bean2.xml"); IAccountService accountService = (IAccountService)context.getBean("accountService"); accountService.transfer("aaa","bbb",100f); } }

3. SpringTemplate与声明式事务

  3.1配置文件的开发

    1.持久层的编写

/**
 * 账户的持久层实现类
 */
public class AccountDaoImpl3 implements IAccountDao {

    private JdbcTemplate jdbcTemplate;

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

    public List<Account> findAllAccount() {

        try {
            return jdbcTemplate.query("select * from account",new BeanPropertyRowMapper<Account>(Account.class));
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    public Account findAccountById(Integer accountId) {
        try {
            List<Account> list = jdbcTemplate.query("select * from account where id = ?", 
          new BeanPropertyRowMapper<Account>(Account.class), accountId); return list.isEmpty()?null:list.get(0); } catch (Exception e) { throw new RuntimeException(e); } } public void saveAccount(Account account) { try { jdbcTemplate.update("insert into account(name,money) values(?,?)",account.getName(),account.getMoney()); } catch (Exception e) { throw new RuntimeException(e); } } public void updateAccount(Account account) { try { jdbcTemplate.update("update account set name = ?,money = ? where id = ?",account.getName(),account.getMoney(),
            account.getId()); }
catch (Exception e) { throw new RuntimeException(e); } } public void deleteAccount(Integer acccountId) { try { jdbcTemplate.update("delete from account where id = ?",acccountId); } catch (Exception e) { throw new RuntimeException(e); } } public Account findAccountByName(String accountName) { try{ List<Account> accounts = jdbcTemplate.query("select * from account where name = ? ",
          new BeanPropertyRowMapper<Account>(Account.class),accountName); if(accounts == null || accounts.size() == 0){ return null; } if(accounts.size() > 1){ throw new RuntimeException("结果集不唯一,数据有问题"); } return accounts.get(0); }catch (Exception e) { throw new RuntimeException(e); } } }

  2.XMl配置文件的编写

<?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:aop="http://www.springframework.org/schema/aop"
       xmlns:context="http://www.springframework.org/schema/context" xmlns:tx="http://www.springframework.org/schema/tx"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
    http://www.springframework.org/schema/aop
    http://www.springframework.org/schema/aop/spring-aop-3.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd">

    <!-- 配置Service -->
    <bean id="accountService" class="com.itheima.service.impl.AccountServiceImpl2">
        <property name="accountDao" ref="accountDao"></property>
    </bean>

    <!--配置Dao对象-->
    <bean id="accountDao" class="com.itheima.dao.impl.AccountDaoImpl3">
        <property name="jdbcTemplate" ref="jdbcTemplate"></property>
    </bean>

    <!-- 配置一个数据库的操作模板:JdbcTemplate -->
    <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
        <property name="dataSource" ref="dataSource"/>
    </bean>

    <context:property-placeholder location="classpath:jdbc.properties"/>

    <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
        <!--连接数据库的必备信息-->
        <property name="driverClass" value="${jdbc.driverClass}"></property>
        <property name="jdbcUrl" value="${jdbc.url}"></property>
        <property name="user" value="${jdbc.username}"></property>
        <property name="password" value="${jdbc.password}"></property>
    </bean>

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

    <!-- 事务的配置 -->
    <tx:advice id="txAdvice" transaction-manager="transactionManager">
        <tx:attributes>
            <tx:method name="*" read-only="false" propagation="REQUIRED"/>
            <tx:method name="find*" read-only="true" propagation="SUPPORTS"/>
        </tx:attributes>
    </tx:advice>

    <!--aop配置-->
    <aop:config>
        <aop:pointcut id="pd1" expression="execution(* com.itheima.service.impl.*.*(..))"/>
        <aop:advisor advice-ref="txAdvice" pointcut-ref="pd1"/>
    </aop:config>
</beans>

   3.测试类

public class AccountTransactionTest {

    @Test
    public void test1(){
        ApplicationContext context = new ClassPathXmlApplicationContext("jdbcTemplate.xml");
        IAccountService accountService = (IAccountService)context.getBean("accountService");
        accountService.transfer("aaa","bbb",100f);
    }
}

3.2纯注解开发

 1.配置文件类

@Configuration
@EnableTransactionManagement
@ComponentScan(basePackages = "com.itheima")
@PropertySource("classpath:jdbc.properties")
public class SpringTxConfiguration {

    @Value("${jdbc.driverClass}")
    public String driver;
    @Value("${jdbc.url}")
    public String url;
    @Value("${jdbc.username}")
    public String username;
    @Value("${jdbc.password}")
    public String password;

    @Bean(name="dataSource")
    public DataSource createDataSource(){
        ComboPooledDataSource dataSource = new ComboPooledDataSource();
        try {

            System.out.println(driver);
            System.out.println(url);
            System.out.println(password);
            System.out.println(username);

            dataSource.setDriverClass(driver);
            dataSource.setJdbcUrl(url);
            dataSource.setPassword(password);
            dataSource.setUser(username);
        } catch (PropertyVetoException e) {
            e.printStackTrace();
        }
        return dataSource;
    }
    @Bean(name="jdbcTemplate")
    public JdbcTemplate createJdbcTemplate(DataSource dataSource){
        return new JdbcTemplate(dataSource);
    }
    @Bean(name="transactionManager")
    public DataSourceTransactionManager createtransactionManager(DataSource dataSource){
        return new DataSourceTransactionManager(dataSource);
    }

}

 2.持久层类

/**
 * 账户的持久层实现类
 */
@Repository("accountDao")
public class AccountDaoImpl3_Anno implements IAccountDao {

    @Autowired
    private JdbcTemplate jdbcTemplate;

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

    public List<Account> findAllAccount() {

        try {
            return jdbcTemplate.query("select * from account",new BeanPropertyRowMapper<Account>(Account.class));
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    public Account findAccountById(Integer accountId) {
        try {
            List<Account> list = jdbcTemplate.query("select * from account where id = ?", 
          new BeanPropertyRowMapper<Account>(Account.class), accountId); return list.isEmpty()?null:list.get(0); } catch (Exception e) { throw new RuntimeException(e); } } public void saveAccount(Account account) { try { jdbcTemplate.update("insert into account(name,money) values(?,?)",account.getName(),account.getMoney()); } catch (Exception e) { throw new RuntimeException(e); } } public void updateAccount(Account account) { try { jdbcTemplate.update("update account set name = ?,money = ? where id = ?",
          account.getName(),account.getMoney(),account.getId()); }
catch (Exception e) { throw new RuntimeException(e); } } public void deleteAccount(Integer acccountId) { try { jdbcTemplate.update("delete from account where id = ?",acccountId); } catch (Exception e) { throw new RuntimeException(e); } } public Account findAccountByName(String accountName) { try{ List<Account> accounts = jdbcTemplate.query("select * from account where name = ? ",
          new BeanPropertyRowMapper<Account>(Account.class),accountName); if(accounts == null || accounts.size() == 0){ return null; } if(accounts.size() > 1){ throw new RuntimeException("结果集不唯一,数据有问题"); } return accounts.get(0); }catch (Exception e) { throw new RuntimeException(e); } } }

3.服务层类

@Service("accountService")
@Transactional(readOnly = true,propagation = Propagation.SUPPORTS)
public class AccountServiceImpl2_Anno implements IAccountService{

    @Autowired
    private IAccountDao accountDao;

    public List<Account> findAllAccount() {

            List<Account> accounts = accountDao.findAllAccount();

            return accounts;

    }

    public Account findAccountById(Integer accountId) {
        Account account = accountDao.findAccountById(accountId);

        return account;
    }

    public void saveAccount(Account account) {
        accountDao.saveAccount(account);
    }

    public void updateAccount(Account account) {

        accountDao.updateAccount(account);
    }

    public void deleteAccount(Integer acccountId) {

        accountDao.deleteAccount(acccountId);

    }

    @Transactional(readOnly = false,propagation = Propagation.REQUIRED)
    public void transfer(String sourceName, String targetName, Float money) {

            //2.1根据名称查询转出账户
            Account source = accountDao.findAccountByName(sourceName);
            //2.2根据名称查询转入账户
            Account target = accountDao.findAccountByName(targetName);
            //2.3转出账户减钱
            source.setMoney(source.getMoney()-money);
            //2.4转入账户加钱
            target.setMoney(target.getMoney()+money);
            //2.5更新转出账户
            accountDao.updateAccount(source);

           // int i=1/0;

            //2.6更新转入账户
            accountDao.updateAccount(target);

    }
}

4.测试类

public class AccountTransactionTest {

@Test public void test3Anno(){ ApplicationContext context = new AnnotationConfigApplicationContext(SpringTxConfiguration.class); IAccountService accountService = (IAccountService)context.getBean("accountService"); accountService.transfer("aaa","bbb",100f); } }

 

posted @ 2020-02-24 21:20  wu阿毛  阅读(134)  评论(0)    收藏  举报