用Java创建自己的AOP

介绍

如您所知,AOP是Spring框架提供的最好的功能之一,它在实现跨领域关注的同时提供了最大的灵活性。 您是否想到过AOP在Spring如何工作? 有时这是高级技术面试时要问的问题。 有时,仅涉及核心Java时,这个问题变得更加重要。 最近,我的一位朋友去参加采访,他面临一个尴尬的问题,即如何仅在核心Java中使用AOP而无需使用Spring和相关库。 在本文中,我将为您提供有关如何仅在具有某些限制的情况下仅在核心Java中创建自己的AOP的概述。 这不是Spring AOP和Java AOP之间的比较研究。 但是,您可以使用适当的设计模式在一定程度上用Java实现AOP。

大家都知道AOP以及如何使用Spring框架使用AOP,本文将使您深入了解不使用Spring就能在Java中实现AOP的方法。 作为参考,Spring使用JDK代理和CGlib来提供AOP实现。 JDK动态代理提供了一种灵活的方法来挂钩方法并以一定的限制执行某些操作。 限制是应该有一个接口,并且应该有该接口的实现。 到目前为止,还不清楚。 让我们举个例子。 我们有一个计算器,通过它我们可以执行一些数学运算。 让我们考虑用一个数字除以另一个数字。 现在的问题是有人已经在核心框架中提供了除法运算的实现,是否有可能在该方法中进行劫持以执行额外的验证? 是的。 为此,我在下面的代码片段中提供了这种简单的情况。 基本的抽象代码如下。

public interface Calculator {public int calculate( int a , int b);
}

该实现的代码如下。

public class CalculatorImpl implements Calculator {@Overridepublic int calculate(int a, int b) {return a/b;}
}

想象一下,上面的代码已冻结,并且内核中不能进行更多修改,但是您必须毫无问题地实现功能。 怎么做 ? 让我们使用JDK动态代理的功能。

public class SomeHandler implements InvocationHandler {// Code omitted for simplicity…..@Overridepublic Object invoke(Object proxy, Method method, Object[] params) throws Throwable {
// Your complex business validation and logicObject result = method.invoke(targetObject ,params);return result;}}

让我们来看一下使用我们的jdk动态代理来执行所需功能的测试类。

public static void main(String[] args) {CalculatorImpl calcImpl = new CalculatorImpl();Calculator proxied = (Calculator) getProxy (Calculator.class, calcImpl, new SomeHandler(calcImpl));int result = proxied.calculate(20, 10);System.out.println("FInal Result :::" + result);}

如您所见,我们只是通过简单地实现了伟大的接口调用“ InvocationHandler ”而提供了一个挂钩实现。 根据Java文档,它处理代理实例上的方法调用。

现在,您已经在上面看到了我们可以使用InvocationHandler's invoke()方法执行某些操作来获得所需的结果。 现在我们想到的问题是,在实际方法执行之前和之后如何做些事情。 有可能在执行方法之前做些什么然后在执行该方法之后做些什么吗? 为了使它更具体,我们可以添加多个aops(之前,之后,周围)来挂钩一个方法吗? 我们可以通过制作简化的代码模板来实现。 让我们按照以下步骤实现它。

  1. 创建一种抽象方法,将您自己的aop应用于目标对象。
  2. 创建自己的AOP,例如BeforeHandler和AfterHandler,其中前者在方法执行之前做一些工作,而后者在方法执行之后做一些工作。
  3. 创建一个代理类以使开发人员成为朋友,以便可以轻松传递所有aop处理程序和目标对象以创建钩子。
  4. 提供您自己的业务逻辑或跨领域关注点。
  5. 最后,通过传递必需的参数来创建代理对象。

简要的技术实施

按照以下方式创建抽象处理程序。

public abstract class AbstractHandler implements InvocationHandler {private Object targetObject;public void setTargetObject(Object targetObject) {this.targetObject = targetObject;}
}

创建灵活的开发人员友好的处理程序,例如BeforeHandlerAfterHandler

apublic abstract class BeforeHandler extends AbstractHandler {public abstract void handleBefore(Object proxy, Method method, Object[] args);public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {handleBefore(proxy, method, args);return method.invoke(getTargetObject(), args);}
}
public abstract class AfterHandler extends AbstractHandler {public abstract void handleAfter(Object proxy, Method method, Object[] args);public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {Object result = method.invoke(getTargetObject(), args);handleAfter(proxy, method, args);return result;}
}

创建代理实用程序。

public class ProxyFactory {public static Object getProxy(Object targetObject,List<AbstractHandler> handlers) {//Code to get the proxyreturn proxyObject;} else {return targetObject;}}
}

现在,下面给出了测试工具代码段。

CalculatorImpl calcImpl = new CalculatorImpl();
BeforeHandler before = new BeforeHandlerImpl();
AfterHandler after = new AfterHandlerImpl();
List<AbstractHandler> handlers = new ArrayList<AbstractHandler>();
handlers.add(before);
handlers.add(after);
Calculator proxy = (Calculator) ProxyFactory.getProxy(calcImpl,handlers);
int result = proxy.calculate(20, 10);

组态

以上所有代码段都很简短,以使您对结构实现更加清楚。 进行实际的品味/测试来实现现实总是更好。 从下面的github链接下载完整的项目,并在您喜欢的Java编辑器中对其进行配置,然后运行测试类以查看效果。

