spring之事务之动态代理

  • 事务使用的地方
    service层
  • 事务配置
    package com.spring.utils;
    
    /**
     * 和事务相关的工具类,它3包含了,开启事务,提交事务、回滚事务、释放事务
     */
    public class TransactionManagement {
    
        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();
            }catch (Exception e){
                e.printStackTrace();
            }
        }
    
    }
    
  • 配置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:context="http://www.springframework.org/schema/context"
           xsi:schemaLocation="http://www.springframework.org/schema/beans
            https://www.springframework.org/schema/beans/spring-beans.xsd
            http://www.springframework.org/schema/context
            https://www.springframework.org/schema/context/spring-context.xsd">
    
    
        <!--配置service层-->
        <bean id="accountService" class="com.spring.service.impl.AccountServiceImpl">
            <property name="accountDao" ref="accountDao"></property>
            <property name="txManagement" ref="transactionManagement"></property>
        </bean>
        <!--配置dao层-->
        <bean id="accountDao" class="com.spring.dao.AccountDaoImpl">
            <property name="queryRunner" ref="queryRunner"></property>
            <property name="connectionUtils" ref="connectionUtils"></property>
        </bean>
    
        <!--配置QueryRunner-->
        <bean id="queryRunner" class="org.apache.commons.dbutils.QueryRunner" scope="prototype"></bean>
    
        <!--配置数据源-->
        <bean id="datasource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
            <property name="driverClass" value="com.mysql.cj.jdbc.Driver"></property>
            <property name="jdbcUrl" value="jdbc:mysql://120.25.236.19:3306/practice?useSSL=false"></property>
            <property name="user" value="root"></property>
            <property name="password" value="123456"></property>
        </bean>
    
        <!--配置Connection的工具类-->
        <bean id="connectionUtils" class="com.spring.utils.ConnectionUtils">
            <property name="dataSource" ref="datasource"></property>
        </bean>
    
    
        <!--配置事务管理器-->
        <bean id="transactionManagement" class="com.spring.utils.TransactionManagement">
            <property name="connectionUtils" ref="connectionUtils"></property>
        </bean>
    
    </beans>
  • 使用事务
    说明:每个方法都需要使用,代码比较臃肿,不易维护需要我们进行改造

    package com.spring.service.impl;
    
    import com.spring.dao.AccountDao;
    import com.spring.entity.Account;
    import com.spring.entity.Area;
    import com.spring.service.AccountService;
    import com.spring.utils.TransactionManagement;
    
    
    /**
     * 问题:每个方法都写txManagement 事务方法
     *          代码比较臃肿,不易维护
     */
    
    public class AccountServiceImpl implements AccountService {
    
        private AccountDao accountDao;
        private TransactionManagement txManagement;
    
        public void setAccountDao(AccountDao accountDao) {
            this.accountDao = accountDao;
        }
    
        public void setTxManagement(TransactionManagement txManagement) {
            this.txManagement = txManagement;
        }
    
        public Account findAccountByName(String accountName) {
            try{
                txManagement.beginTransaction();
                Account accountByName = accountDao.findAccountByName(accountName);
                txManagement.commit();
                return  accountByName;
            }catch (Exception e){
                txManagement.rollback();
                throw  new RuntimeException(e);
            }finally {
                txManagement.release();
            }
        }
    
        public void updateAccount(Account account) {
            try{
                txManagement.beginTransaction();
                accountDao.updateAccount(account);
                txManagement.commit();
            }catch (Exception e){
                txManagement.rollback();
                throw  new RuntimeException(e);
            }finally {
                txManagement.release();
            }
    
        }
    
    
    
        public void transfer(String sourceName, String targetName, Float money) {
            try{
                txManagement.beginTransaction();
                //根据A名称查询出账户
                Account source = accountDao.findAccountByName(sourceName);
                //根据B名称查询出账户
                Account target = accountDao.findAccountByName(targetName);
                //转出账户减钱
                source.setMoney(source.getMoney() - money);
                //转入账户加钱
                target.setMoney(target.getMoney() + money);
                //更新转出账户
                accountDao.updateAccount(source);
                int i = 1/0;
                //更新转入账户
                accountDao.updateAccount(target);
                txManagement.commit();
            }catch (Exception e){
                txManagement.rollback();
                throw  new RuntimeException(e);
            }finally {
                txManagement.release();
            }
    
        }
    }
    

