zoukankan      html  css  js  c++  java
  • 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();
        }
    }
    
  • 相关阅读:
    eclipse注释乱码的一个小问题
    《java 编程思想》 读书笔记 (一)
    《java 编程思想》 读书笔记 (一)
    055_SSM——sprinMVC的返回值
    054_jQuary——html()与text()方法的区别?
    053_Servlet——resp.getWrite()与resp.getPrint()的区别?
    052_html——html转环成jsp出现乱码的问题?
    051_html——checkbox的默认值与工作属性
    050_SSM——SpringMVCV中的各个器都起了什么作用?
    047_SSM——为什么返回String使用StringHttpMessageConverter解析时会造成乱码?
  • 原文地址:https://www.cnblogs.com/klvchen/p/15612335.html
Copyright © 2011-2022 走看看