您当前的位置: 首页 > 

white camel

暂无认证

  • 2浏览

    0关注

    442博文

    0收益

  • 0浏览

    0点赞

    0打赏

    0留言

私信
关注
热门博文

设计模式——代理设计模型

white camel 发布时间:2020-06-18 16:44:18 ,浏览量:2

在Spring中的相关介绍 https://blog.csdn.net/m0_37989980/article/details/104593905

具体什么是静态代理、动态代理这里不赘述, 可以参考上面 !

一、静态代理
/**
 * Description: 传统静态代理的举例
 * 

* 特点: 代理类和被代理类在编译期间, 就确定下来了 * * @author zygui * @date Created on 2020/6/18 15:12 */ interface ClothFactory { void produceCloth(); } // 代理类 class ProxyClothFactory implements ClothFactory { private ClothFactory factory; // 用被代理对象进行实例化(真实类) public ProxyClothFactory(ClothFactory factory) { this.factory = factory; } @Override public void produceCloth() { System.out.println("代理工厂准备一些工作..."); factory.produceCloth(); // 被代理类干的事情 System.out.println("代理工厂做一些后续的收尾工作..."); } } // 被代理类 class NikeClothFactory implements ClothFactory { @Override public void produceCloth() { System.out.println("Nike工厂生产一批运动服"); } } public class StaticProxyTest { public static void main(String[] args) { // 创建被代理对象 ClothFactory nike = new NikeClothFactory(); // 创建代理类对象 ClothFactory proxy = new ProxyClothFactory(nike); // 代理类执行的工作,实际是被代理类干的事情 proxy.produceCloth(); } }

总结: 代理类被代理类(委托类/真实类) 实现同一个接口, 代理类中包含被代理类, 当调用代理类执行相应的操作方法时, 执行的是被代理类(真实类)中的方法;

代理类在运行前就已经和被代理类的关系就确定了;

二、动态代理

想要实现动态代理, 需要解决的问题?

  • 问题一: 如何根据加载到内存中被代理类, 动态的创建一个代理类及其对象
  • 问题二: 当通过代理类的对象调用方法时, 如何动态的去调用被代理类中的同名方法
/**
 * Description: 动态代理的举例
 *
 *      代理类和被代理类要实现同一接口!
 *
 * @author zygui
 * @date Created on 2020/6/18 15:39
 */

interface Human {

    String getBelief();

    void eat(String food);

}

// 被代理类
class SuperMan implements Human {

    @Override
    public String getBelief() {
        return "I believe I can fly!";
    }

    @Override
    public void eat(String food) {
        System.out.println("我喜欢吃" + food);
    }
}

/*
    想要实现动态代理, 需要解决的问题?
    问题一: 如何根据加载到内存中被代理类, 动态的创建一个代理类及其对象
    问题二: 当通过代理类的对象调用方法时, 如何动态的去调用被代理类中的同名方法
 */

// 生产代理类的工厂
class ProxyFactory {

    /**
     * 调用此方法,通过传递过来的被代理类对象, 返回一个该被代理类对象的代理对象; 解决问题一
     *
     * @param obj 被代理类的对象
     * @return
     */
    public static Object getProxyInstance(Object obj) {

        /*
            // 用来创建代理类的方法
            public static Object newProxyInstance(
                  ClassLoader loader,      // 和被代理类使用同一加载器
                  Class[] interfaces,   // 因为代理类和被代理类要实现同一接口, 这里获取被代理类所实现的接口, 供创建出来的代理类也实现这些接口
                  InvocationHandler h      // 解决上面的问题二: 会去找下面的Invoke方法
            )

            也就是说, 创建的代理类对象去调用a方法时, 被代理类就会去handler里面调用invoke方法
         */
        MyInvocationHandler handler = new MyInvocationHandler();

        handler.bind(obj);

        return Proxy.newProxyInstance(obj.getClass().getClassLoader(), obj.getClass().getInterfaces(), handler);
    }

}

class MyInvocationHandler implements InvocationHandler {

    // 声明一个被代理对象
    private Object obj;     // 赋值时, 也需要使用具体的被代理对象进行赋值

    public void bind(Object obj) {
        this.obj = obj;
    }

    // 当我们通过代理类对象,调用方法a时, 就会自动的调用如下的方法: invoke(), 在invoke方法中的参数Method就是代理类对象调用的方法对象
    // 将被代理类要执行的方法a的功能就声明在invoke()中了
    @Override
    /*
        参数:
            Object proxy    :   代理类对象
            Method method   :   代理类调用的那个方法,这里就是该方法
            Object[] args   :   代理类调用的那个方法中的参数
     */
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {

        // method: 即为 代理类对象调用的方法, 此方法也就作为了 被代理类对象 要调用的方法
        // 下面的invoke方法中的 参数1: 调用该方法的对象(这里就是被代理类的对象), 参数2: 是调用该方法的参数
        Object retrunValue = method.invoke(obj, args);
        return retrunValue;
    }
}

public class DynamicProxyTest {
    public static void main(String[] args) {

        // 被代理类对象
        SuperMan superMan = new SuperMan();

        // proxyInstance代理类对象(此时是superMan的代理对象)
        Human proxyInstance = (Human) ProxyFactory.getProxyInstance(superMan);

        // 通过代理类对象调用下面的方法, 就动态调用了被代理类中的同名方法
        String belief = proxyInstance.getBelief();
        System.out.println(belief);
        proxyInstance.eat("四川麻辣烫");

    }
}

此时通过调用代理类中的方法, 就动态的调用的是被代理类中的同名方法了!

总结:

  • 创建一个生产代理类的一个工厂类, public static Object getProxyInstance(Object obj) {, obj就是被代理对象, 根据被代理对象创建一个其代理类; 通过Proxy.newProxyInstance(obj.getClass().getClassLoader(), obj.getClass().getInterfaces(), handler);方法来创建代理类;
  • 上面参数3对象, 需要实现InvocationHandler, 重写invoke方法, 该方法中的参数就已经是代理类对象, 已经代理类调用的方法, 方法参数;
  • method.invoke(obj, args); 此时通过反射, 将被代理类的对象传递过来, 已经参数, 实现 调用代理类的方法, 实际是调用被代理类的方法
关注
打赏
1661428283
查看更多评论
立即登录/注册

微信扫码登录

0.0389s