代理模式

大家可能会有这样的经历,想买某样国外商品,可自己又不能去国外,这时可能会找代购帮忙购买,你只需要将想买的东西告诉代购,由他去和国外商家购买,而你不需要直接和国外商家交流。类似的这种操作,在程序世界里,叫做代理模式

 

代理模式(Proxy Pattern):给某个对象提供一个代理,并且由代理对象控制对原对象的引用。代理模式是一种对象结构型模式

 

完成代理模式需要3个角色

抽象角色(Subject):声明了真实角色和代理角色的共同接口,客户端需要针对抽象角色进行编程

真实角色(RealSubject):定义了代理角色所代表的真实对象,实现了真实的业务

代理角色(Proxy):内部包含了对真实角色的引用,可以在引用的真实角色操作之前或之后进行其他操作,以达到增强的效果

 

代理模式可以根据代理类的创建时间分为静态代理和动态代理

代理类在程序运行前已经将代码编写在程序中,称为静态代理

代理类在程序运行时被创建,这种代理方式称为动态代理。在 java 中实现动态代理有两种方式,JDK 动态代理CGlib 动态代理

 

下面代码演示代理模式

静态代理

定义抽象角色

package com.design.structural.proxy.staticproxy;

/**
 * 抽象角色
 */
public interface Subject {

    void request();
}

定义真实角色

package com.design.structural.proxy.staticproxy;

/**
 * 真实角色
 */
public class RealSubject implements Subject{

    @Override
    public void request() {
        System.out.println("真实角色方法调用");
    }
}

定义代理角色

package com.design.structural.proxy.staticproxy;

/**
 * 代理角色
 */
public class Proxy implements Subject{

    private Subject subject;

    public Proxy(Subject subject) {
        this.subject = subject;
    }

    @Override
    public void request() {
        System.out.println("真实角色方法调用前操作");
        subject.request();
        System.out.println("真实角色方法调用后操作");
    }
}

 

类图如下

 

测试调用

package com.design.structural.proxy.staticproxy;

/**
 * 代理模式(静态代理)
 */
public class TestMain {

    public static void main(String[] args) {
        Subject subject = new RealSubject();
        Proxy proxy = new Proxy(subject);
        proxy.request();
    }
}

结果如下

 

 

动态代理

jdk 动态代理

定义抽象角色

package com.design.structural.proxy.dynamicproxy.jdkproxy;

/**
 * 抽象角色
 */
public interface Subject {

    void proxyMethod();
}

定义真实角色

package com.design.structural.proxy.dynamicproxy.jdkproxy;

/**
 * 真实角色
 */
public class RealSubject implements Subject{

    @Override
    public void proxyMethod() {
        System.out.println("被代理的方法执行");
    }
}

定义代理角色

package com.design.structural.proxy.dynamicproxy.jdkproxy;

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

/**
 * 代理角色
 */
public class JdkDynamicProxy implements InvocationHandler {

    private Subject subject;

    public JdkDynamicProxy(Subject subject) {
        this.subject = subject;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("被代理的方法执行前操作");
        Object obj = method.invoke(subject, args);
        System.out.println("被代理的方法执行后操作");
        return obj;
    }
}

 

类图如下

 

测试调用

package com.design.structural.proxy.dynamicproxy.jdkproxy;

import java.lang.reflect.Proxy;

/**
 * jdk动态代理
 */
public class TestMain {

    public static void main(String[] args) {
        Subject subject = (Subject) Proxy.newProxyInstance(
                TestMain.class.getClassLoader(),
                new Class[]{Subject.class},
                new JdkDynamicProxy(new RealSubject()));

        subject.proxyMethod();
    }
}

结果如下图

 

 

cglib 动态代理

定义真实角色

package com.design.structural.proxy.dynamicproxy.cglibproxy;

/**
 * 真实角色
 */
public class RealSubject {

    public void proxyMethod(){
        System.out.println("被代理的方法执行");
    }
}

定义代理角色

package com.design.structural.proxy.dynamicproxy.cglibproxy;

import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;
import java.lang.reflect.Method;

/**
 * 代理角色
 */
public class CglibDynamicProxy implements MethodInterceptor {

    @Override
    public Object intercept(Object obj, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
        System.out.println("被代理的方法执行前操作");
        Object res = methodProxy.invokeSuper(obj, args);
        System.out.println("被代理的方法执行后操作");
        return res;
    }
}

 

类图如下

 

测试调用

package com.design.structural.proxy.dynamicproxy.cglibproxy;

import net.sf.cglib.proxy.Enhancer;

/**
 * cglib动态代理
 */
public class TestMain {

    public static void main(String[] args) {
        Enhancer enhancer = new Enhancer();
        enhancer.setSuperclass(RealSubject.class);
        enhancer.setCallback(new CglibDynamicProxy());
        RealSubject realSubject = (RealSubject) enhancer.create();
        realSubject.proxyMethod();
    }
}

调用结果

 

 

如果读者想了解JDK 动态代理CGlib 动态代理的更多内容,可以参考下面两篇文章

JDK 动态代理:https://blog.csdn.net/wsjzzcbq/article/details/90116215

CGLIB 动态代理:https://blog.csdn.net/wsjzzcbq/article/details/90182495

 

 

代理模式总结:

优点:将代理对象与真实被调用的目标对象分离;降低系统耦合度;控制对一个对象的访问;增强目标对象

缺点:造成系统设计中类的数目增加;客户端和目标对象之间增加了代理对象,将导致请求处理速度变慢;增加系统复杂度

适用场景:需要控制一个对象的访问时;需要为一个对象提供额外的操作,以增强目标对象;

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

悟世君子

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值