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

2023-09-17 21:31:14

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

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

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发生的可能性。也就是说,如果你喜欢他,那么他就会喜欢你。如果你对他好,他也会对你好的。因此,如果你表白,你需要相信他,将全部的情感完全吐露给对方,将真诚当成一生的信念,投入到爱情中,去充实彼此的关系,全心全意地去经营彼此的关系,将相互接纳、宽容、体谅和支持当作最可贵的宝贵财富。 

更多推荐

第三届阿里云磐久智维算法大赛——GRU BaseLine

赛题比赛链接:第三届阿里云磐久智维算法大赛-天池大赛-阿里云天池(aliyun.com)大赛概况庸医只知头痛医头脚痛医脚,凡良医者,必会抽丝剥茧,察其根本,方得药到病除。第一届和第二届磐久智维算法大赛,我们针对异常预测开展了积极的探索和卓有成效的实践。本届大赛我们延续对异常/故障这一领域的深入挖掘,以根因诊断为赛题,和

HTML

HTML1.HTML结构1.1认识HTMLHTML是超文本标记语言,电脑上看到的所有网站都是html实现的HTML代码是“标签”构成的,简单来说,html就是一堆标签的组合形如<body>hello</body>标签名(body)放到<>中大部分标签成对出现.为开始标签,为结束标签.少数标签只有开始标签,称为“单标签”

Linux内嵌汇编

文章目录前言一、内嵌汇编二、内嵌汇编示例三、不使用printf实现打印四、INT80H总结前言本篇文章我们来讲讲内嵌汇编的概念和教大家如何来编写内嵌汇编的代码。一、内嵌汇编内嵌汇编(InlineAssembly)是将汇编代码嵌入到高级语言中的一种编码技术。内嵌汇编能够将底层的机器代码和高层的高级语言代码无缝地结合起来,

java_web的框架分析

文章目录本阶段技术体系用项目理解原理controllersClassPathXmlApplicationContextDispatcherServletFruitServiceImplFilter本阶段技术体系用项目理解原理项目的目录首先设置一个参数,这里里面用反射机制,获取方法的时候如果不设置会获取到arg[0],a

Linux之Shell基础入门

文章目录什么是shellshell入门案例什么是shell什么是shell?Shell(外壳)是一个用C语言编写的程序,它是用户使用Linux的桥梁。Shell既是一种命令语言,又是一种程序设计语言。Shell是指一种应用程序,这个应用程序提供了一个界面,用户通过这个界面访问操作系统内核的服务。什么是脚本?脚本简单地说

WebGL透视投影

目录透视投影透视投影可视空间可视空间构造效果图Matrix4.setPerspective()三角形与可视化空间的相对位置示例代码代码详解示例效果投影矩阵的作用透视投影矩阵对物体进行了两次变换透视投影变换示意图透视投影在透视投影下,产生的三维场景看上去更是有深度感,更加自然,因为我们平时观察真实世界用的也是透视投影。在

Java高级-反射

反射1.介绍2.获取Class对象的三种方法3.获取类的构造器4.获取类的成员变量5.获取类的成员方法6.反射的作用和应用场景1.介绍反射加载类,并允许以编程的方式解剖类的各种成分(成员变量、方法、构造器等)反射步骤1.加载类,获取类的字节码:Class对象2.获取类的构造器:Constructor对象3.获取类的成员

JS 继承

JS继承的方式一、继承是什么?二、继承实现的方式2.1原型链继承2.2原型式继承2.3构造函数继承2.4组合继承2.5寄生式继承2.6寄生组合式继承2.7extends方法一、继承是什么?继承(inheritance)是面向对象软件技术当中的一个概念。如果一个类别B“继承自”另一个类别A,就把这个B称为“A的子类”,而

软件工程 第一次随堂练习

以下答案是经过人工智能生成,个人理解得出的答案,若有不同见解,请在评论区留言或私信说明下列需求分别属于下面的哪种类型,为什么?A.业务需求B.用户需求C.系统级(功能)需求D.性能需求E.质量需求F.约束G.对外接口H.数据需求I.过程需求J.项目需求K.其他需求(硬件需求、人力需求等)1.经过10天培训的收银员能熟练

页面静态化、Freemarker入门

页面静态化介绍页面的访问量比较大时,就会对数据库造成了很大的访问压力,并且数据库中的数据变化频率并不高。那需要通过什么方法为数据库减压并提高系统运行性能呢?答案就是页面静态化。页面静态化其实就是将原来的动态网页(例如通过ajax请求动态获取数据库中的数据并展示的网页)改为通过静态化技术生成的静态网页,这样用户在访问网页

《IP编址与路由:网络层的关键技术》

前言:在TCP/IP协议栈中,网络层位于第三层,起到了承上启下的关键作用。它不仅负责处理来自数据链路层和传输层的请求,还需确保数据包的正确转发。本文将深入探讨IP编址与路由的相关知识,帮助您更好地理解网络层的重要性和应用。目录IP地址分类:ARP/RARP协议原理:路由器工作原理:IP地址分类:IPv4和IPv6是两种

热文推荐