动态代理的实现

本文对比静态代理与动态代理的特点,并通过Java内置动态代理及Cglib库实现动态代理,探讨了不同场景下两种代理方式的应用。

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

静态代理

之前通过1+N的问题实践了下静态代理。但静态代理有其局限性。代理类需要实现目标接口,而如果目标接口有所改变,代理类和目标实现均需要作出改变,不是很灵活。

动态代理

那如何实现动态代理呢?我们可以通过java内建的动态代理功能或者通过cglib(code generation library)来实现。需要注意的是,java的动态代理只能对接口进行代理,需要对类进行代理只能使用cglib。

   java的动态代理
// 定义接口
public interface IPerson
{
    void say();
}
public class Person implements IPerson
{
    @Override
    public void say() {
        System.out.println("我是个人");
    }
}
public class ProxyForPerson implements InvocationHandler
{

    IPerson person = null;

    // 关联代理类和接口
    public IPerson getProxyInterface(IPerson person) {
        this.person = person;
        return (IPerson) Proxy.newProxyInstance(person.getClass()
                .getClassLoader(),
                person.getClass()
                        .getInterfaces(),
                this);
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        if("say".equals(method.getName())){
            method.invoke(person, args);
        }
        return null;
    }
}
// 客户端调用
public class Client
{
    public static void main(String[] args) {

        Person person = new Person();
        ProxyForPerson proxy = new ProxyForPerson();
        // 获得代理类
        IPerson iperson = proxy.getProxyInterface(person);

        iperson.say();
    }
}
   cglib实现动态代理

注意使用cglib,需要引入cglib的jar包。同时注意jar名称为cglib-nodep-xxx.jar,而不是cglib-xxx.jar。如果添加引用后者,会如下报错:

Caused by: java.lang.ClassNotFoundException: org.objectweb.asm.Type
public class CglibProxy implements MethodInterceptor
{
    private Enhancer enhancer = new Enhancer();

    public Object getProxy(Class clazz) {
        // 设置需要创建子类的类
        enhancer.setSuperclass(clazz);
        enhancer.setCallback(this);
        // 通过字节码技术动态创建子类实例
        return enhancer.create();
    }

    // 实现MethodInterceptor接口方法
    public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
        System.out.println("前置代理");
        // 通过代理类调用父类中的方法
        Object result = proxy.invokeSuper(obj, args);
        System.out.println("后置代理");
        return result;
    }
}
//客户端调用
public class ClientForCglib
{
    public static void main(String[] args) {
        CglibProxy proxy = new CglibProxy();
        Person proxyson =  (Person)proxy.getProxy(Person.class);

        proxyson.say();
    }
}

后记

CGLib创建的动态代理对象时的性能比JDK创建的动态代理对象的性能高不少,但是CGLib在创建代理对象时所花费的时间却比JDK多得多,所以前者适用于创建单例对象,因为无需频繁创建对象。反之,使用JDK方式要更为合适一些。同时,由于CGLib由于是采用动态创建子类的方法,对于final方法,无法进行代理。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值