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

    定义: 为其他对象提供一种代理,以控制对这个对象的访问

    代理对象在客户端和目标对象之间起到中介的作用

    类型: 结构性

    适用场景

    1、保护目标对象

    2、增强目标对象

    优点

    代理模式能将代理对象与真实被调用的目标对象分离

    一定程度上降低了系统的耦合度,扩展性好

    保护目标对象

    增强目标对象(如加before和after)

    缺点:

    代理模式会造成系统设计中类数目增加

    在客户端和目标对象增加一个代理对象,会造成请求速度变慢

    增加系统的复杂度

    代理-扩展

    静态代理

    动态代理

    CGLib代理

    Spring 代理选择-扩展

    当Bean有实现接口时,Spring就会用JDK的动态代理

    当Bean没有实现接口时,Spring使用CGlib

    可以强制使用Cglib

          在spring配置中加入 <aop:aspectj-autoproxy proxy-target-class="true" /> 

    静态代理实践(另外一个静态代理的例子Spring AOP原理

    1、创建实体Order

    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;
        }
    }
    

      

    2、创建Dao层

     IOrderDao接口

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

      IOrderDao接口实现

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

      

    3、创建服务层

    创建IOrderService 接口

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

      创建IOrderService 接口实现

    public class OrderServiceImpl   implements  IOrderService{
    
        private IOrderDao iOrderDao;
    
        @Override
        public int saveOrder(Order order) {
            //Spring会自己注入,这里就直接注入了
            iOrderDao = new OrderDaoImpl();
            System.out.println("Service层调用Dao层添加Order");
            return  iOrderDao.insert(order);
        }
    }
    

      

    4、模拟Spring中分库的使用介绍

    创建DynamicDataSource  

    public class DynamicDataSource  extends AbstractRoutingDataSource{
    
    
        /**
         * 返回值代表使用哪个Db
         * @return
         */
        @Override
        protected Object determineCurrentLookupKey() {
            return DataSourceContextHolder.getDBType();
        }
    }
    

      创建DataSourceContextHolder 

    public class DataSourceContextHolder {
    
        private static  final  ThreadLocal<String> CONTEXT_HOLDER = new ThreadLocal<>();
    
        public static  void setDBType(String dbType){
            CONTEXT_HOLDER.set(dbType);
        }
    
        public static  String getDBType(){
           return (String)  CONTEXT_HOLDER.get();
        }
    
        public static  void clearDBType(){
             CONTEXT_HOLDER.remove();
        }
    
    }
    

      

    5、创建代理类

    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){
            System.out.println("静态代理 before code");
    
            int userId = order.getUserId();
            int dbRouter = userId % 2;
            System.out.println("静态代理分配到【db" + dbRouter + "】处理数据");
    
            // TODO: 2020/1/27 设置dataSource
            DataSourceContextHolder.setDBType("db" + String.valueOf(dbRouter));
        }
    
        private void afterMethod(){
            System.out.println("静态代理 after code");
        }
    
    }
    

      

      

    6、测试

    public class Test {
    
    
        public static void main(String[] args) {
            Order order = new Order();
            order.setUserId(2);
            OrderServiceStaticProxy orderServiceStaticProxy = new OrderServiceStaticProxy();
            orderServiceStaticProxy.saveOrder(order);
        }
    }
    

      

    7、UML图如下

    8、输出结果如下

    静态代理 before code
    静态代理分配到【db0】处理数据
    静态代理 after code
    Service层调用Dao层添加Order
    Dao层添加Order成功
    

      

    动态代理实践(另外一个动态代理的例子Spring AOP原理

    1、创建动态代理类

    public class OrderServiceDynamicProxy  implements InvocationHandler{
    
        private Object target;
    
        public OrderServiceDynamicProxy(Object target){
            this.target = target;
        }
    
        public Object build(){
            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: 2020/1/27 设置dataSource
            DataSourceContextHolder.setDBType("db" + String.valueOf(dbRouter));
        }
    
    
        private void afterMethod(){
            System.out.println("动代理 after code");
        }
    }
    

      

    2、测试

    public class Test {
    
    
        public static void main(String[] args) {
            Order order = new Order();
            order.setUserId(2);
            IOrderService orderServiceDynamicProxy = (IOrderService)new OrderServiceDynamicProxy(new OrderServiceImpl()).build();
            orderServiceDynamicProxy.saveOrder(order);
        }
    }
    

      

    3、输出

    动态代理 before code
    动态代理分配到【db0】处理数据
    Service层调用Dao层添加Order
    Dao层添加Order成功
    动代理 after code
    

      

    代理模式在源码中的应用

    1、JDK中的java .lang.reflet.Proxy类

    2、Spring中的ProxyFactoryBean

     核心的方法为getObject()

     还有JdkDynamicAopProxy和CglibAopProxy

    3、Mybatis中

    MapperProxyFactory

  • 相关阅读:
    7.Pod控制器—Job&CronJob
    6.Pod控制器—DaemonSet
    5.Pod控制器—ReplicaSet&Deployment
    0.4kubeadm参数说明
    14.Open vSwitch实现跨主机的容器之间网络互联
    p1144_最短路计数问题
    vue在dom绑定点击事件后,同时将值和事件传递
    vue中使用lodash的throttle不生效解决方案
    vuecli3项目添加pwa支持
    flutter for web跨域解决方案
  • 原文地址:https://www.cnblogs.com/linlf03/p/12234735.html
Copyright © 2011-2022 走看看