zoukankan      html  css  js  c++  java
  • 代理模式

    一、代理模式介绍

    1、定义与类型

    定义:为其他对象提供一种代理,以控制对这个对象的访问
    代理对象在客户端和目标对象之间起到中介的作用
    类型:结构型

    2、适用场景

    保护目标对象
    增强目标对象

    3、优点

    代理模式能将代理对象与真实被调用的目标对象分离
    一定程度上降低了系统的耦合度,扩展性好
    保护目标对象
    增强目标对象

    4、缺点

    代理模式会造成系统设计中类的数目增加
    在客户端和目标对象增加一个代理对象,会造成请求处理速度变慢
    增加系统的复杂度

    5、扩展

    静态代理
    动态代理
    CGLib代理

    6、Spring代理选择-扩展

    当Bean有实现接口时,Spring就会用JDK的动态代理
    当Bean没有实现接口时,Spring使用CGlib
    可以强制使用Cglib
    在spring配置中加入<aop:aspectj-autoproxy proxy-target-class="true"/>
    参考资料:htpsi//docs.spring.io/spring/docs/current/spring-framework-reference/core.html

    7、代理-相关设计模式

    代理模式和装饰者模式
    实现上相似,但目的不同,装饰者模式是为对象加上行为,而代理模式是为了控制访问,代理模式更加注重通过增加代理人的方式来增强目标对象。

    代理模式和适配器模式
    适配器模式主要考虑改变目标对象的接口,而代理模式是不能改变代理类的接口的

    二、代码示例

    模拟场景:spring中,service调用dao前,需要先根据分库策略,切换数据源,即AOP面向切面

    实体订单类:

    public class Order {
        private Object orderInfo;
        private Integer userId;
        public Object getOrderInfo() {
            return orderInfo;
        }
        public void setOrderInfo(Object orderInfo) {
            this.orderInfo = orderInfo;
        }
        public Integer getUserId() {
            return userId;
        }
        public void setUserId(Integer userId) {
            this.userId = userId;
        }
    }
    

    持久层dao接口:

    public interface IOrderDao {
        int insert(Order order);
    }
    

    持久层dao实现类:

    public class OrderDaoImpl implements IOrderDao {
        @Override
        public int insert(Order order) {
            System.out.println("Dao层添加Order成功");
            return 1;
        }
    }
    

    服务层service接口:

    public interface IOrderService {
        int saveOrder(Order order);
    }
    

    服务层service类:

    public class OrderServiceImpl implements IOrderService {
        private IOrderDao iOrderDao;
        @Override
        public int saveOrder(Order order) {
            //模拟自动注入
            iOrderDao = new OrderDaoImpl();
            System.out.println("Service层调用Dao层添加Order");
            return iOrderDao.insert(order);
        }
    }
    

    1、静态代理

    静态代理类:

    public class OrderServiceStaticProxy {
        private IOrderService iOrderService;
    
        public int saveOrder(Order order){
            beforeMethod(order);
            // 模拟自动注入
            iOrderService = new OrderServiceImpl();
            int result = iOrderService.saveOrder(order);
            afterMethod();
            return result;
        }
    
        private void beforeMethod(Order order){
            // 模拟分库代理操作
            int userId = order.getUserId();
            int dbRouter = userId % 2;
            System.out.println("静态代理分配到【db"+dbRouter+"】处理数据");
    
            //todo 设置dataSource;
            DataSourceContextHolder.setDBType("db"+String.valueOf(dbRouter));
            System.out.println("静态代理 before code");
        }
    
        private void afterMethod(){
            System.out.println("静态代理 after code");
        }
    }
    

    测试类:

    public class Test {
        public static void main(String[] args) {
            Order order = new Order();
            order.setUserId(2);
            
            //直接调用代理类
            OrderServiceStaticProxy orderServiceStaticProxy = new OrderServiceStaticProxy();
            orderServiceStaticProxy.saveOrder(order);
        }
    }
    

    2、动态代理

    动态代理类:

    public class OrderServiceDynamicProxy implements InvocationHandler {
        private Object target;
    
        public OrderServiceDynamicProxy(Object target) {
            this.target = target;
        }
    
        public Object bind(){
            Class cls = target.getClass();
            return Proxy.newProxyInstance(cls.getClassLoader(),cls.getInterfaces(),this);
        }
    
        @Override
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
            Object argObject = args[0];
            beforeMethod(argObject);
            Object object = method.invoke(target,args);
            afterMethod();
            return object;
        }
    
        private void beforeMethod(Object obj){
            int userId = 0;
            System.out.println("动态代理 before code");
            if(obj instanceof Order){
                Order order = (Order)obj;
                userId = order.getUserId();
            }
            int dbRouter = userId % 2;
            System.out.println("动态代理分配到【db"+dbRouter+"】处理数据");
    
            //todo 设置dataSource;
            DataSourceContextHolder.setDBType("db"+String.valueOf(dbRouter));
        }
    
        private void afterMethod(){
            System.out.println("动态代理 after code");
        }
    }
    

    测试类:

    public class Test {
        public static void main(String[] args) {
            Order order = new Order();
            order.setUserId(1);
    // 通过代理类取到service
            IOrderService orderServiceDynamicProxy = (IOrderService) new OrderServiceDynamicProxy(new OrderServiceImpl()).bind();
    
            orderServiceDynamicProxy.saveOrder(order);
        }
    }
    

    三、 源码示例

    1、spring中的ProxyFactoryBean(静态代理)

    2、mybatis中的MapperProxy(动态代理)

  • 相关阅读:
    ubuntu修改主机名称+修改终端显示目录和计算机名称
    google 搜索 PPT
    就为在YouTube上下载个视频
    读书笔记 ---- 《嵌入式系统技术》
    WARNING: Unable to open an initial console
    Ubuntu ftp服务器搭建 + UltraEdit编辑FTP文件
    51Nod 1079 中国剩余定理【模板题】
    Leetcode 11 Container with most water【双指针】
    kuangbin专题六 最小生成树【从入门到熟练】【5题】
    kuangbin专题十二 基础DP1【从入门到熟练】【10题】
  • 原文地址:https://www.cnblogs.com/weixk/p/12996346.html
Copyright © 2011-2022 走看看