设计模式之代理模式

设计模式之代理模式

定义

为其它对象提供一种代理,以控制对这个对象的访问。代理对象在客户端和目标对象之间起到中介的作用。

场景

1)保护目标对象
2)增强目标对象

分类

静态代理:

静态代理的原理是创建一个类来代理原始类,这个代理类与原始类实现相同的接口,并在其方法中调用原始类的方法,在其中可以添加额外的逻辑。

需要注意的是,静态代理在编译期间就已经确定了,每添加一个代理类,就需要手动创建一个新的代理类。这使得静态代理不太适合大规模或频繁使用代理的情况。

动态代理:

Java动态代理是基于Java的反射机制实现的。

它使用了两个关键类:Proxy 和 InvocationHandler。当调用Proxy.newProxyInstance()方法时,Java运行时会在内存中动态生成一个代理类,该代理类继承自指定接口,并在其中实现了指定接口的所有方法。生成的代理类会拦截对接口方法的调用,并将这些调用转发到InvocationHandler的invoke()方法中。在invoke()方法中,可以通过反射获取到被代理方法的相关信息,通过反射调用原始对象的方法。

需要注意的是,动态代理只能代理接口,而不能代理具体的类。这是由于代理类是继承自接口的,所以只能代理接口中的方法。如果需要代理具体的类,可以考虑使用其他的代理技术,如CGLib代理。

CGLib代理:

CGLib代理是一种基于继承的动态代理技术。它通过字节码技术创建目标类的一个子类来实现代理功能,然后重写或增加子类的方法来拦截对目标类方法的调用。

动态代理实现

1:我们定义一个接口 Animal:

public interface Animal {
    void makeSound();
}

2:创建一个实现该接口的类 Cat:

public class Cat implements Animal {
    @Override
    public void makeSound() {
        System.out.println("喵喵喵");
    }
}

3:建一个实现 InvocationHandler 接口的代理类 AnimalProxy,它将充当动态代理的中介:

public class AnimalProxy implements InvocationHandler {
    private Animal animal;

    public AnimalProxy(Animal animal) {
        this.animal = animal;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        // 在方法调用前进行一些操作
        System.out.println("调用前");

        // 调用实际对象的方法
        Object result = method.invoke(animal, args);

        // 在方法调用后进行一些操作
        System.out.println("调用后");

        return result;
    }
}

4:调用测试类:

public class Main {
    public static void main(String[] args) {
        // 创建真实对象
        Animal cat = new Cat();

        // 生成代理对象,这个对象实现了Animal接口,并且实现了Animal接口的所有方法
        Animal proxy = (Animal) Proxy.newProxyInstance(
                cat.getClass().getClassLoader(),
                cat.getClass().getInterfaces(),
                new AnimalProxy(cat)
        );

        // 调用代理对象的方法
        proxy.makeSound();
    }
}
CGLib代理实现

1:目标类

class TargetClass {
    public void doSomething() {
        System.out.println("TargetClass: Doing something");
    }
}

2:设置回调:通过实现MethodInterceptor接口来创建一个回调对象,并将其设置到Enhancer对象中。MethodInterceptor接口中的intercept()方法用于拦截对目标方法的调用。

// 方法拦截器
class MyMethodInterceptor implements MethodInterceptor {
    @Override
    public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
        // 在目标方法执行前进行操作
        System.out.println("Before method execution");

        // 调用目标方法
        Object result = proxy.invokeSuper(obj, args);

        // 在目标方法执行后进行操作
        System.out.println("After method execution");

        return result;
    }
}

3:调用,创建Enhancer对象:Enhancer是CGLib库中的一个类,它用于生成代理类。创建一个Enhancer对象,并设置目标类为其父类。

public static void main(String[] args) {
    // 创建Enhancer对象
    Enhancer enhancer = new Enhancer();
    // 设置目标类
    enhancer.setSuperclass(TargetClass.class);
    // 设置回调对象
    enhancer.setCallback(new MyMethodInterceptor());

    // 创建代理类
    TargetClass proxy = (TargetClass) enhancer.create();

    // 使用代理类调用目标方法
    proxy.doSomething();
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值