动态代理JDK于cglib

静态代理的缺点:

1、由于静态代理中的代理类是针对某一个类去做代理的,那么假设一个系统中有100个Service,则需要创建100个代理类
2、如果一个Service中有很多方法需要事务(增强动作),发现代理对象的方法中还是有很多重复的代码
3、由第一点和第二点可以得出:静态代理的重用性不强
那怎么解决呢?
用动态代理就可以很好的解决上述问题,本篇介绍一下:Java中的动态代理
动态代理实现的目的和静态代理一样,都是对目标方法进行增强,而且让增强的动作和目标动作分开,达到解耦的目的
动态代理分为JDK的动态代理和cglib动态代理,他俩有略微的差别:cglib动态代理产生的代理对象是目标对象的子类。
下面分别介绍JDK的动态代理(是JDK的代码实现的)和cglib动态代理(是cglib的jar包实现的)

JDK的动态代理

Interface

package com.itheima.proxy;/*** 对生产常见的要求*/
public interface IProducer {/*** 销售* @param money*/public void saleProduct(float money);/*** 售后* @param money*/public void afterServer(float money);
}

Producer

package com.itheima.proxy;/*** 一个生产者[需要符合代理商的要求,代理商的要求是 要有销售和售后]*/
public class Producer implements IProducer {/*** 销售** @param money*/public void saleProduct(float money) {System.out.println("拿到钱,卖出产品"+money);}/*** 售后** @param money*/public void afterServer(float money) {System.out.println("提供售后服务,并拿到钱"+money);}
}

client

