• 设计模式-代理模式


    代理模式

    应用场景:不该变源代码,给源代码增加功能。

    在Java中,常用的代理有JDK动态代理和cglib动态代理。JDK动态代理由java.lang.reflect包下的Proxy提供的,基于接口生成的代理类,实现对目标类的代理;cglib是由Oracle提供的Java开发工具包,采用字节码技术,直接修改字节码并生成代理子类。
    注意:JDK动态代理中,调用方法时其代理类并不知道目标类的具体方法,因此需要通过反射来进行调用,效率很低。

    JDK实现动态代理

    public class Person implements IPerson {
        @Override
        public void eat(){
            System.out.println("开始吃饭");
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    1.定义接口,定义需要代理的方法

    public interface IPerson {
        public void eat();
    }
    
    • 1
    • 2
    • 3

    2.定义类并创建代理对象

        public static IPerson createPersonProxy(Person person){
            IPerson iPersonProxy = (IPerson) Proxy.newProxyInstance(PersonProxy.class.getClassLoader()
                    , new Class[]{IPerson.class}
                    , new InvocationHandler() {
                        @Override
                        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                            if(method.getName() == "eat"){
                                System.out.println("拿筷子");
                                System.out.println("拿碗");
                            }
    
                            return method.invoke(person ,args);
                        }
                    });
            return iPersonProxy;
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    3.调用代理对象的方法

    public class Demo {
        public static void main(String[] args) {
            Person person = new Person();
            IPerson personProxy = PersonProxy.createPersonProxy(person);
            personProxy.eat();
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    CGLIB实现动态代理

    public class Person{
        public void eat(){
            System.out.println("开始吃饭");
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    public class PersonProxy implements MethodInterceptor {
        private Enhancer enhancer = new Enhancer();
    
        public Object getProxy(Class clazz){
            enhancer.setSuperclass(clazz);
            enhancer.setCallback(this);
            //通过字节码技术动态创建子类实例
            return enhancer.create();
        }
    
        @Override
        public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
            if(method.getName().equals("eat")){
                System.out.println("拿筷子");
                System.out.println("拿碗");
            }
    
            //通过代理类调用父类中的方法
            Object result = methodProxy.invokeSuper(o, objects);
    
            return result;
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
  • 相关阅读:
    最少刷题数
    ATtiny88初体验(七):TWI
    failed to create symbolic link ‘/usr/bin/mysql’: File exists
    认识java
    Springboot建筑造价师资格考试应试网站毕业设计源码260839
    C语言开发过程中段错误处理方法之经典
    Kubernetes基础概念及架构和组件
    教程图文详解 - 无线通信网(第五章)
    Android的亮灯逻辑辨析
    arm-linux gdb远程调试
  • 原文地址:https://blog.csdn.net/qq_52763385/article/details/132752408