当前位置:首页 > CN2资讯 > 正文内容

java设计模式:代理模式(二)动态代理java代理模式

2天前CN2资讯


java的代理模式有两种,一种是jdk自带的动态代理,一种是cglib动态代理。

1、jdk动态代理:

/**
* 1.创建接口
*/
public interface Subject {
int sellBook();

String speak();
}
/**
* 2.创建真实对象
*/
public class RealSubject implements Subject {
@Override
public int sellBook() {
System.out.println("卖书");
return 1;
}

@Override
public String speak() {
System.out.println("说话");
return "张三";
}
}
/**
* 3.创建真实对象的代理类,代理类要实现InvocationHandler接口,表示使用jdk动态代理
* 代理模式的重要作用是用于在被代理类的方法执行前后切入代码
*/
public class JdkProty implements InvocationHandler {
/**
* 因为需要处理真实对象,所以需要将真实对象传过来,通过构造方法赋值
*/
private Subject subject;

public JdkProty(Subject subject) {
this.subject = subject;
}

/**
* @param proxy 被代理的对象
* @param method 正在调用的方法
* @param args 方法的参数
* @return
* @throws Throwable
*/
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("调用代理类");
if (method.getName().equals("sellBook")) {
int invoke = (int) method.invoke(subject, args);
System.out.println("调用了卖书的方法");
return invoke;
} else if (method.getName().equals("speak")) {
String string = (String) method.invoke(subject, args);
System.out.println("调用的是说话的方法");
return string;
}
return null;
}
}/***测试方法*/
public class TestDemo {
public static void main(String[] args) {
Subject subject = new RealSubject();
JdkProty jdkProty = new JdkProty(subject);

/**
* 代理对象(本方法可以封装入代理类中,被代理类对象作为obj参数传递)
*subject.getClass().getClassLoader():被代理类对象的加载器
* subject.getClass().getInterfaces():得到被代理类对象的所有接口
* jdkProty:与被代理类对象相关的代理类对象
*/
Subject proxyInstance = (Subject) Proxy.newProxyInstance(subject.getClass().getClassLoader(), subject.getClass().getInterfaces(), jdkProty);
proxyInstance.sellBook();
proxyInstance.speak();
}
}


 使用jdk动态代理的前提条件:被代理的类一定要有实现的接口

/*** java.lang.reflect包下提供了一个Proxy类和一个InvocationHandler接口用来完成动态代理。* InvocationHandler接口:* 当我们通过代理对象调用一个方法时,这个方法的调用就会被转发为由InvocationHandler这个接口的invoke方法进行调用* Proxy类* 该类提供了一个创建动态代理对象的方法*/

 2、cglib动态代理

​​Cglib​​ 动态代理是针对代理的类, 动态生成一个子类, 然后子类覆盖被代理类中的方法, 如果是private或是final类修饰的方法,则不会被重写。

CGLIB是一个功能强大,高性能的代码生成包。它为没有实现接口的类提供代理,为JDK的动态代理提供了很好的补充。通常可以使用Java的动态代理创建代理,但当要代理的类没有实现接口或者为了更好的性能,CGLIB是一个好的选择。

使用cglib动态代理需要导包:cglib-nodep-2.2.2.jar

/**
* 1.创建真实类对象
*/
public class Ennigeer {

//可以被代理的方法
public int eat() {
System.out.println("工程师在吃饭");
return 1;
}

//final修饰的方法不会被cglib生成的子类覆盖,可以通过代理类调用,但是不能执行代理类的方法
public final String work() {
System.out.println("工程师在工作");
return "hello";
}

//private修饰的方法不会被生成的子类覆盖,不能通过代理类调用
private void play() {
System.out.println("工程师在玩");
}
}
public class CglibProxy implements MethodInterceptor {

/**
* 该intercept方法类似于jdk的invoke方法发
* @param o 被代理类对象
* @param method 被代理类的方法对象
* @param objects 传进去的参数
* @param methodProxy 代理方法的代理对象
* @return
* @throws Throwable
*/
@Override
public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
System.out.println("方法调用之前");
Object invoke = methodProxy.invokeSuper(o, objects);
System.out.println("方法调用之后");
return invoke;
}