package com.itheima.proxy;import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;/*** 模拟一个消费者*/
public class client {public static void main(String[] args) {//生产者final Producer producer = new Producer();/*** 动态代理* 特点:字节码 随用随创建,随用随加载* 作用:不修改源码的基础上对方法增强* 分类:基于接口的动态代理*          设计的类 peoxy*          提供者:JDK官方**      基于子类的动态代理*如何创建代理对象*      使用Proxy类中的newProxyInstance方法*创建代理对象的要求*      被代理类必须实现一个接口,如果没有则不能使用* newProxyInstance 参数*        ClassLoader:类加载器*          它是用于加载代理对象的字节码的,和被代理对象使用相同的类加载器 固定写法*        class[]:字节码数组*          它是用于让代理对象和被代理对象有相同的方法。 固定写法*        InvocationHandler :用于提供增强的代码*          它是让我们写如何代理,我们一般都是写一个该接口的实现类,通常情况下都是匿名内部类,但不是必须的*          此接口的实现类都是谁用谁写**//*代理对象为  iProducer。被代理对象producer*/IProducer iProducer = (IProducer) Proxy.newProxyInstance(producer.getClass().getClassLoader(), producer.getClass().getInterfaces(), new InvocationHandler() {/***  作用:执行被代理对象的任何接口方法都会经过该方法* @param proxy  代理对象的引用* @param method 当前执行的方法* @param args   当前执行方法的参数* @return       和被代理对象方法有相同的返回值* @throws Throwable*/public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
//                提供增强的代码Object returnValue = null;
//                获取方法执行的参数Float money = (Float) args[0];
//                判断当前的方法是不是销售if ("saleProduct".equals(method.getName())) {returnValue = method.invoke(producer, money * 0.8f);} else {returnValue = method.invoke(producer, money * 0.08f);}return returnValue;}});iProducer.saleProduct(10000f);iProducer.afterServer(1000f);}
}
结果
拿到钱,卖出产品8000.0
提供售后服务,并拿到钱80.0

cglib动态代理

client

package com.itheima.cglib;import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;import java.lang.reflect.Method;public class client {public static void main(String[] args) {final Producer producer = new Producer();/*动态代理:特点:字节码随用随创建,随用随加载作用:在不修改源码的基础上对方法增强分类:基于接口的动态代理基于子类的动态代理涉及的类:Enhancer提供者:   第三方cglib库如何创建代理对象:使用Enhance类中的create方法创建代理对象的要求:被代理对象的类不能是最终类create方法的参数class:字节码它是用于指定被代理对象的字节码CallBack:用于提供增强的代码它是让我们写如何代理,我们一般都是写一个该接口的实现类,通常情况下采用匿名内部类,但是不是必须的我们一般写的都是该接口的子接口的实现类,MethodInterceptor*/Producer producerProxy = (Producer) Enhancer.create(producer.getClass(), new MethodInterceptor() {/*** 执行被代理对象的任何方法都会经过该方法, 具有拦截作用** @param proxy* @param method* @param args        以上是哪个参数和基于接口的动态代理中的invoke方法的参数是一样的* @param methodProxy 当前执行方法的代理对象* @return* @throws Throwable*/public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {Object returnValue = null;Float money = (Float) args[0];if ("saleProduct".equals(method.getName())) {returnValue = method.invoke(producer, money * 0.8f);}else {returnValue = method.invoke(producer, money * 0.08f);}return returnValue;}});producerProxy.saleProduct(10000f);producerProxy.afterServer(1000f);}
}
Producer
package com.itheima.cglib;public   class Producer {/*** 销售** @param money*/public void saleProduct(float money) {System.out.println("拿到钱,卖出产品"+money);}/*** 售后** @param money*/public void afterServer(float money) {System.out.println("提供售后服务,并拿到钱"+money);}
}
结果
拿到钱,卖出产品8000.0
提供售后服务,并拿到钱80.0

以上就是动态代理的两种实现。

我们用上边的做法去实现目标方法的增强,实现代码的解耦,是没有问题的,但是还是需要自己去生成代理对象,自己手写拦截器,在拦截器里自己手动的去把要增强的内容和目标方法结合起来,这用起来还是有点繁琐,有更好的解决方案吗?

答案是:有的!那就是Spring的AOP,这才是咱们最终想引出来的重点!

有了Spring的AOP后,就不用自己去写了,只需要在配置文件里进行配置,配置好后Spring按照你的配置去帮你生成代理对象,按照你的配置把增强的内容和目标方法结合起来。就相当于自己写代码也能实现和aop类似的功能,但是有了Spring aop以后有些事情Spring帮你做了,而且人家Spring做成了可配置化,用起来非常简单而且很灵活

咱们上边用的JDK动态代理和cglib动态代理,这两种在Spring的AOP里都有用到,Spring是根据不同的情况去决定是使用JDK的动态代理生成代理对象,还是使用cglib去生成代理对象。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/325595.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

以深圳.NET俱乐部名义 的技术交流会圆满成功

2017年5月13日的深圳下着暴雨,一场以深圳.NET俱乐部名义的.NET技术交流会在微软Build 2017刚闭幕时在罗湖布吉路与翠山路交界处富基PARK国际6F举办,这次交流以微软Build 2017 大会发布的.NET Standard 2.0 Preview1/.NET Core 2.0 Preview 1为契机&#…

C#中的序列化和反序列化

序列化:是将对象的状态存储到特定存储介质的过程,也可以说是将对象状态转换为可保持或传输的格式的过程。 上面的解释是官方定义,大白话解释就是,将对象以二进制的方式存储在文件中,如果简简单单的将一些数据或者内容存…

JS中的JSON

<!DOCTYPE html> <html><head><meta charset"UTF-8"><title></title><!--如果需要兼容IE7及以下的JSON操作&#xff0c;则可以通过引入一个外部的js文件来处理--><script type"text/javascript" src"js…

关于勒索病毒 Ransom:Win32.WannaCrypt 解决方案的最后一次说明

2017/5/12 晚&#xff0c;勒索软件 Ransom:Win32.WannaCrypt 大面积暴发。比病毒爆发更火的&#xff0c;则是各类关于此病毒的新闻、解决方法在朋友圈等社交媒体的爆发。 其中&#xff0c;有主观善意但客观一知半解的指导&#xff0c;更有夹带私货的安全软件商携各类工具的广告…

maven的三种packaging方式

pom是maven依赖文件 jar是java普通项目打包 war是java web项目打包 pom&#xff1a;打出来可以作为其他项目的maven依赖&#xff0c;在工程A中添加工程B的pom&#xff0c;A就可以使用B中的类。用在父级工程或聚合工程中。用来做jar包的版本控制。 jar包&#xff1a;通常是开发…

C#中的序列化和反序列化案例

序列化&#xff1a;是将对象的状态存储到特定存储介质的过程&#xff0c;也可以说是将对象状态转换为可保持或传输的格式的过程。上面的解释是官方定义&#xff0c;大白话解释就是&#xff0c;将对象以二进制的方式存储在文件中&#xff0c;如果简简单单的将一些数据或者内容存…

浅谈MySQL的B树索引与索引优化

转载自 浅谈MySQL的B树索引与索引优化 MySQL的MyISAM、InnoDB引擎默认均使用B树索引&#xff08;查询时都显示为“BTREE”&#xff09;&#xff0c;本文讨论两个问题&#xff1a; 为什么MySQL等主流数据库选择B树的索引结构&#xff1f; 如何基于索引结构&#xff0c;理解常…

.NET特性:异步流

自从VB/C#开始支持async/await后&#xff0c;开发者一直在期待异步版本的IEnumerable。但直到C# 7和ValueTask发布前&#xff0c;从性能的角度来看这一要求几乎是不可能实现的。 在老版本C#中&#xff0c;开发者每次使用await时都需要进行内存分配。如果要枚举10,000个项&…

MySQL 5.5.45+, 5.6.26+ and 5.7.6+ requirements SSL connection must be established

Establishing SSL connection without server’s identity verification is not recommended. According to MySQL 5.5.45, 5.6.26 and 5.7.6 requirements SSL connection must be established by default if explicit option isn’t set. For compliance with existing appli…

优秀学生专栏——孙珩发

继优秀学生董超同学之后的孙珩发同学的回访录&#xff0c;孙珩发同学于今年5月份毕业&#xff0c;是一个非常非常懂事的孩子&#xff0c;比如让他帮忙拿一下水杯&#xff0c;一般的同学都是直接给你拿杯子过来&#xff0c;而孙珩发同学可不是&#xff0c;他会将水杯里面接满水&…

Java并发编程包中atomic的实现原理

转载自 Java并发编程包中atomic的实现原理 这是一篇来自粉丝的投稿&#xff0c;作者【林湾村龙猫】最近在阅读Java源码&#xff0c;这一篇是他关于并发包中atomic类的源码阅读的总结。Hollis做了一点点修改。 引子 在多线程的场景中&#xff0c;我们需要保证数据安全&#…

优秀学生专栏——王浩

今天继续回访优秀学生王浩&#xff0c;王浩是班级里学习最好的同学&#xff0c;就业的时候也是最早入职的&#xff0c;目前所处岗位是开发&#xff0c;最近在北京出差。企业多次向学校表扬王浩同学&#xff0c;以下是王浩同学的简单回访&#xff1a;想对学弟学妹说些什么&#…

.NET Framework 4.7正式发布

以前.NET Framework 4.7是随Windows 10 Creators Edition一并提供的&#xff0c;现在它已经正式发布&#xff0c;这意味着使用旧版本Windows的用户现在也能安装它了。.NET Framework 4.7通过Windows 10 Anniversary Update发布&#xff0c;支持Windows 7 SP1及以上版本&#xf…

Spring XML中如何使用 符号,比如数据库MySQL连接

<property name"url" value"jdbc:mysql://localhost:3306/spring?useUnicodetrue&amp;characterEncodingutf-8&amp;useSSLfalse"></property>使用&amp; 代替&符号&#xff0c;注意后面的分号

动态网站初识体验

一、静态网站的局限性&#xff1a; 1.无法实现交互功能 2.无法及时对页面的更新 二、动态网页&#xff1a; 1.可以根据不同的操作或者输入&#xff0c;返回不同的网页。 三、B/S&#xff1a;&#xff08;浏览器/服务器&#xff09; 程序完全部署在服务器上&#xff0c;用户通过…

如何高效排查系统故障?一分钱引发的系统设计“踩坑”案例

转载自 如何高效排查系统故障&#xff1f;一分钱引发的系统设计“踩坑”案例 背景说明 某日&#xff0c;做产品X的开发接到客户公司电话&#xff0c;说是对账出了1分钱的差错&#xff0c;无法处理。本着“客户第一”的宗旨&#xff0c;开发立马上线查看情况。查完发现&#…

JWT(JSON web token)

1.什么是JWT JSON Web Token (JWT) is an open standard (RFC 7519) that defines a compact and self-contained way for securely transmitting information between parties as a JSON object. This information can be verified and trusted because it is digitally sign…

优秀学生专栏——李浩然

今天回访的同学是李浩然同学&#xff0c;李浩然同学不光长得帅&#xff08;下面有照片哦&#xff09;&#xff0c;技术还过硬&#xff0c;今年5月份毕业的&#xff0c;目前从事教学工作&#xff0c;自从工作以来&#xff0c;企业曾多次向学校表扬李浩然同学&#xff0c;下面是对…