Java代理模式

静态代理

代理类,代理对象在编译期生成

动态代理

代理类,代理对象在运行时生成
动态代理有JDK和CGLIB两种

public interface SellTickets { void sell(); }
// 火车站
public class TrainStation implements SellTickets{
    public void sell() { System.out.println("火车站卖票"); }
}
// 代售点
// 代理对象和目标对象实现同样的接口
// 代理对象中维护了目标对象的引用
// 代理对象调用相应方法时,实际调用了目标对象的那个方法,只不过可能会在之前或之后做一些处理
public class ProxyPoint implements SellTickets{
    private TrainStation trainStation = new TrainStation();
    public void sell(){
        System.out.println("代售点收取一些服务费用");
        trainStation.sell();// 最终还是火车站\目标对象卖票,只不过代售点可能会在之前或之后做一些处理
    }
}
// 通过代理对象来买票
public static void main(String[] args) {
    ProxyPoint proxyPoint = new ProxyPoint();
    proxyPoint.sell();
}

JDK动态代理

public static void main(String[] args) {
    SellTickets proxy = getProxyObject(); // class com.sun.proxy.$Proxy0
    proxy.sell();
}
private static SellTickets getProxyObject(){
    // 目标对象
    TrainStation station = new TrainStation();
    // 代理对象
    SellTickets proxy = (SellTickets)Proxy.newProxyInstance(
            station.getClass().getClassLoader(),// 类加载器
            station.getClass().getInterfaces(),// 实现的接口
            new InvocationHandler() { // InvocationHandler接口的匿名实现类的对象
                /**
                 * @param proxy: 代理对象proxy自己, 在invoke方法中基本不用
                 * @param method: 代理对象proxy调用的那个方法,比如上面调用的sell方法
                 * @param args: 代理对象调用方法时,传的参数
                 * @return: 代理对象proxy调用的那个方法的返回值
                 */
                @Override
                public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                    System.out.println("代售点收取一定的服务费用(JDK动态代理)");
                    // 调用目标对象的对应方法
                    Object returnValue = method.invoke(station, args);
                    return returnValue;
                }
            }
    );
    return proxy;
}

运行时生成的,内存中的代理类$Proxy0

package com.sun.proxy;

import cn.Code.SellTickets;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
// 目标类和代理类都实现了同样的接口
public final class $Proxy0 extends Proxy implements SellTickets {
    private static Method m3;
    // InvocationHandler的实现类对象,在创建代理对象时已提供
    public $Proxy0(InvocationHandler var1) throws  {
		super(var1);
    }
    // invoke方法的逻辑,在创建代理对象时已提供
    public final void sell() throws  {
		super.h.invoke(this, m3, (Object[])null);
    }
    static {
		m3 = Class.forName("cn.Code.SellTickets").getMethod("sell");
    }
}

将运行时,内存中生成的代理类$Proxy0保存到磁盘中

// main方法的第一行加上这个,可以将内存中生成的代理类保存为class文件
System.setProperty("jdk.proxy.ProxyGenerator.saveGeneratedFiles", "true");
// 或者可以考虑使用下面命令,在UI端中操作
jhsdb hsdb

CGLIB动态代理

如果没有SellTickets接口,只有TrainStation类,这个时候使用CGLIB代理

<dependency>
    <groupId>cglib</groupId>
    <artifactId>cglib</artifactId>
    <version>2.2.2</version>
</dependency>
// 火车站(目标类)
public class TrainStation{
    // 如果sell方法在目标类中是final或private的,代理类中不会有sell方法
    // (protected,public,default), 且不是final, 代理类中才会有增强的sell方法
    // final:此时调用的是目标类中的sell方法,代理类中没有,不会有增强效果
    // private:只能在目标类内部调用
    public void sell() {
        System.out.println("火车站卖票");
    }
}
public static void main(String[] args) {
	// cn.Code.TrainStation$$EnhancerByCGLIB$$e0808941
    TrainStation proxy = getProxyObject();
    proxy.sell();
}
private static TrainStation getProxyObject(){
    // 目标对象
    TrainStation station = new TrainStation();

    Enhancer enhancer = new Enhancer();
    enhancer.setSuperclass(TrainStation.class);//指定父类
    enhancer.setCallback(new MethodInterceptor() {//设置CallBack
        public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
            System.out.println("代售点收取一定的服务费用(CGLIB代理)");
            Object returnValue = method.invoke(station, objects);
            return returnValue;
        }
    });

    // 代理对象
    TrainStation proxy = (TrainStation) enhancer.create();
    return proxy;
}

运行时,生成的代理类TrainStation$$EnhancerByCGLIB$$e0808941

package cn.Code;
import java.lang.reflect.Method;
import net.sf.cglib.core.ReflectUtils;
import net.sf.cglib.core.Signature;
import net.sf.cglib.proxy.Callback;
import net.sf.cglib.proxy.Factory;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;
public class TrainStation$$EnhancerByCGLIB$$e0808941 extends TrainStation implements Factory {
    private boolean CGLIB$BOUND;
    private static final ThreadLocal CGLIB$THREAD_CALLBACKS;
    private static final Callback[] CGLIB$STATIC_CALLBACKS;
    private MethodInterceptor CGLIB$CALLBACK_0;
    private static final Method CGLIB$sell$0$Method;
    private static final MethodProxy CGLIB$sell$0$Proxy;
    private static final Object[] CGLIB$emptyArgs;

