栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

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

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

一文搞懂两种最常用的动态代理: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;
        
        return Proxy.newProxyInstance(target.getClass().getClassLoader(),
   target.getClass().getInterfaces(), this);
    }
    
    @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代理
调用真实对象后

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

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/643255.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号