Spring设计模式,事务管理和代理模式的应用

2023-11-10

扩充:贝叶斯定理答案见底。

设计模式对关于面向对象问题的具体解决方案.

1,单例多例

在设计单例模式时,要注意两个点

1.构造方法要私有

2.成员变量要私有

3.创建对象所用的方法要被synchronized修饰.(因为方法体中会涉及到判断当前成员对象是否为空,在饿汉模式下,会有多个线程来访问该方法,为了防止判断访问结果同时为空,从而创建多个对象,就要被synchronized修饰)

2,模版

所谓模板板式,就是在父类中定义算法的主要流程,而把一些个性化的步骤延迟到子类中去实现,父类始终控制着整个流程的主动权,子类只是辅助父类实现某些可定制的步骤

父类

public abstract class FatherClass {

    //人生
    public final void 人生(){
        学习();
        工作();
        爱情();
    }

    //学习
    public void 学习(){
        System.out.println("=========放学回家学到晚上12点不许睡觉===========");
    }

    //工作
    public void 工作(){
        System.out.println("============稳定就好===============");
    }

    //爱情(放飞自我)
    public abstract void 爱情();



}

继承父类的类

package com.apesource.test;
//儿子
public class SonClass extends FatherClass{



    @Override
    public void 学习() {
        System.out.println("=========开心就好,及格万岁============");
    }


    @Override
    public void 爱情() {
        System.out.println("======肤白貌美大长腿.....=======");
    }
}

如果该方法被重写,那么结果是子类的内容。反之,则是父类的内容 

  •  Spring中jdbcTemplate、hibernateTemplate等以Template结尾的
  •  对数据库操作的类,它们就使用到模板模式。一般情况下,我们都是使用继承的方式来实现模板模式,但是Spring并没有使用这种方式,而是使用Callback模式与模板方法配合,既达到了代码复用的效果,同时增加了灵活性。

3,工厂

一个工厂可以根据传入参数的不同,而创建出来不同的对象。

4,代理(静态代理,动态代理)

 功能:
        1.中介隔离作用
        2.方法增强

一.静态代理,静态代理中,代理在代码执行前已经被创建出来了。

动态代理,是代码执行的时候被创建出来的, 1.基于接口(jdk自带)2.基于子类(第三方)

import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.InvocationHandler;子类

public class Test03 {
    public static void main(String[] args) {
        //1.创建被代理对象
        ISinger teng = new TengEr();
        //2.创建代理对象
        ISinger jinJiRen = (ISinger)Enhancer.create(teng.getClass(), new InvocationHandler() {
            @Override
            public Object invoke(Object o, Method method, Object[] objects) throws Throwable {

                Object obj = method.invoke(teng,objects);

                return obj;
            }
        });

        //3.使用
        jinJiRen.sing();


    }
}

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy; 

public class Test02 {
    public static void main(String[] args) {
        //1.被代理对象
        ISinger zhouJieLun = new ZhouJieLun();
        /**
         * 2.创建代理对象
         * ClassLoader loader被代理对象的类的加载器
         * Class<?>[] interfaces,被代理对象的类的字节数组
         * InvocationHandler h处理器对象
         * */
        ISinger jinJiRen = (ISinger) Proxy.newProxyInstance(zhouJieLun.getClass().getClassLoader(), zhouJieLun.getClass().getInterfaces(), new InvocationHandler() {
            /**
             * Object proxy, 被代理对象的引用
             * Method method,被代理对象类中的所有方法
             * Object[] args 被代理对象类中的所有方法的参数
             * Object 被代理对象类中的所有方法的返回值
             *
             * */
            @Override
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                //方法增强
                System.out.println("挑一个舞,打个球~~~");

                Object obj = method.invoke(zhouJieLun,args);//执行周杰伦唱歌方法,(执行被代理对象中的所有方法)

                return obj;
            }
        });

        //3.消费使用
        jinJiRen.sing();


    }
}

 

事务管理

1,在转账服务时,更新数据库时,可能会发生异常,就会导致金额不对

解决方法,1.被调用到的dao层语句,都拿着同一个对象,这个对象可以实现锁的功能。那么就要在dao层query和update语句中,增加一个Connection对象。threadLocal可以充当sql语句的锁对象

因为threadlocal有一个线程们的公共区域,完全可以实现当公共区有一个connection的时候,线程们完全不需要再考虑在去造很多connection。

