一文搞懂两种最常用的动态代理:JDK和CGLIB

目前最常用两种动态代理就是JDK和CGLIB,一种是JDK自带的,一种是三方技术。

两者区别:

JDK:JDK动态代理是java.lang.reflect.*包提供的方式,它必须借助一个接口才能产生代理对象。

CGLIB:在一些不能提供接口的环境中,只能采用其他第三方技术,比如CGLIB动态代理。它的优势在于不需要提供接口,只要一个非抽象类就能实现动态代理。

 1.JDK代理

因为JDK需要接口才能产生代理对象,所以先创建一个接口

package service;

public interface HelloWordService {
    void sayHello();
}



//实现类
package service.serviceimpl;

import service.HelloWordService;

public class HelloWordServiceImpl implements HelloWordService {
    @Override
    public void sayHello() {
        System.out.println("Hello Word");
    }
    
}

完成上面操作后,我们先要建立起代理对象和真实服务对象的关系,然后实现代理逻辑,所以一共分为两个步骤。
在 JDK 动态代理中,要实现代理逻辑类必须去实现 java.lang.reflect.InvocationHandler接口,它里面定义了一个invoke方法,并提供接口数组用于下挂代理对象,

package classtext;

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

public class JDKProxyExample implements InvocationHandler {

    Object target=null;
    //代理对象
    public Object bind(Object target){
        this.target=target;
        /*newProxyInstance方法参数,第一个参数获得当前类加载器,第二个参数获得当前类接口
        第三个参数代表当前对象并实现了InvocationHandler接口
         */
        return Proxy.newProxyInstance(target.getClass().getClassLoader(),
   target.getClass().getInterfaces(), this);
    }
    /*
    * invoke代理方法参数
    * 第一个参数是代理对象,第二个参数是当前调度方法,第三个参数是方法参数
    * */
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) 
throws Throwable {
        System.out.println("进入代理逻辑模式");
        System.out.println("在调度真实对象之前的服务");
        Object obj=method.invoke(target,args);
        System.out.println("在调度真实对象之后的服务");
        return obj;

    }

}

其中建立代理对象和真实对象的关系是通过下图实现的,实现代理逻辑的是ivnoke方法

return Proxy.newProxyInstance(target.getClass().getClassLoader(),
target.getClass().getInterfaces(),
                this);

单元测试如下图


public class ProxyTest {
    public static void main(String[] args) {
        //绑定关系,因为挂在接口HelloWord下,所以声明代理对象HelloWordService proxy
        JDKProxyExample jdkProxyExample=new JDKProxyExample();
        //此时proxy为代理对象,他会进入invoke方法里
        HelloWordService proxy=(HelloWordService) jdkProxyExample.bind(new HelloWordServiceImpl());
        proxy.sayHello();

输出结果:

进入代理逻辑模式
在调度真实对象之前的服务
Hello Word
在调度真实对象之后的服务

2.CGLIB

再不能提供接口时使用,只需要一个非抽象类即可实现动态代理

package service.serviceimpl;

public class ReflectServiceImpl {
    public void sayHello(){
        System.out.println("CGLIB代理");
    }
}

动态代理逻辑类:

package classtext;

import org.springframework.cglib.proxy.Enhancer;
import org.springframework.cglib.proxy.MethodInterceptor;
import org.springframework.cglib.proxy.MethodProxy;

import java.lang.reflect.Method;

public class CglibProxyExample implements MethodInterceptor {
    //创建代理对象
    public Object getProxy(Class cls){
        //增强类对象
        Enhancer enhancer = new Enhancer();
        //设置增强类型,通过setSuperclass设置它的代理类
        enhancer.setSuperclass(cls);
        //定义代理逻辑对象为当前对象,要求当前对象实现MethodInterceptor
        enhancer.setCallback(this);
        //生成并返回代理对象
        return enhancer.create();
    }
    /*
    * 代理逻辑方法
    * 第一个参数是代理对象 第二个参数是方法 第三个方法参数
    * 第四个是调度方法
    * */
    @Override
    public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
        System.out.println("调用真实对象之前");
        //CGLIB反射调用真实对象
        Object result=methodProxy.invokeSuper(proxy,args);
        System.out.println("调用真实对象后");
        return result;
    }
}

单元测试:

   CglibProxyExample cglibProxyExample=new CglibProxyExample();
        ReflectServiceImpl reflectProxy=(ReflectServiceImpl) cglibProxyExample
                .getProxy(ReflectServiceImpl.class);
        reflectProxy.sayHello();

输出结果:

调用真实对象之前
CGLIB代理
调用真实对象后

 两者十分相似,它们都是先获取代理对象之后调用代理逻辑实现,而代理逻辑要实现接口的一个方法,这个借口定义的方法就是代理逻辑的实现,它可以控制真实对象的方法。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值