JAVA 注解的框架封装

作者: 右耳菌 | 来源:发表于2022-04-18 01:04 被阅读0次

一、代理模式

代理模式(Proxy)为其他的对象提供一种代理,以控制对这个对象的访问。代理对象在客户端和目标对象之间起到中介的作用。

1. 代理模式的作用
  • 在某些情况下,一个客户类不想或者不能直接引用一个委托对象,而代理类对象可以在客户类和委托对象之间起到中介的作用,其特征是代理类和委托类实现相同的接口。
  • 代理类除了是客户类和委托类的中介之外,我们还可以通过给代理类增加额外的功能来扩展委托类的功能,这样做我们只需要修改代理类而不需要再修改委托类,符合代码设计的开闭原则。
图解代理模式
2. 静态代理

静态代理在使用时,需要定义接口或者父类,被代理对象与代理对象一起实现相同的接口或者是继承相同父类。

  • 一个例子
    1. 创建服务接口 GameFactory
    package cn.lazyfennec.proxydemo.service;
    
    public interface GameFactory {
    
        String make();
    
    }
    
    1. 创建Ps4GameFactory和GameBoyFactory实现GameFactory
    package cn.lazyfennec.proxydemo.real;
    
    import cn.lazyfennec.proxydemo.service.GameFactory;
    
    /**
     * @Author: Neco
     * @Description:
     * @Date: create in 2022/4/17 23:57
     */
    public class Ps4Factory implements GameFactory {
        @Override
        public String make() {
            return "ps4";
        }
    }
    
    package cn.lazyfennec.proxydemo.real;
    
    import cn.lazyfennec.proxydemo.service.GameFactory;
    
    /**
     * @Author: Neco
     * @Description:
     * @Date: create in 2022/4/18 0:08
     */
    public class GameBoyFactory implements GameFactory {
    
        @Override
        public String make() {
            return "game boy";
        }
    
    }
    
    1. 创建代理类NecoProxy
    package cn.lazyfennec.proxydemo.proxy;
    
    import cn.lazyfennec.proxydemo.service.GameFactory;
    
    /**
     * @Author: Neco
     * @Description:
     * @Date: create in 2022/4/18 0:04
     */
    public class NecoProxy implements GameFactory {
    
        GameFactory factory;
    
        public NecoProxy(GameFactory factory) {
            this.factory = factory;
        }
    
        @Override
        public String make() {
            doSomethingBefore();
            String make = factory.make();
            System.out.println(make);
            doSomethingAfter();
            return null;
        }
    
        // 售前服务
        private void doSomethingBefore() {
    
        }
    
        // 售后服务
        private void doSomethingAfter() {
    
        }
    
    }
    
    4、创建执行类
    package cn.lazyfennec.proxydemo.caller;
    
    import cn.lazyfennec.proxydemo.proxy.NecoProxy;
    import cn.lazyfennec.proxydemo.real.GameBoyFactory;
    import cn.lazyfennec.proxydemo.real.Ps4Factory;
    
    /**
     * @Author: Neco
     * @Description:
     * @Date: create in 2022/4/17 23:58
     */
    public class Tuhao {  
    
        public static void main(String[] args) { // 土豪要去购买,代理
    
            Ps4Factory ps4Factory = new Ps4Factory();
            NecoProxy necoProxy = new NecoProxy(ps4Factory);
            necoProxy.make();
    
            GameBoyFactory gameBoyFactory = new GameBoyFactory();
            necoProxy = new NecoProxy(gameBoyFactory);
            necoProxy.make();
        }  
    
    }
    
  • 静态代理总结
    1. 优点:不修改目标对象的功能前提下,对目标功能进行扩展。
    2. 缺点:因为代理对象需要与目标对象实现一样的接口,所以会有很多代理类被创建,类太多。同时一旦接口增加方法,目标与代理对象都要维护,增加维护成本。
3. 动态代理
  • 代理类在程序运行时创建的代理方式被称为动态代理。

  • 这种情况下,代理类并不是在Java代码中定义的,而是在运行时根据我们在Java代码中的“指示”动态生成的。

  • 要点

    • proxy 代理对象 - 由它分配代理对象
    • InvocationHandler 标准化的代购流程
  • 一个例子

    1. 创建服务接口 GameFactory,与静态代理一致
    2. 创建Ps4GameFactory和GameBoyFactory实现GameFactory,与静态代理一致
    3. 创建代理类NecoDynamicProxy
    package cn.lazyfennec.proxydemo.proxy;
    
    import java.lang.reflect.InvocationHandler;
    import java.lang.reflect.Method;
    import java.lang.reflect.Proxy;
    
    /**
     * @Author: Neco
     * @Description:
     * @Date: create in 2022/4/18 0:34
     */
    public class NecoDynamicProxy implements InvocationHandler {  
    
        public Object target; // 被代理的对象
    
        public Object getTarget() {
            return target;
        }
    
        public void setTarget(Object target) {
            this.target = target;
        }
    
        public Object getProxy() { // 我只负责与总公司联系,不再去接触具体的店铺
            return Proxy.newProxyInstance(
                    target.getClass().getClassLoader(), target.getClass().getInterfaces(), this);
        }
    
        @Override
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
            doSomethingBefore();
            Object invoke = method.invoke(target, args);
            System.out.println(invoke);
            doSomethingAfter();
            return null;
        }
    
        // 售前服务
        private void doSomethingBefore() {
            System.out.println("pay");
        }
    
        // 售后服务
        private void doSomethingAfter() {
            System.out.println("is ok");
        }
    }
    
    1. 创建执行类
    package cn.lazyfennec.proxydemo.caller;
    
    import cn.lazyfennec.proxydemo.proxy.NecoDynamicProxy;
    import cn.lazyfennec.proxydemo.real.Ps4Factory;
    import cn.lazyfennec.proxydemo.service.GameFactory;
    
    /**
     * @Author: Neco
     * @Description:
     * @Date: create in 2022/4/18 0:43
     */
    public class TuhaoDynamic {  
    
        public static void main(String[] args) {
            NecoDynamicProxy proxy = new NecoDynamicProxy();
            Ps4Factory ps4Factory = new Ps4Factory();
            proxy.setTarget(ps4Factory);
            GameFactory factory = (GameFactory) proxy.getProxy();
            factory.make();
        }
    
    }
    
4. 动态代理VS静态代理:
  • 静态代理类和委托类实现了相同的接口,代理类通过委托类实现了相同的方法。这样就出现了大量的代码重复。
  • 静态代理对象只服务于一种类型的对象,如果要服务多类型的对象。势必要为每一种对象都进行代理,静态代理在程序规模稍大时就无法胜任了。
5. 更高级的封装
  • 加入 Spring Aop 和 Ioc

相关文章

网友评论

    本文标题:JAVA 注解的框架封装

    本文链接:https://www.haomeiwen.com/subject/kyflertx.html