ThreadLocal叫做线程变量,意思是ThreadLocal中填充的变量属于当前线程,该变量对其他线程而言是隔离的,也就是说该变量是当前线程独有的变量。ThreadLocal为变量在每个线程中都创建了一个副本,那么每个线程可以访问自己内部的副本变量。

2.service层中,调用事务管理,当异常发生时,实现事务的回滚

①在dao层用到的连接工具类

package com.apesource.util;

import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.SQLException;

/**
 * @author  * @version 1.0
 * @since 2023/9/15
 */
public class ConnectionUtil {

    //1.线程区域对象
    ThreadLocal<Connection> threadLocal =  new ThreadLocal<Connection>();
    //2.数据源
    private DataSource dataSource;
    public void setDataSource(DataSource dataSource) {
        this.dataSource = dataSource;
    }
    Connection connection = null;

    //获取连接
    public Connection createConn(){
        try {
            //1.线程区域
            connection = threadLocal.get();
            //2.判断
            if (connection ==null){
                //创建连接
                connection = dataSource.getConnection();
                //保存
                threadLocal.set(connection);
            }
            return connection;
        } catch (SQLException throwables) {
            throwables.printStackTrace();
        }
        return null;
    }

    //关闭连接
    public void closeConn(){
        threadLocal.remove();//解除绑定
    }
}

在dao层的每一个语句都装配工具类 

 //装配连接工具类
    ConnectionUtil connectionUtil;

    public void setConnectionUtil(ConnectionUtil connectionUtil) {
        this.connectionUtil = connectionUtil;
    }

    @Override
    public void save(Student student) {
        try {
            queryRunner.update(connectionUtil.createConn(),"insert into student(sname,shobby,smoney) value(?,?,?)",student.getSname(),student.getShobby(),student.getSmoney());
        } catch (SQLException throwables) {
            throwables.printStackTrace();
        }
    }

②在service层用到的事务管理工具类

package com.apesource.util;

import java.sql.SQLException;

/**
 * @author 
 * @version 1.0
 * @since 2023/9/15
 */
public class TransactionUtil {
    //装配连接工具类
    ConnectionUtil connectionUtil;

    public void setConnectionUtil(ConnectionUtil connectionUtil) {
        this.connectionUtil = connectionUtil;
    }

    //开启事务
    public void beginTransaction(){
        try {
            connectionUtil.createConn().setAutoCommit(false);
        } catch (SQLException throwables) {
            throwables.printStackTrace();
        }
    }
    //提交事务
    public void commitTransaction(){
        try {
            connectionUtil.createConn().commit();
        } catch (SQLException throwables) {
            throwables.printStackTrace();
        }
    }
    //回滚事务
    public void rollbackTransaction(){
        try {
            connectionUtil.createConn().rollback();
        } catch (SQLException throwables) {
            throwables.printStackTrace();
        }
    }
    //关闭事务
    public void closeTransaction(){
        try {
            connectionUtil.createConn().close();//关闭连接
            connectionUtil.closeConn();//解除绑定
        } catch (SQLException throwables) {
            throwables.printStackTrace();
        }
    }
}

service里的用到的事务管理

   @Override
    public void transfer(String sourceName, String targetName, int money) {
        try {
            //开启事务
            transactionUtil.beginTransaction();
            //1.查询用户信息
            Student sourceStudent =  dao.findByName(sourceName);
            Student targetStudent =  dao.findByName(targetName);
            //2.java代码中实现转账
            sourceStudent.setSmoney(sourceStudent.getSmoney()-money);
            targetStudent.setSmoney(targetStudent.getSmoney()+money);
            //3.修改数据库
            dao.update(sourceStudent);
            int a = 10/0;//模拟异常
            dao.update(targetStudent);
            //提交事务
            transactionUtil.commitTransaction();
        } catch (Exception e) {
            e.printStackTrace();
            //回滚事务
            transactionUtil.rollbackTransaction();
        }finally {
            //关闭事务
            transactionUtil.closeTransaction();
        }
    }

                                                                      优化方法

优化方法

采用Beanfactory创建代理对象,代理对象可以用来方法增强,可以将被代理对象的方法不经过污染,就可以实现事务管理。