  • https://github.com/debjava/aopusingjdkdynamicproxy

结论

希望您喜欢我关于Java的AOP的小文章,发表一些评论以丰富和增强双方的知识。 在本文之前和之后的文章中,我将“ Around”和“ Throw” AOP留给读者。

翻译自: https://www.javacodegeeks.com/2015/03/create-your-own-aop-in-java.html

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

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

相关文章

linux中常用的头文件

#include <linux/***.h> 是在linux-2.6.29/include/linux下面寻找源文件。 #include <asm/***.h> 是在linux-2.6.29/arch/arm/include/asm下面寻找源文件。 #include <mach/***.h> 是在linux-2.6.29/arch/arm/mach-s3c2410/include/mach下面寻找源文件。 #in…

java的文本框如何回车键触发按钮_java回车触发按钮的代码

使用的时候&#xff0c;只要将SwingUtils .enterPressesWhenFocused(JButton)这样就可以实现回车时候&#xff0c;触发按钮。另外文本输入框回车触发事件则是&#xff1a;SwingUtils .enterPressesWhenFocused(JTextField textField,ActionListener actionListener) 。其中acti…

Typescript Interface 覆盖继承的接口定义

type Merge<M, N> Omit<M, Extract<keyof M, keyof N>> & N;使用方式 interface A {name: string;color?: string; } type B Merge<A, {name: string | number;favorite?: boolean; }>;参考地址

JBoss Fuse –一些鲜为人知的技巧

TL; DR 将Java静态调用公开为Karaf Shell本机命令 在部署时覆盖OSGi标头 在使用OSGi片段部署时间后覆盖OSGi标头 将Java静态调用公开为Karaf Shell本机命令 作为必须与支持人员和客户进行协作的软件工程师的一部分&#xff0c;我经常发现自己需要从无法访问的系统中提取其他…

cocos2d-x学习笔记之图片分辨率适配

从wiki里面看到&#xff0c;新的版本是去掉了enabelRetinaDisplay&#xff0c;因为要兼容iosandroid&#xff0c;其他平台是否也是如此&#xff0c;未知&#xff5e; 测试代码 std::vector<std::string> resDirOrders; resDirOrders.push_back("testImage2"…

vue 外部方法调用内部_vue函数内部调用外部函数,报错外部函数不是函数

zeroFill (num,len,radix) {let str num.toString(radix || 10);while (str.length < len) {str 0 str;}return str;},initMap() {console.log(this.zeroFill(50, 8, 16))//底图图层数据源var googleDXSource new XYZ({tileUrlFunction: function (coor) {console.log(c…

electron+react 用户自定义安装路径

使用electron-builder打包electron项目&#xff0c;其中Windows提供了NSIS来自定义安装程序。 在主进程的package.json文件中添加一些配置 "scripts":{},"build": {"directories": {"output": "release"},"nsis":…

模型微调入门介绍一

备注&#xff1a;模型微调系列的博客部分内容来源于极客时间大模型微调训练营素材&#xff0c;撰写模型微调一系列博客&#xff0c;主要是期望把训练营的内容内化成自己的知识&#xff0c;我自己写的这一系列博客除了采纳部分训练营的内容外&#xff0c;还会扩展细化某些具体细…

JMH:如何设置和运行JMH基准

健康警告&#xff01; 这篇文章描述了如何设置和运行简单的JMH基准测试。 众所周知&#xff0c;微基准测试很难正确设置&#xff0c;即使您确实正确设置了&#xff08;通过使用JMH之类的工具&#xff09;&#xff0c;它们仍然会产生误导。 仅仅因为您的代码在极端孤立的人为情况…

npp夜光数据介绍 viirs_科研成果快报第177期:中国地区长时序AVHRR气溶胶数据的主要问题: 气溶胶反演频次与重污染天气...

中国地区长时序AVHRR气溶胶数据的主要问题&#xff1a;气溶胶反演频次与重污染天气A critical view of long-term AVHRR aerosol data record in China: Retrieval frequency and heavy pollution成果信息Minghui Tao, Rong Li, Lili Wang et al. (2020)A critical view of lon…

使用Eclipse创建一个Android程序方法

要编写Android程序&#xff0c;需要安装JDK、Eclipse和Android SDK。 Android SDK的安装路径不要在program file或program file(x86)下&#xff0c;否则在debug时会碰很奇怪的问题。最好直接放在C:\Android下。&#xff08;如果非要放在Program files下也可以&#xff0c;在ecl…

ahooks useVirtualList 滚动条抖动或者数据抖动

原因 页面内容高度发生变化引起滚动条跳动的问题。浏览器会自动触发onscroll事件&#xff0c;调整滚动条的位置&#xff0c;让滚动条不乱跳动 ; 懒加载的时候由于不断更新列表项内部的高度&#xff0c;因此就会使浏览器自动触发滚动事件&#xff0c;而滚动事件又触发懒加载的更…

如何使用Hibernate批处理DELETE语句

介绍 在我以前的文章中 &#xff0c;我解释了批处理INSERT和UPDATE语句所需的Hibernate配置。 这篇文章将继续本主题的DELETE语句批处理。 领域模型实体 我们将从以下实体模型开始&#xff1a; Post实体与Comment具有一对多关联&#xff0c;并且与PostDetails实体具有一对一…

蓝点linux_新闻速读 gt; Windows 10 的 Linux 内核将像驱动程序一样由微软更新服务进行更新 | Linux 中国...

本文字数&#xff1a;3252&#xff0c;阅读时长大约&#xff1a;4 分钟导读&#xff1a;• Ubuntu 发行商 Canonical 将参加微软欧洲虚拟开源峰会 • 树莓派支持 Vulkan 最新进展&#xff1a;通过 70000 项测试 • 谷歌浏览器开始隐藏 URL 详细路径&#xff0c;未来地址栏将只显…

struts2-通配符和动态方法调用

通配符举例--BookAction 1 public class BookAction extends ActionSupport {2 3 public String execute() throws Exception {4 System.out.println("BookAction ********** execute()");5 return null;6 }7 /*8 * 显示图书添加页…

JavaFX技巧18:路径剪切

我最近注意到&#xff0c;我致力于ControlsFX项目的PopOver控件无法正确剪切其内容。 当我为FlexCalendarFX框架开发手风琴弹出窗口时&#xff0c;这一点变得显而易见。 每当最后一个标题窗格扩展时&#xff0c;其底角不再是圆角而是正方形。 在将红色矩形作为内容放置到标题窗…

electron 微信扫码登录 ERR_PROXY_CONNECTION_FAILED

electron: Failed to load URL with error: ERR_PROXY_CONNECTION_FAILED 解决 电脑代理问题;电脑设置里面找到代理,关闭就好了

关于erlang的套接字编程

套接字编程即熟悉的Socket编程&#xff0c;根据传输层协议&#xff0c;可分为&#xff1a;UDP协议和TCP协议.下面写一个简单的例子&#xff0c;再重新认识下它&#xff1a; 1.在同一主机节点下启动两个Erlang节点. a).在第一个Erlang节点下&#xff0c;打开端口为1234的UDP套接…

kotlin 添加第一个 集合_Flutter开发必学Dart语法篇之集合操作符函数与源码分析...

简述:在上一篇文章中&#xff0c;我们全面地分析了常用集合的使用以及集合部分源码的分析。那么这一节讲点更实用的内容&#xff0c;绝对可以提高你的Flutter开发效率的函数&#xff0c;那就是集合中常用的操作符函数。这次说的内容的比较简单就是怎么用&#xff0c;以及源码内…

在Java中确定文件类型

以编程方式确定文件的类型可能非常棘手&#xff0c;并且已经提出并实现了许多基于内容的文件标识方法。 Java中有几种可用于检测文件类型的实现&#xff0c;其中大多数很大程度上或完全基于文件的扩展名。 这篇文章介绍了Java中最常见的文件类型检测实现。 本文介绍了几种在Ja…