/**
* 得到代理类
* @param obj 被代理类对象
* @return 代理类对象
*/
public Object getProxy(Object obj) {
//创建加强器,用来创建被代理类的对象
Enhancer enhancer = new Enhancer();
//为加强器指定要代理的业务类(即:为下面生成的代理类指定父类)
enhancer.setSuperclass(obj.getClass());
//设置回调,对代理类上所有方法的调用,都会调用CallBack(),而CallBack()方法则需要intercept方法进行拦截
enhancer.setCallback(this);
//创建被代理类对象的特殊格式的对象
return enhancer.create();
}
}
public class TestDemo {
public static void main(String[] args) {
Ennigeer ennigeer = new Ennigeer();
CglibProxy cglibProxy = new CglibProxy();
Ennigeer proxy = (Ennigeer) cglibProxy.getProxy(ennigeer);
int eat = proxy.eat();//可以被代理的方法
String work = proxy.work();//不能被代理的方法,可以调用该方法,但是不能代理
System.out.println(eat);
System.out.println(work);
}
}/*** net.sf.cglib.proxy.MethodInterceptor接口:是最通用的回调(callback)类型,* 它经常被AOP用来实现拦截(intercept)方法的调用。这个接口只定义了一个方法。* public Object intercept(Object proxy, Method method, Object[] params, MethodProxy methodProxy)* proxy:代理的对象;* method:委托类执行的方法;* params:方法中的参数;* methodProxy:代理的方法* 由于性能的原因,对原始方法的调用我们使用CGLIB的net.sf.cglib.proxy.MethodProxy对象,而不是反射中一般使用java.lang.reflect.Method对象*/

两种代理方式的比较:

  CGLib动态代理创建代理实例速度慢,但是运行速度快;JDK动态代理创建实例速度快,但是运行速度慢。如果实例是单例的,推荐使用CGLib方式动态代理,反之则使用JDK方式进行动态代理。Spring的实例默认是单例,所以这时候使用CGLib性能高。 

  JDK动态代理是通过接口中的方法名,在动态生成的代理类中调用业务实现类的同名方法;

  CGlib动态代理是通过继承业务类,生成的动态代理类是业务类的子类,通过重写业务方法进行代理;

   静态代理是通过在代码中显式定义一个业务实现类一个代理,在代理类中对同名的业务方法进行包装,用户通过代理类调用被包装过的业务方法;



    你可能想看:

    扫描二维码推送至手机访问。

    版权声明:本文由皇冠云发布,如需转载请注明出处。

    本文链接:https://www.idchg.com/info/24231.html

    分享给朋友:

    “java设计模式:代理模式(二)动态代理java代理模式” 的相关文章

    CUII工业互联网平台:助力企业实现智能制造与数字化转型

    CUII的定义与背景 CUII,全称为China Unicom Industrial Internet,是中国联通精心打造的工业互联网平台。它的诞生源于对智能制造领域不断增长的需求,特别是在网络通信基础设施方面。中国联通意识到,随着工业4.0的推进,传统的网络解决方案已无法满足现代工业对高质量、高安...

    全面提升VPS性能测试与优化方法指南

    VPS性能测试概述 在使用VPS的过程中,了解它的性能测试显得尤为重要。VPS性能测试是一种评估虚拟专用服务器性能的手段,可以帮助我们清晰地了解VPS的状态与能力。这项测试不仅关注CPU型号、内存大小等硬件配置,还涵盖了磁盘存储量、操作系统版本以及虚拟化程序等多个方面的检测。通过这些参数,我们能对V...

    DMIT VPS怎么样?性能与价格的全面评测

    在选择VPS的时候,性能绝对是一个关键因素。对于DMIT VPS,我从多个层面来进行评测,特别是它的处理器和存储配置。DMIT采用的Intel至强处理器,真的是一大亮点。这种处理器在处理高负载任务时表现十分优越,其稳定性和速度都让人印象深刻。而且,配合全SSD RAID存储方案,数据的读写速度得到了...

    如何选择合适的Windows VPS服务: 实用指南与推荐

    在寻找合适的Windows VPS服务时,了解主要服务商的特点无疑是一个重要的步骤。市面上众多提供Windows VPS服务的商家中,vpsdime.com、raksmart.com、ion.krypt.asia以及bacloud.com等都是值得考虑的选择。这些服务商在多个地区运营,提供了不同版本...

    Debian 修改DNS 设置的详细指南及常见问题解决方法

    了解DNS及其重要性 在日常使用网络的过程中,我们常会遇到“DNS”这个术语。简单来说,DNS(Domain Name System)是互联网的“电话簿”。它将我们输入的域名转换为计算机理解的IP地址,确保我们能够顺利访问网站。如果没有DNS,我们将不得不记住每一个网站的IP地址,那可真是太麻烦了!...

    优化RackNerd DC2机房 IP使用体验与性能评测

    我最近对RackNerd的DC2机房产生了越来越多的兴趣,特别是位于美国洛杉矶的这座机房。它被誉为RackNerd中中国国内访问速度较快的机房之一,吸引了很多需求高效网络连接的用户。这座机房的地理位置确实蛮不错,靠近美西主干线,对于需要与国内建立连接的网站和应用来说,能带来相对更快的访问速度。 对于...