在这个案例中,controller是消费者

 <!--注入被代理service-->
    <bean id="serviceImp" class="com.apesource.service.StudentServiceImp">
        <property name="dao" ref="daoImp"></property>
    </bean>

    <!--注入代理service-->
    <bean id="proxySerivce" class="com.apesource.service.StudentServiceImp" factory-bean="factory" factory-method="createProxy"></bean>
    <bean id="factory" class="com.apesource.factory.BeansFactory">
        <property name="transactionUtil" ref="transactionUtil"></property>
        <property name="toProxyService" ref="serviceImp"></property>
    </bean>

    <!--注入controller-->
    <bean id="controllerImp" class="com.apesource.controller.StudentControllerImp">
        <property name="studentService" ref="proxySerivce"></property>
    </bean>

抽取方法用到了代理对象 ,BeansFactory代码如下:

package com.apesource.factory;

import com.apesource.service.IStudentService;
import com.apesource.util.TransactionUtil;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

/**
 * @author 
 * @version 1.0
 * @since 2023/9/15
 */
public class BeansFactory {

    //装配被代理业务对象
    IStudentService toProxyService;

    public void setToProxyService(IStudentService toProxyService) {
        this.toProxyService = toProxyService;
    }

    //装配事务工具类
    TransactionUtil transactionUtil;

    public void setTransactionUtil(TransactionUtil transactionUtil) {
        this.transactionUtil = transactionUtil;
    }

    //创建代理对象
    public IStudentService createProxy(){
      return (IStudentService)Proxy.newProxyInstance(toProxyService.getClass().getClassLoader(), toProxyService.getClass().getInterfaces(), new InvocationHandler() {
            @Override
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {

                Object obj = null;//主业务方法
                try {
                    transactionUtil.beginTransaction();
                    obj = method.invoke(toProxyService,args);
                    transactionUtil.commitTransaction();
                } catch (Exception e) {
                    e.printStackTrace();
                    transactionUtil.rollbackTransaction();
                } finally {
                    transactionUtil.closeTransaction();
                }
                return obj;
            }
        });
    }
}

八年后的重逢:贝叶斯定理是一则随机事件的条件概率(或边缘概率)的定理,其中P(A|B)是在B发生的情况下A发生的可能性。也就是说,如果你喜欢他,那么他就会喜欢你。如果你对他好,他也会对你好的。因此,如果你表白,你需要相信他,将全部的情感完全吐露给对方,将真诚当成一生的信念,投入到爱情中,去充实彼此的关系,全心全意地去经营彼此的关系,将相互接纳、宽容、体谅和支持当作最可贵的宝贵财富。 

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Spring设计模式,事务管理和代理模式的应用 的相关文章