    public TrainStation$$EnhancerByCGLIB$$e0808941() {
        CGLIB$BIND_CALLBACKS(this);
    }
    // 设置CGLIB$CALLBACK_0
    private static final void CGLIB$BIND_CALLBACKS(Object var0) {
        TrainStation$$EnhancerByCGLIB$$e0808941 var1 = (TrainStation$$EnhancerByCGLIB$$e0808941)var0;
        if (!var1.CGLIB$BOUND) {
            var1.CGLIB$BOUND = true;
            Object var10000 = CGLIB$THREAD_CALLBACKS.get();
            if (var10000 == null) {
                var10000 = CGLIB$STATIC_CALLBACKS;
                if (var10000 == null) {
                    return;
                }
            }
            var1.CGLIB$CALLBACK_0 = (MethodInterceptor)((Callback[])var10000)[0];
        }
    }
    static {
        CGLIB$THREAD_CALLBACKS = new ThreadLocal();
        CGLIB$emptyArgs = new Object[0];
        Class var0 = Class.forName("cn.Code.TrainStation$$EnhancerByCGLIB$$e0808941");
        Class var1;
        CGLIB$sell$0$Method = ReflectUtils.findMethods(new String[]{"sell", "()V"}, (var1 = Class.forName("cn.Code.TrainStation")).getDeclaredMethods())[0];
        CGLIB$sell$0$Proxy = MethodProxy.create(var1, var0, "()V", "sell", "CGLIB$sell$0");
    }
    public Object newInstance(Callback[] var1) {
        CGLIB$THREAD_CALLBACKS.set(var1);// 设置CallBack
        TrainStation$$EnhancerByCGLIB$$e0808941 var10000 = new TrainStation$$EnhancerByCGLIB$$e0808941();
        CGLIB$THREAD_CALLBACKS.set((Callback[])null);// 清空CallBack
        return var10000;
    }
	// 当目标类中sell方法为protected或public或default,且不为final时,代理类中才会有这个方法
    public final void sell() {
        MethodInterceptor var10000 = this.CGLIB$CALLBACK_0;
        if (var10000 == null) {
            CGLIB$BIND_CALLBACKS(this);
            var10000 = this.CGLIB$CALLBACK_0;
        }
        if (var10000 != null) {
        	// 增强逻辑
            var10000.intercept(this, CGLIB$sell$0$Method, CGLIB$emptyArgs, CGLIB$sell$0$Proxy);
        } else {
            super.sell();
        }
    }
    final void CGLIB$sell$0() {
        super.sell();
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Java代理模式是一种结构型设计模式,其目的是为其他对象提供一种代理以控制对这个对象的访问。代理对象可以在客户端和目标对象之间充当中介,以便于客户端访问目标对象时,可以在不改变目标对象的情况下添加一些额外的功能,比如安全性、远程访问、缓存等。 在Java中,代理模式可以通过两种方式实现:静态代理和动态代理。静态代理需要手动编写代理类,而动态代理可以在运行时通过反射机制动态生成代理类,更加灵活。 举个例子,假设我们有一个接口`Subject`,其中定义了一些方法。我们希望在调用这些方法时,增加一些额外的日志记录功能。我们可以编写一个代理类`SubjectProxy`,在代理类中实现接口方法并调用目标对象的方法,同时在方法前后添加日志记录的代码。客户端则通过代理类访问目标对象。 静态代理示例代码如下: ```java public interface Subject { void doSomething(); } public class RealSubject implements Subject { @Override public void doSomething() { System.out.println("RealSubject do something."); } } public class SubjectProxy implements Subject { private Subject realSubject; public SubjectProxy(Subject realSubject) { this.realSubject = realSubject; } @Override public void doSomething() { System.out.println("Before do something."); realSubject.doSomething(); System.out.println("After do something."); } } public class Client { public static void main(String[] args) { Subject realSubject = new RealSubject(); Subject subjectProxy = new SubjectProxy(realSubject); subjectProxy.doSomething(); } } ``` 动态代理示例代码如下: ```java public class SubjectHandler implements InvocationHandler { private Object target; public SubjectHandler(Object target) { this.target = target; } @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { System.out.println("Before " + method.getName()); Object result = method.invoke(target, args); System.out.println("After " + method.getName()); return result; } } public class Client { public static void main(String[] args) { Subject realSubject = new RealSubject(); InvocationHandler handler = new SubjectHandler(realSubject); Subject subjectProxy = (Subject) Proxy.newProxyInstance(realSubject.getClass().getClassLoader(), realSubject.getClass().getInterfaces(), handler); subjectProxy.doSomething(); } } ``` 无论是静态代理还是动态代理,代理模式都可以在不改变目标对象的情况下,为其添加额外的功能,提高代码的可复用性和灵活性。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值