本篇文章小编给大家分享一下Java实现动态代理代码实例,文章代码介绍的很详细,小编觉得挺不错的,现在分享给大家供大家参考,有需要的小伙伴们可以来看看。
前言
动态代理在Java中有着广泛的应用,比如Spring AOP、Hibernate数据查询、测试框架的后端mock、RPC远程调用、Java注解对象获取、日志、用户鉴权、全局性异常处理、性能监控,甚至事务处理等。
代理,指的是使用代理对象代替对其它对象的访问,简单点说,你求职时找的中介就是代理,那么在Java中,代理如何体现呢?
静态代理
我们首先需要知道,何为静态代理?静态代理指的是在编译期就对目标对象的方法进行增强,例如:
public class TestDemo { interface EmailService { void sendEmail(String emailContent); } static class EmailServiceImpl implements EmailService{ @Override public void sendEmail(String emailContent) { System.out.println("发送了一封邮件,内容为:" + emailContent); } } public static void main(String[] args) { EmailService emailService = new EmailServiceImpl(); emailService.sendEmail("hello"); } }
现在若是想在发送邮件之前获取一下当前的时间,则可以使用代理类对发邮件的方法进行增强:
public class TestDemo { interface EmailService { void sendEmail(String emailContent); } static class EmailServiceImpl implements EmailService{ @Override public void sendEmail(String emailContent) { System.out.println("发送了一封邮件,内容为:" + emailContent); } } static class EmailProxy implements EmailService{ private final EmailService emailService; public EmailProxy(EmailService emailService) { this.emailService = emailService; } @Override public void sendEmail(String emailContent) { System.out.println(LocalDateTime.now()); emailService.sendEmail(emailContent); } } public static void main(String[] args) { EmailService emailProxy = new EmailProxy(new EmailServiceImpl()); emailProxy.sendEmail("hello"); } }
静态代理的缺点非常明显,编写麻烦,且可扩展性不强,而动态代理的出现,将彻底解决这些问题。
动态代理
动态代理与静态代理恰恰相反,动态代理是在运行期对目标对象的某个方法进行增强,比如仍然是发邮件的服务,使用动态代理,即可这样实现:
public class TestDemo { interface EmailService { void sendEmail(String emailContent); } static class EmailServiceImpl implements EmailService { @Override public void sendEmail(String emailContent) { System.out.println("发送了一封邮件,内容为:" + emailContent); } } public static void main(String[] args) { EmailService emailService = new EmailServiceImpl(); EmailService emailProxy = (EmailService) Proxy.newProxyInstance(EmailServiceImpl.class.getClassLoader(), EmailServiceImpl.class.getInterfaces(), new InvocationHandler() { @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { System.out.println(LocalDateTime.now()); Object result = method.invoke(emailService, args); return result; } }); emailProxy.sendEmail("hello"); } }
使用JDK提供的Proxy和InvocationHandler类能够轻松实现动态代理,但这种方式也是有局限性的,就是被增强的类必须实现了接口,因为Proxy的参数中需要接收类的接口信息。
CGLib实现动态代理
CGLib的出现,打破了这一僵局,使用CGLib,能够增强任意的对象方法,即使你没有实现任何接口,因为它是通过继承的方式进行增强的。
下面就来演示一下如何使用CGLib,首先引入依赖:
cglib cglib 3.3.0
实现如下:
public class TestDemo { static class EmailServiceImpl { public void sendEmail(String emailContent) { System.out.println("发送了一封邮件,内容为:" + emailContent); } } public static void main(String[] args) { EmailServiceImpl emailService = new EmailServiceImpl(); EmailServiceImpl emailProxy = (EmailServiceImpl) Enhancer.create(emailService.getClass(), new MethodInterceptor() { @Override public Object intercept(Object o, Method method, Object[] args, MethodProxy methodProxy) throws Throwable { System.out.println(LocalDateTime.now()); Object obj = methodProxy.invokeSuper(o, args); return obj; } }); emailProxy.sendEmail("hello"); } }
它的写法与JDK提供的方式类似,通过Enhancer类的create()方法即可增强一个对象,并传入对象的Class对象和一个MethodInterceptor接口的实现类,并在intercept()方法中对原方法进行增强。
忍者必须死34399账号登录版 最新版v1.0.138v2.0.72
下载勇者秘境oppo版 安卓版v1.0.5
下载忍者必须死3一加版 最新版v1.0.138v2.0.72
下载绝世仙王官方正版 最新安卓版v1.0.49
下载Goat Simulator 3手机版 安卓版v1.0.8.2
Goat Simulator 3手机版是一个非常有趣的模拟游
Goat Simulator 3国际服 安卓版v1.0.8.2
Goat Simulator 3国际版是一个非常有趣的山羊模
烟花燃放模拟器中文版 2025最新版v1.0
烟花燃放模拟器是款仿真的烟花绽放模拟器类型单机小游戏,全方位
我的世界动漫世界 手机版v友y整合
我的世界动漫世界模组整合包是一款加入了动漫元素的素材整合包,
我的世界贝爷生存整合包 最新版v隔壁老王
我的世界MITE贝爷生存整合包是一款根据原版MC制作的魔改整