(12)代理模式

概念

对一个对象生成一个新的代理对象,代理对象具备原对象的功能,且能对原对象的功能进行增强。很像装饰模式,但是装饰模式只是把对象的某个方法进行增强,而代理模式把整个对象的所有方法都增强。

例如:每个人都会睡午觉,也会睡晚觉。我现在希望每个人睡午觉的前后都刷牙,睡晚觉的前后也都刷牙

实现方式

JDK代理

对目标类的接口生成代理类,代理类中会保存目标类的对象,代理类在调用目对象的方法前后能做一些操作,比如记录目标类的方法执行时间

使用JDK代理时,目标类必须有接口,否则不能使用JDK代理

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

/**
 * JDK代理。被代理的类必须实现接口
 */
public class Demo {
    public static void main(String[] args) {
        Person person = (Person) Proxy.newProxyInstance(Student.class.getClassLoader(), new Class[]{Person.class}, new InvocationHandler() {
            @Override
            public Object invoke(Object o, Method method, Object[] objects) throws Throwable {
                System.out.println("睡觉前先刷牙");
                Object result = method.invoke(new Student(), objects);
                System.out.println("睡醒后也要刷牙");
                return result;
            }
        });
        person.noonSleep();
        System.out.println("===========");
        person.nightSleep();
    }
}

interface Person {
    void noonSleep();
    void nightSleep();
}

// 被代理的类必须实现接口,否则无法使用JDK代理
class Student implements Person {
    public void noonSleep() {
        System.out.println("中午睡觉");
    }

    @Override
    public void nightSleep() {
        System.out.println("晚上睡觉");
    }
}

睡觉前先刷牙
中午睡觉
睡醒后也要刷牙
===========
睡觉前先刷牙
晚上睡觉
睡醒后也要刷牙

cglib 代理

对目标类生成代理类,其实代理类就是目标类的子类。代理类由于继承了目标类,所以代理类可以在调用目标类方法的前后做一些操作,比如记录目标类的方法执行时间

使用CGLIB代理时,目标类可以不用实现某个接口

先引入cglib包

<dependency>
    <groupId>cglib</groupId>
    <artifactId>cglib</artifactId>
    <version>3.3.0</version>
</dependency>
import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;

import java.lang.reflect.Method;

/**
 * CGLIB代理。被代理的类可以不实现接口
 */
public class Demo {
    public static void main(String[] args) {
        Enhancer enhancer = new Enhancer();
        enhancer.setSuperclass(Student.class);
        enhancer.setCallback(new MethodInterceptor() {
            @Override
            public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
                System.out.println("睡觉前先刷牙");
                Object result = method.invoke(new Student(), objects);
                System.out.println("睡醒后也要刷牙");
                return result;
            }
        });

        Student s = (Student) enhancer.create();
        s.noonSleep();
        System.out.println("===========");
        s.nightSleep();
    }
}

// 不实现接口也能代理
class Student {
    public void noonSleep() {
        System.out.println("中午睡觉");
    }

    public void nightSleep() {
        System.out.println("晚上睡觉");
    }
}

睡觉前先刷牙
中午睡觉
睡醒后也要刷牙
===========
睡觉前先刷牙
晚上睡觉
睡醒后也要刷牙

posted @ 2021-11-30 17:45  、嘎路的米。  阅读(36)  评论(0)    收藏  举报