代理模式

本文深入探讨了代理模式在软件设计中的应用,包括静态代理和动态代理的实现方式,以及JDK动态代理和CGLIB动态代理的具体操作。通过实例,详细解释了如何在不同场景下使用代理模式来增强方法,实现对方法的拦截和特殊需求的适应。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

背景

代理模式的主要作用是为其他对象提供一种代理以控制对这个对象的访问。在某些情况下,一个对象不想或者不能直接引用另一个对象,而代理对象可以在客户端和目标对象之间起到中介的作用。

在实际应用中对用于对调用的方法进行拦截然后将方法增强以适应各种特殊的需求场景!!

代理分为静态代理和动态代理,区分就是静态代理是编译时就生成的,而动态代理是运行时生成的!!这里主要是看需要,没有绝对的好坏,静态代理速度快,而动态代理灵活!!

静态代理

简单的说就是让代理类也去实现被代理类的接口!!换句话说被代理的对象和代理类都实现了同一个接口,然后对这个接口定义的方法进行增强。
下面是通用框架:

//被代理的公共接口
interface Subject {
	// 定义了一个方法
	public void request();
}
 
//被代理对象
class RealSubject implements Subject {
	// 实现方法
	public void request() {
		// 业务处理
	}
}
 
//代理类
class Proxy implements Subject {
	// 要代理哪个实现类
	private Subject subject = null;
 
 
	public Proxy(Subject subject) {
		this.subject = subject
	}
 
	// 实现接口中定义的方法
	public void request() {
		this.before();
		this.subject.request();
		this.after();
	}
	// 增强处理
	private void before() {
		// do something
	}
	// 增强处理
	private void after() {
		// do something
	}
}

实现

定义一个"吃"的接口,现在对这个接口代理一下,增强”吃“方法,比如洗手洗碗。。。。下面是代理结构:
在这里插入图片描述

public interface IEat {
    void eat();
}
public class EatImpl implements IEat {
    @Override
    public void eat() {
        System.out.println("我要吃!!");
    }
}
public class Proxy implements IEat {
    private IEat proxyObject;

    public Proxy(IEat proxyObject){
        this.proxyObject=proxyObject;
    }
    @Override
    public void eat() {
        eatbefore();
        proxyObject.eat();
        eatafter();
    }
	//增强方法
    private void eatafter() {
        System.out.println("去洗碗筷!!");
    }
    private void eatbefore() {
        System.out.println("先洗手!!");
    }
}

最后调用实现类:

public class StaticProxyTest {
    public static void main(String[] args) {
        IEat proxyedObject=new EatImpl();
        Proxy proxy = new Proxy(proxyedObject);
        proxy.eat();
    }
}

在这里插入图片描述

动态代理

Java动态代理机制中有两个重要的类和接口InvocationHandler(接口)和Proxy(类),这一个类Proxy和接口InvocationHandler是我们实现动态代理的核心,利用反射机制生成一个实现代理接口的匿名类。
这里自己的注意的是:JDK动态代理只能代理实现了接口的类,没有实现接口的类是不能实现JDK动态代理。

实现

还是上面的吃的例子,下面是代理结构:
在这里插入图片描述
IEat和EatImpl是没有变,下面就是jdk代理的核心:

public class JdkProxy implements InvocationHandler {
    private Object obj;
    public JdkProxy(Object obj){
        this.obj=obj;
    }
    //通过Proxy类利用反射机制创建了这个代理类
    public Object create(){
        return Proxy.newProxyInstance(getClass().getClassLoader(),obj.getClass().getInterfaces(),this);
    }
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        eatbefore();
        Object invoke = method.invoke(obj, args);
        eatafter();
        return invoke;
    }
    //增强方法
    private void eatafter() {
        System.out.println("去洗碗筷!!");
    }

    private void eatbefore() {
        System.out.println("先洗手!!");
    }
}

在这里插入图片描述

cglib动态代理

用它就可以实现代理没有实现接口的类,其原理就是继承被代理类然后生成被代理类的子类,最终增强方法。既然是继承类实现的话,就不适用与final修饰类的情况,因为无法继承。
废话不多说,看实现。。。

实现

现在没有”吃“这个接口了,我们可以直接代理Eat类:

public class Ea{
    public void eat() {
        System.out.println("我要吃!!!");
    }
}
public class CglibProxy implements MethodInterceptor {
    private Object obj;

    public CglibProxy(Object obj){
        this.obj=obj;
    }
    //通过Enhancer类生成被代理类的子类
    public Object create(){
        Enhancer enhancer = new Enhancer();
        enhancer.setSuperclass(obj.getClass());
        //设置回调,当调用方法时,回调重写的intercept方法
        enhancer.setCallback(this);
        return enhancer.create();
    }

    @Override
    public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
        eatbefore();
        Object invoke = method.invoke(obj, objects);
        eatafter();
        return invoke;
    }
    private void eatafter() {
        System.out.println("去洗碗筷!!");
    }

    private void eatbefore() {
        System.out.println("先洗手!!");
    }
}

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值