• Java 基础 (反射的应用:动态代理)


    代理设计模式的原理:

    使用一个代理将对象包装起来,然后用该代理对象取代原始对象。任何对原始对象的调用都要通过代理。代理对象决定是否以及何时将方法调用转到原始对象上。

    动态代理是指客户通过代理类来调用其它对象的方法,并且是在程序运行时根据需要动态创建目标类的代理对象。

    动态代理使用场合:

    1.调试
    2.远程方法调用

    动态代理相比于静态代理的优点:

    抽象角色中(接口)声明的所有方法都被转移到调用处理器一个集中的方法中处理,这样,我们可以更加灵活和统一的处理众多的方法。

    动态代理与AOP (Aspect Orient Programming)

    StaticProxyTest.java

    package com.klvchen.java;
    
    /*
      静态代理举例
      特点:代理类和被代理类在编译期间,就确定下来了。
     */
    
    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) {
            //创建被代理类的对象
            NikeClothFactory nike = new NikeClothFactory();
            //创建代理类的对象
            ProxyClothFactory proxyClothFactory = new ProxyClothFactory(nike);
    
            proxyClothFactory.produceCloth();
        }
    }
    

    ProxyTest.java

    package com.klvchen.java;
    
    
    import java.lang.reflect.InvocationHandler;
    import java.lang.reflect.Method;
    import java.lang.reflect.Proxy;
    
    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 HumanUtil{
        public void method1(){
            System.out.println("========================== 通用方法一 ==========================");
        }
    
        public void method2(){
            System.out.println("========================== 通用方法二 ==========================");
        }
    }
    
    /*
    要想实现动态代理,需要解决的问题?
    问题一:如何根据加载到内存中的被代理类,动态的创建一个代理类及其对象。
    问题二:当通过代理类的对象调用方法时,如何动态的去调用被代理类中的同名方法。
    
     */
    class ProxyFactory {
    
        // 调用此方法,返回一个代理类的对象。解决问题一
        public static Object getProxyInstance(Object obj) { //obj: 被代理类对象
    
            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()
        //将被代理类要执行的方法a的功能就声明在invoke()中
        @Override
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
    
            HumanUtil util = new HumanUtil();
            util.method1();
    
            //method:即为代理类对象调用的方法,此方法也就作为了被代理类对象要调用的方法
            //obj:被代理类的对象
            Object returnValue = method.invoke(obj, args);
    
            util.method2();
    
            //上述方法的返回值就作为当前类中的invoke()的返回值。
            return returnValue;
        }
    }
    
    public class ProxyTest {
    
        public static void main(String[] args) {
            SuperMan superMan = new SuperMan();
            //proxyInstance:代理类的对象
            Human proxyInstance = (Human) ProxyFactory.getProxyInstance(superMan);
            //当通过代理类对象调用方法时,会自动的调用被代理类中同名的方法
            proxyInstance.getBelief();
            proxyInstance.eat("四川麻辣烫");
    
            System.out.println("*****************************************");
    
            NikeClothFactory nikeClothFactory = new NikeClothFactory();
    
            ClothFactory proxyClothFactory = (ClothFactory) ProxyFactory.getProxyInstance(nikeClothFactory);
    
            proxyClothFactory.produceCloth();
        }
    }
    
  • 相关阅读:
    w3wp.exe占用CPU100%的解决办法
    Visual Studio 2005 查找和替换窗口 显示不了
    IIS:w3wp.exe进程占用cpu和内存过多的处理办法
    C# form ComboBox
    从尾到头打印链表,不允许逆置原链表
    [置顶] ATL窗口thunk机制的剖析与实现
    flex自定义用ArrayCollection做数据源的带checkbox的tree(功能强大的完美版^_^)
    oracle的PremaredStatement.executeBatch为什么返回2
    窗体Controls的OfType<>方法的使用
    HDU 1421 动态规划(DP) 搬寝室
  • 原文地址:https://www.cnblogs.com/klvchen/p/15612335.html
Copyright © 2020-2023  润新知