zoukankan      html  css  js  c++  java
  • Java代理之静态代理

    什么是代理

    代理就是给目标对象一个代理对象,并由代理对象控制目标的引用。

    为什么要使用代理模式

    1、通过引入代理对象的方式,可以间接的访问目标对象,避免直接访问目标对象给系统带来不必要的复杂性。
    2、通过代理对象可以对原有的业务进行业务增强处理。

    举例:如果我们需要买国外的某一件商品A,这个时候我们一般有两个途径要么直接去国外买,要么可以找一些代购人员帮我们去购买。在这种情况下,我们由于直接去国外买,实在是太耗软妹币,而且还要花时间等等,这个时候我们最优的选择就是找代购购买,这样也帮我们省去了很多麻烦的事情。

    代理模式类图

    代码示例

    抽象对象:

    public interface ITargetFactoryService {
    
        void sale(String name);
    }
    

    目标对象:

    @Slf4j
    public class TargetFactoryServiceImpl implements ITargetFactoryService {
    
        @Override
        public void sale(String name) {
            log.info(name+"购买了商品A");
        }
    }
    

    代理对象:

    @Slf4j
    public class ProxyImpl implements ITargetFactoryService {
    
        public ITargetFactoryService service;
    
        public ProxyImpl(ITargetFactoryService service){
            super();
            this.service = service;
        }
    
        @Override
        public void sale(String name) {
            before();
            service.sale("代购");
            after();
    
        }
    
        /**
         * 后置增强
         */
        private void after() {
            log.info("代购在购买后得到了市场调研结果");
        }
    
        /**
         * 前置增强
         */
        private void before() {
            log.info("代购在购买前做了市场调研");
        }
    }
    
    

    测试类:

    @Slf4j
    @SpringBootApplication(exclude = {DataSourceAutoConfiguration.class, DataSourceTransactionManagerAutoConfiguration.class, JdbcTemplateAutoConfiguration.class})
    public class SpsringJdbcApplication {
    
      public static void main(String[] args) {
        TargetFactoryServiceImpl service = new TargetFactoryServiceImpl();
        ProxyImpl proxy = new ProxyImpl(service);
        proxy.sale("代购");
        SpringApplication.run(SpsringJdbcApplication.class, args);
      }
    
    }
    

    测试结果:

    我们可以在代码示例中清晰的看到,在代理类中,代理对象包含了目标对象,并且在业务处理上进行了一定的业务扩展,但是却和目标对象继承于同一个接口。但是此扩展基于Spring AOP来讲,以更加专业的叫法为前置增强、后置增强。

    此类代理便是我们常说的静态代理,静态代理适合在业务比较简单,实现类少,需求变化不频繁,但是却要对原有目标服务对象功能进行扩展,并且不去修改原有服务,这个时候我们就可以选择使用静态代理。

    静态代理的缺点

    如果此时我们业务需要进行扩展,我们的代购同学在经过市场调研以后,发现商品B更加受大家欢迎,这个时候我们就需要对自己的业务进行扩展了,怎么扩展呢?一起接着往下看。

    抽象对象:

    public interface ITargetFactoryBService {
    
        void saleB(String name);
    }
    

    目标对象:

    
    @Slf4j
    public class ITargetFactoryBServiceImpl implements ITargetFactoryBService {
    
        @Override
        public void saleB(String name) {
            log.info(name + "购买了商品B");
        }
    }
    
    

    代理对象:

    @Slf4j
    public class ProxyTwoImpl implements ITargetFactoryService, ITargetFactoryBService {
    
        public ITargetFactoryService service;
    
        public ITargetFactoryBService bService;
    
        public ProxyTwoImpl(ITargetFactoryService service,ITargetFactoryBService bService){
            super();
            this.service = service;
            this.bService = bService;
        }
    
        @Override
        public void sale(String name) {
            before();
            service.sale("代购");
            after();
    
        }
    
        @Override
        public void saleB(String name) {
            before();
            bService.saleB("代购");
            after();
        }
    
        /**
         * 后置增强
         */
        private void after() {
            log.info("代购在购买后得到了市场调研结果");
        }
    
        /**
         * 前置增强
         */
        private void before() {
            log.info("代购在购买前做了市场调研");
        }
    
    
    }
    

    测试类:

    
    @Slf4j
    @SpringBootApplication(exclude = {DataSourceAutoConfiguration.class, DataSourceTransactionManagerAutoConfiguration.class, JdbcTemplateAutoConfiguration.class})
    public class SpsringJdbcApplication {
    
      public static void main(String[] args) {
        TargetFactoryServiceImpl service = new TargetFactoryServiceImpl();
        ITargetFactoryBServiceImpl bService = new ITargetFactoryBServiceImpl();
        ProxyTwoImpl proxy2 = new ProxyTwoImpl(service, bService);
        proxy2.sale("代购");
        proxy2.saleB("代购");
        SpringApplication.run(SpsringJdbcApplication.class, args);
      }
    
    }
    
    

    结果:

    我们可以看到,在实现业务扩展的时候,需要对原有的代理类进行修改,如果后期我们需要扩展的业务较多的时候,这个类将变的更加繁杂,大量的继承以及方法重写,以至于牵一发而动全身,所以在这种业务扩展性高、业务变化频繁的情况下我们不建议使用静态代理。

    静态代理总结:

    1、违反Java设计模式开闭原则,即:程序对外扩展开放,对修改关闭。当需求进行变更时,我们应该是新增代码块来实现,而不是在原来的代码中进行修改实现。
    2、扩展性很差。
    3、可维护性差。
    4、代码耦合度高。

    如果觉着不错可以关注公众号:Java秃头猿,专注于项目实际开发技术分享。

  • 相关阅读:
    QNET弱网测试工具
    echart
    数组按照一大一小打乱排列
    根据环境开启 vconsole
    时间戳在ios上面显示NAN Bug
    去除字符串中html标签
    ios 上 复选框背景黑边bug
    echarts配置项说明
    JS 数据处理技巧及小算法
    js中最常用的几种遍历数据方法
  • 原文地址:https://www.cnblogs.com/staticking/p/13628267.html
Copyright © 2011-2022 走看看