动态代理

  • 概念
* 动态代理
*      特点:字节码随用随创建,随用随加载
*      作用:不修改源码的基础上对方法增强
*      分类:
*          基于接口的动态代理
*          基于类的动态代理
*      基于接口的动态代理:
*          涉及的类:Proxy
*          提供者:JDK官方
*      创建接口代理对象:
*          使用Proxy的newProxyInstance方法
*      创建接口代理的要求:
*          被代理类最少要实现一个接口,如果没有则不能使用。
*      newProxyInstance方法的参数。
*          ClassLoader:类加载器
*              他是用于加载代理对象字节码的,和被代理对象使用相同的类加载器。固定写法。
*          Class[]:字节码数组
*               他是用于让代理对象和被代理对象有相同方法,固定写法。
*          InvocationHandler:用于提供增强的代码
*                他是让我们写如何代理,我们一般都是些一个该接口的实现类,通常情况下都是匿名内部类,但不是必须的,此接口的实现类都是谁用谁写。

  • 接口代理
  public static void main(String[] args) {
        final Product product = new Product();
    IProduct iProduct = (IProduct)Proxy.newProxyInstance(product.getClass().getClassLoader(), product.getClass().getInterfaces(), new InvocationHandler() {
        /**
         * 作用:执行被代理对象的任何接口方法都会经过该方法
         * @param proxy 代理对象的引用,一般不用
         * @param method 当前执行的方法
         * @param args  和被代理有相同的返回值
         * @return
         * @throws Throwable
         */
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
            //提供增强的方法
            Object returnValue = null;
            //1、获取执行方法的参数
            Float arg = (Float) args[0];
            //2.判断时不是增强方法(销售)
            if("saleProduct".equals(method.getName())){
                returnValue = method.invoke(product, arg * 0.8f);
            }
            return returnValue;
        }
    });
        iProduct.saleProduct(10000);
    }
}
  • 类的代理
    导包

            <dependency>
                <groupId>cglib</groupId>
                <artifactId>cglib</artifactId>
                <version>2.1_3</version>
            </dependency>
         *      创建接口代理对象:
         *          Enhancer类中的create方法
         *      创建类代理的要求:
         *          被代理类不是最终类。 最终类指被final修饰的类,不能被修改。
         *      create方法的参数。
         *           Class字节码数组
         *                     他是用于指定被代理对象的字节码。
         *
         *           Callback:用于提供增强的代码
         *                     他是让我们写如何代理。我们一般都是些一个该接口的实现类、通常情况下都是            
         *                     匿名内部类,但是不是必须的。
         *                     此接口的实现类都是谁用谁写。
         *                     我们一般写的都是该接口的子接口实现类:MethodInterceptor
    
    
    
    public static void main(String[] args) {
            final Product product = new Product();
            IProduct p = (IProduct) Enhancer.create(product.getClass(), new MethodInterceptor() {
                /**
                 * 作用:执行被代理对象的任何接口方法都会经过该方法
                 * @param proxy  代理对象的引用,一般不用
                 * @param method 当前执行的方法
                 * @param args   和被代理有相同的返回值
                 * @return
                 * @throws Throwable
                 */
                public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
                    //提供增强的方法
                    Object returnValue = null;
                    //1、获取执行方法的参数
                    Float arg = (Float) args[0];
                    //2.判断时不是增强方法(销售)
                    if ("saleProduct".equals(method.getName())) {
                        returnValue = method.invoke(product, arg * 0.8f);
                    }
                    return returnValue;
                }
            });
            p.saleProduct(10000f);
        }
    }
  • 总结:
    代理都是向上转型

  • 1

  • git地址:
     https://gitee.com/Xiaokeworksveryhard/dynamic_proxy.git

发布了158 篇原创文章 · 获赞 26 · 访问量 9万+

猜你喜欢

转载自blog.csdn.net/qq_41650354/article/details/103755970
今日推荐