Spring学习(三)

  • 编写事务管理工具类并分析连接和线程解绑
  • 编写业务层和持久层事务控制代码并配置spring的ioc
  • 测试转账并分析案例中的问题

工具类:TransactionManager的实现

在这里插入*
* 和事务管理相关的工具类,它包含了: 开启事务,提交事务,回滚事务和释放连接*/
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();
        }
    }


}代码片

连接的工具类: ConnectionUtils

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

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

    private DataSource dataSource;

    public void setDataSource(DataSource dataSource) {
        this.dataSource = dataSource;
    }

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

    /*
    * 把连接和线程解绑*/
    public void removeConnection() {
        t1.remove();
    }

}
  • 使用以上两个类,实现转账功能
public void transfer(String sourceName, String targetName, Float money) {

        try {
            //1.开启事务
            tsManager.beginTransaction();
            //2.执行操作
            //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);
            //2.6.更新转入账户
            accountDao.updateAccount(target);
            //3.提交事务
            tsManager.commit();
        }catch (Exception e){
            //4.回滚操作
            tsManager.rollback();
            e.printStackTrace();
        }finally {
            //5.释放连接
            tsManager.release();
        }

动态代理学习:
  • 建立一个 Producer 类作为生产者

基于子类的生产者类:

public class Producer {

    /*
    * 销售*/
    public void saleProduct(float money) {
        System.out.println("销售产品,并拿到钱:" + money);
    }

}

基于接口的生产者类:

/*
* 一个生产者*/
public class Producer implements IProducer {

    /*
    * 销售*/
    public void saleProduct(float money) {
        System.out.println("销售产品,并拿到钱:" + money);
    }

    /*
    * 售后*/
    public void afterService(float money) {
        System.out.println("提供售后服务,并拿到钱:" + money);
    }
}

基于接口的生产者的接口:

/*
* 对生产厂家要求的接口*/
public interface IProducer {

    /*
     * 销售*/
    public void saleProduct(float money);

    /*
     * 售后*/
    public void afterService(float money);
}
  • 1.基于接口的动态代理:
/*
* 模拟一个消费者*/
public class Client {

    public static void main(String[] args) {
        final Producer producer = new Producer();

        producer.saleProduct(10000f);

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

        IProducer proxyProducer =  (IProducer)Proxy.newProxyInstance(producer.getClass().getClassLoader(),
                producer.getClass().getInterfaces(),
                new InvocationHandler() {
                /*
                proxy:代理对象的引用
                method:当前执行的方法
                args:当前执行方法所需的参数和被代理对象有相同的返回值
                作用:执行被代理对象的任何接口方法都会经过该方法*/
                    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                        //提供增强的代码
                        Object returnValue = null;
                        //1.获取方法执行的参数
                        Float money = (Float) args[0];
                        //2.判断当前方法是不是销售
                        if("saleProduct".equals(method.getName())){
                            return method.invoke(producer,money*0.8f);
                        }
                        return  returnValue;
                    }
                });
        proxyProducer.saleProduct(10000f);
    }
  • 2.基于子类的动态代理
/*
* 模拟一个消费者*/
public class Client {

    public static void main(String[] args) {
        final Producer producer = new Producer();

        producer.saleProduct(10000f);

        /*
        * 动态代理:
        *   特点: 字节码随用随创建,随用随加载
        *   作用:不修改源码的基础上对方法增强
        *   分类
        *       基于接口的动态代理
        *       基于子类的动态代理
        *   基于子类的动态代理:
        *       涉及的类:Enhancer
        *       提供者:第三方cglib库
        *   如何创建代理对象:
        *       使用Enhancer类中的create方法
        *   创建代理对象的要求:
        *       被代理类不能是最终类
        *   newProxyInstance方法的参数:
        *       Class:字节码
        *           它是用于指定被代理对象的字节码
        *       Callback:用于提供增强的代码
        *           它是让我们写如何代理。我们一般都是一个该接口的实现类,通常情况下都是匿名内部类,但不是必须的。
        *           此接口的实现类都是谁用谁写。
        *           我们一般写的都是该接口的子接口实现类:MethodInterceptor
        * */

        Producer cglibProducer = (Producer) Enhancer.create(producer.getClass(), new MethodInterceptor() {
            public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy)
                    throws Throwable {
                //提供增强的代码
                Object returnValue = null;
                //1.获取方法执行的参数
                Float money = (Float) objects[0];
                //2.判断当前方法是不是销售
                if("saleProduct".equals(method.getName())){
                    return method.invoke(producer,money*0.8f);
                }
                return  returnValue;
            }
        });
        cglibProducer.saleProduct(12000f);
    }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值