介绍
如您所知,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(之前,之后,周围)来挂钩一个方法吗? 我们可以通过制作简化的代码模板来实现。 让我们按照以下步骤实现它。
- 创建一种抽象方法,将您自己的aop应用于目标对象。
- 创建自己的AOP,例如BeforeHandler和AfterHandler,其中前者在方法执行之前做一些工作,而后者在方法执行之后做一些工作。
- 创建一个代理类以使开发人员成为朋友,以便可以轻松传递所有aop处理程序和目标对象以创建钩子。
- 提供您自己的业务逻辑或跨领域关注点。
- 最后,通过传递必需的参数来创建代理对象。
简要的技术实施
按照以下方式创建抽象处理程序。
public abstract class AbstractHandler implements InvocationHandler {private Object targetObject;public void setTargetObject(Object targetObject) {this.targetObject = targetObject;}
}
创建灵活的开发人员友好的处理程序,例如BeforeHandler和AfterHandler 。
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