随机推荐

  • 动态规划学习(一)

    动态规划算法与分治法类似 其基本思想也是将待求解问题分解成若干个子问题 但是经过分解得到的子问题往往不是相互独立的 在用分治法求解的时候 子问题被重复计算了多次 解决方法 保存已解决的子问题的答案 避免大量重复计算 动态规划与分治法区别 适
  • 前端学习:表格学习,附练习+源码

    文章目录 一 表格的主要作用 二 表格属性 三 总结 四 合并单元格方式 一 表格的主要作用 1 表格主要用于显示 展示数据 因为它可以让数据显示的非常的规整 可读性非常好 特别是后台展示数据的时候 能够熟练运用表格就显得很重要 一个清爽简
  • 微信公众号群发接口和原创校验

    一 说明 1 1限制 二 群发图文消息 三 群发图片 文本 四 群发时使用is to all 五 上传图文消息接口 5 1 上传图文消息内的图片获取URL 订阅号与服务号认证后均可用 5 2 上传图文消息素材 订阅号与服务号认证后均可用 六
  • C语言变长数组讲解

    C语言变长数组讲解 参考资料 1 https www cnblogs com Anker p 3744127 html 2 https www cnblogs com veis p 7073076 html 3 https blog csd
  • EXCEL解析导入,多线程批量插入大量数据

    EXCEL解析导入 批量插入大量数据 excel导入基本分为3个步骤 1 上传文件 2 解析文件 3 逻辑内容 首先查看是哪一步需要优化 一般需要在第3步 插入数据库的逻辑优化 如果数据量比较大的话 单条sql执行很慢 几条数据几次和数据库
  • Alibaba Java Code Guidelines

    Alibaba Java Code Guidelines这个代码规范插件 对于Java代码规范 业界有统一的标准 不少公司对此都有一定的要求 但是即便如此 庞大的Java使用者由于经验很水平的限制 未必有规范编码的意识 而且即便经验丰富的老
  • 提取python字符串括号中的内容

    一些数据按字符串保存 如str1 1 0 123 2 0 234 当我们需要将字符串中的数据提取出来进行计算时 涉及只提出括号中的内容 此时可采取用Python re正则表达式模块和split 函数完成 操作过程略复杂 有更简洁方法时再更新
  • 每日一题(C语言基础篇)3

    题目描述 求一个整数中2进制为1的个数 例如 8 00001000 有一个二进制为1的数 9999 270F 有8个2进制为1的数 代码实现 include
  • 树莓派4B串口配置

    树莓派环境 硬件 树莓派4B 系统 ubuntu22 04 串口信息 树莓派4B一共有6个串口 之前的版本只有2个串口 这6个串口中 有5个时硬件串口 还有个mini串口 这5个硬件串口在我们需要使用外设时 但是 默认情况下 5个默认串口只
  • Qt与VS的对比(1)

    对话框篇 QT与VS创建对话框的方式非常相似 都需要创建一个对话框类 在需要显示该对话框的地方包含对应的头文件 显示即可 区别 QT显示模态对话框使用函数QDialog exec VS显示模态对话框使用函数CDialog DoModal Q
  • JDK的下载与安装详细解释

    JDK的下载与安装 一 JDK下载 进入Oracle官网 https www oracle com index html 打开后我们通过选项卡找到Downloads 操作如下界面 接下来我们找到Deverloper Downloads中的J
  • Unity3D之简单的点击拾取

    新建一个Cube物体和一个脚本Cube 将Cube脚本挂到Cube物体上 代码如下 csharp view plain copy using UnityEngine using System Collections public class
  • Web Components 系列(八)—— 自定义组件的样式设置

    前言 通过前面的学习 对自定义组件的相关概念和知识点也有了一定了解 今天我们就来学习一下给自定义元素及其子元素设置样式的几种方法 直接给自定义标签添加样式 index html
  • 多module启动报错Could not resolve dependencies for project

    前几天用若依的前后端分离版本 项目能启动 打包发布时异常 提示找不到项目依赖 无法解析artifact Could not resolve dependencies for project The following artifacts c
  • [管理与领导-82]:IT基层管理者 - 核心技能 - 高效执行力 - 7- 高效执行的结果通过高效的过程保证

    目录 前言 一 执行前 对 1 1 确保做对事 do right thing 1 目标 行动的目标 2 方向 行动的方向 3 需求 行动是为了满足某种需求 4 指令 行到受谁的指令 1 2 确定做对事的方法 1 2 1 确认 do righ
  • 理解DOM事件流的三个阶段

    本文主要解决两个问题 什么是事件流 DOM事件流的三个阶段 起因 在学习前端的大半年来 对DOM事件了解甚少 一般也只是用用onclick来绑定个点击事件 在寒假深入学习JavaScript时 愈发觉得自己对DOM事件了解不够 遂打开我的
  • 全网最全的IDEA热部署方案,看完弄懂,再也不用加班

    概念 热部署就是正在运行状态的应用 修改了它的源码之后 在不重新启动的情况下能够自动把增量内容编译并部署到服务器上 使得修改立即生效 热部署为了解决的问题有两个 1 在开发的时候 修改代码后不需要重启应用就能看到效果 大大提升开发效率 2
  • python的http服务

    在一个局域网中因为要传输文件给朋友 所以建一个简单的http服务器 自己主机作为服务器 让朋友下载文件 自己主机安装pyhton 到要共享的文件夹下 开启HTTP服务 python m http server 9999 其他主机浏览器访问
  • Java实现算法“两数之和”

    最近开始刷LeetCode 为了加深印象 一定要写下来 题目 给定一个整数数组nums和一个目标值target 请你在该数组中找出和为目标值的那两个整数 并返回它们的数组下标 可以假设每种输入只会对应一个答案 但是不能重复利用这个数组中同样
  • Spring设计模式,事务管理和代理模式的应用

    扩充 贝叶斯定理答案见底 设计模式对关于面向对象问题的具体解决方案 1 单例多例 在设计单例模式时 要注意两个点 1 构造方法要私有 2 成员变量要私有 3 创建对象所用的方法要被synchronized修饰 因为方法体中会涉及到判断当前成