zoukankan      html  css  js  c++  java
  • spring学习9-代理模式

    代理模式

    静态代理

    场景:

    服务层有增删查改功能,现在需要对增删改添加事务的支持。

    如果在基础的代码上修改的话会很麻烦,所以使用代理的模式

    1.抽象角色

    创建一个抽象角色,比如咋们平时做的用户业务,抽象起来就是增删改查!

    //抽象角色:增删改查业务
    public interface UserService {
        void add();
        void delete();
        void update();
        void query();
    }
    

    2.真实对象

    我们需要一个真实对象来模拟完成这些增删改查操作

    //真实对象,完成增删改查操作的人
    public class UserServiceImpl implements UserService {
        @Override
        public void add() {
            System.out.println("增加一个用户");
        }
    
        @Override
        public void delete() {
            System.out.println("删除一个用户");
        }
    
        @Override
        public void update() {
            System.out.println("更新一个用户");
        }
    
        @Override
        public void query() {
            System.out.println("查找一个用户");
        }
    }
    

    3.模拟事务

    public class MyTransaction {
        public void starTranSaction(){
            System.out.println("开启事务...");
        }
        public void closeTranSaction(){
            System.out.println("关闭事务...");
        }
    }
    

    4.代理角色

    设置一个代理类来模拟处理事务

    /代理角色,在这里面增加事务的支持
    public class UserServiceProxy implements UserService {
        private MyTransaction transaction = new MyTransaction();
        private UserServiceImpl userService;
        public void setUserService(UserServiceImpl userService) {
            this.userService = userService;
        }
    
        @Override
        public void add() {
            transaction.starTranSaction();
            userService.add();
            transaction.closeTranSaction();
        }
    
        @Override
        public void delete() {
            transaction.starTranSaction();
            userService.delete();
            transaction.closeTranSaction();
        }
    
        @Override
        public void update() {
            transaction.starTranSaction();
            userService.update();
            transaction.closeTranSaction();
        }
    
        @Override
        public void query() {
            userService.query();
        }
    }
    

    5.测试

        @Test
        public void test1() {
            UserServiceImpl userService = new UserServiceImpl();
            UserServiceProxy proxy = new UserServiceProxy();
            proxy.setUserService(userService);
            proxy.query();
            proxy.add();
            proxy.delete();
            proxy.update();
        }
    

    6.结果

    可以看到,查找的时候没有事务,其它的都添加了事务的支持

    查找一个用户
    开启事务...
    增加一个用户
    关闭事务...
    开启事务...
    删除一个用户
    关闭事务...
    开启事务...
    更新一个用户
    关闭事务...
    

    代理模式的优缺点:

    优点:

    • 可以使真实角色的操作更加纯粹,不用去关心一些公共的业务
    • 公共的业务交给了代理角色,实现业务分工
    • 公共业务发生扩展的时候,方便集中管理

    缺点:

    • 一个真实角色就会产生一个代理角色,代码量翻倍,开发效率变低

    这时候就可以考虑动态代理了

    动态代理

    • 动态代理的角色和静态代理的一样 .
    • 动态代理的代理类是动态生成的 . 静态代理的代理类是我们提前写好的
    • 动态代理分为两类 : 一类是基于接口动态代理 , 一类是基于类的动态代理
      • 基于接口的动态代理----JDK动态代理
      • 基于类的动态代理--cglib
      • 现在用的比较多的是 javasist 来生成动态代理 . 百度一下javasist
      • 我们这里使用JDK的原生代码来实现,其余的道理都是一样的!

    JDK的动态代理需要了解两个类

    核心 : InvocationHandler 和 Proxy , 打开JDK帮助文档看看

    InvocationHandler:调用处理程序

    Object invoke(Object proxy, 方法 method, Object[] args);
    //参数 
    //proxy - 调用该方法的代理实例 
    //method -所述方法对应于调用代理实例上的接口方法的实例。 方法对象的声明类将是该方法声明的接口,它可以是代理类继承该方法的代理接口的超级接口。 
    //args -包含的方法调用传递代理实例的参数值的对象的阵列,或null如果接口方法没有参数。 原始类型的参数包含在适当的原始包装器类的实例中,例如java.lang.Integer或java.lang.Boolean 。 
    

    Proxy : 代理

    //生成代理类
    public Object getProxy(){
        return Proxy.newProxyInstance(this.getClass().getClassLoader(),
                                      rent.getClass().getInterfaces(),this);
    }
    

    代码实现

    动态代理处理程序

    import java.lang.reflect.InvocationHandler;
    import java.lang.reflect.Method;
    import java.lang.reflect.Proxy;
    //这是处理程序,不是代理类,可以通过这个处理程序生成一个带类
    public class UserServiceInvocationHandler implements InvocationHandler {
        private MyTransaction transaction = new MyTransaction();
        private UserService userService;//被代理的接口
    
        public void setUserService(UserService userService) {
            this.userService = userService;
        }
    
        //生成代理类,重点是第二个参数,获取要代理的抽象角色!
        public Object getProxy() {
            return Proxy.newProxyInstance(this.getClass().getClassLoader(),
                    userService.getClass().getInterfaces(),this);
        }
    
        // 处理代理实例,并返回结果
        @Override
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
            if(method.getName().equals("query")){
                Object result = method.invoke(userService,args);
                return result;
            }else {
                transaction.starTranSaction();
                Object result = method.invoke(userService,args);//核心:本质利用反射实现!
                transaction.closeTranSaction();
                return result;
            }
        }
    }
    

    测试

    //动态代理
    @Test
    public void test2() {
        UserServiceImpl userService = new UserServiceImpl();//真实角色
        UserServiceInvocationHandler pih = new UserServiceInvocationHandler();//处理程序
        pih.setUserService(userService); //设置代理的对象
        UserService proxy = (UserService) pih.getProxy(); //动态生成对应的代理类!
        proxy.query();
        proxy.add();
        proxy.delete();
        proxy.update();
    }
    

    结果

    查找一个用户
    开启事务...
    增加一个用户
    关闭事务...
    开启事务...
    删除一个用户
    关闭事务...
    开启事务...
    更新一个用户
    关闭事务...
    

    核心:一个动态代理 , 一般代理某一类业务 , 一个动态代理可以代理多个类,代理的是接口!、

    动态代理程序模板

    我们也可以编写一个通用的动态代理实现的类!所有的代理对象设置为Object即可!

    //动态代理处理程序
    public class ProxyInvocationHandler implements InvocationHandler {
        private Object target;//代理的接口
    
        public void setTarget(Object target) {
            this.target = target;
        }
        //生成代理类
        public Object getProxy(){
            return Proxy.newProxyInstance(this.getClass().getClassLoader(),
                    target.getClass().getInterfaces(),this);
        }
        //处理代理实例,并返回结果
        @Override
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
            doSomething();//在真实对象的方法执行之前执行额外业务
            Object result = method.invoke(target,args);//通过反射生成代理对象
            return result;
        }
        //额外的业务
        private void doSomething(){
            System.out.println("run...");
        }
    }
    

    动态代理的好处

    静态代理有的它都有,静态代理没有的,它也有!

    • 可以使得我们的真实角色更加纯粹 . 不再去关注一些公共的事情 .
    • 公共的业务由代理来完成 . 实现了业务的分工 ,
    • 公共业务发生扩展时变得更加集中和方便 .
    • 一个动态代理 , 一般代理某一类业务
    • 一个动态代理可以代理多个类,代理的是接口!

    爱生活,爱码字

    我是匆匆、我曾喂自己半年酒。

    好好生活吧,有缘或许相见。

  • 相关阅读:
    通用权限管理设计 之 数据库结构设计
    jQuery LigerUI 插件介绍及使用之ligerDateEditor
    jQuery LigerUI 插件介绍及使用之ligerTree
    jQuery LigerUI V1.01(包括API和全部源码) 发布
    jQuery liger ui ligerGrid 打造通用的分页排序查询表格(提供下载)
    jQuery LigerUI V1.1.5 (包括API和全部源码) 发布
    jQuery LigerUI 使用教程表格篇(1)
    jQuery LigerUI V1.0(包括API和全部源码) 发布
    jQuery LigerUI V1.1.0 (包括API和全部源码) 发布
    nginx keepalived
  • 原文地址:https://www.cnblogs.com/ccoonngg/p/12026765.html
Copyright © 2011-2022 走看看