Java编程之动态代理

本文深入探讨了Java中两种动态代理的实现方式:JDK动态代理和CGLIB动态代理。通过具体示例展示了如何使用这两种代理来实现代理模式,并介绍了它们的工作原理。

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

代理:在实例的方法执行之前,由代理插入一段执行代码,然后调用实例的方法,之后也可以插入一段代码。这是AOP编程的核心。

在Java中实现动态代理有两种方式:
★ JDK动态代理 – 应用于代理实现了接口的类
★ cglib动态代理 – 主要应用于代理普通类(未实现接口)

先说说JDK动态代理
JDK动态代理主要依靠JavaAPI中的Proxy类,这个类中有个重要的方法

static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h) 

Returns an instance of a proxy class for the specified interfaces that dispatches method invocations to the specified invocation handler.
这是这个方法的英文解释,供参考。
对上面的方法做个理解:
ClassLoader loader 类加载器,加载被代理类的字节码。
Class<?>[] interfaces 被代理类实现的接口,代理类要和被代理类有相同的行为
InvocationHandler h 指定如何代理, 用到策略设计模式

案例一

//接口
public interface Human {
    void sing(float money);
    void dance(float money);
}
//实现类
public class SpringBrother implements Human {

    public void sing(float money) {
        System.out.println("拿到:"+money+" 元开始唱歌");
    }

    public void dance(float money) {
        System.out.println("拿到:"+money+" 元开始跳舞");
    }

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

public class Client1 {

    public static void main(String[] args) {
        final Human sb = new SpringBrother();

        //产生代理类,得到他的实例
        Human proxyMan = (Human)Proxy.newProxyInstance(sb.getClass().getClassLoader(), 
                sb.getClass().getInterfaces(), 
                new InvocationHandler() {

                    @Override
                    public Object invoke(Object proxy, Method method, Object[] args)
                            throws Throwable {

                        if("sing".equals(method.getName())){
                            //唱歌
                            float money = (Float)args[0];
                            if(money>10000){
                                method.invoke(sb, money/2);
                            }
                        }

                        if("dance".equals(method.getName())){
                            //唱歌
                            float money = (Float)args[0];
                            if(money>20000){
                                method.invoke(sb, money/2);
                            }
                        }
                        return null;
                    }
                }
        );
        proxyMan.sing(20000);
        proxyMan.dance(100000);
    }

}
运行结果:
   拿到钱:10000.0开唱
   拿到钱:50000.0开跳

InvocationHandler是调用处理程序,每个代理类都对应一个调用处理程序
它是个接口,里面只有一个invoke()方法,每个类对其都有不同的实现,用到了策略设计模式

Object invoke(Object proxy, Method method, Object[] args)

Object proxy 对被代理对象的引用。
Method method 调用了被代理对象的哪个方法
Object[] args 当前方法用到的参数,没有则为null

再一个就是cglib动态代理

案例二

 public class SpringBrother{

    public void sing(float money) {
        System.out.println("拿到:"+money+" 元开唱");
    }

    public void dance(float money) {
        System.out.println("拿到:"+money+"元开跳");
    }

}
import java.lang.reflect.Method;

import net.sf.cglib.proxy.Callback;
import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;

public class Client1 {

    public static void main(String[] args) {

        final SpringBrother sb = new SpringBrother();

        /*
        Class type:代理类的父类型
        Callback cb:回调,如何代理
         */
        SpringBrother proxy = (SpringBrother) Enhancer.create(SpringBrother.class,new MethodInterceptor(){

            public Object intercept(Object proxy, Method method, Object[] args,
                    MethodProxy arg3) throws Throwable {
                //判断出场费
                if("sing".equals(method.getName())){
                    //唱歌
                    float money = (Float)args[0];
                    if(money>10000){
                        method.invoke(sb, money/2);
                    }
                }
                if("dance".equals(method.getName())){
                    //唱歌
                    float money = (Float)args[0];
                    if(money>20000){
                        method.invoke(sb, money/2);
                    }
                }
                return null;
            }
        });
        System.out.println(proxy instanceof SpringBrother);
        proxy.dance(100000);
        proxy.sing(50000);

    }

}
运行结果:
   拿到钱:50000.0 元开跳
   拿到:25000.0 元开唱

参考有关动态代理的原理了解底层原理

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值