这篇文章是关于Java的一个疑难杂症,通过利用Java核心库实现简单的AOP方法,并把实例代码做了分析对照,以下是全部内容:
春是一个十分火热开源框架,而AOP(面向切面编程)则是春天最重要的概念之一,为了更好的理解和学习AOP的思想,使用核心库来实现一次不失为一个好方法。
首先介绍一下AOP的概念,AOP(面向方面的编程),即面向切面编程,所谓的面向切面编程,就是从一个横切面的角度去设计代码的思想,传统的OOP思想是用封装继承和多态构造一种纵向的层次关系,但不适合定义横向的关系,而AOP思想则对此进行了很好的补充。
例如日志管理代码往往横向的散布在很多对象层次中,但跟它对应的对象的核心功能可以说是毫无关系,还有很多类似的代码,如权限验证,调试输出,事务处理等,也都是如此,这样的话就不利于代码的复用和管理了。
这时候AOP技术就应运而生了,它利用“横切”技术,深入封装对象的内部,并将那些影响了多个类的公共行为封装到一个可重用模块,并将其命名为“方面”,即切面。所谓“切”面,简单说就是那些与业务无关,却为业务模块所共同调用的逻辑或责任封装起来,便于减少系统的重复代码,降低模块之间的耦合度,并有利于后续的可操作性和可维护性。
那么AOP又是如何实现的呢?
答案是动态代理(关于代理会有另外篇章做详细介绍,这里就不赘述了)。实现动态代理有两种方式,一种是JDK动态代理,一种是CGLib动态代理。
那么分别使用两种方式来做一个简单的栗子。
先设计一个场景,假设我们有一个计算接口ICalculator和实现了该接口的计算器类CalculatorImpl。
<前> 公共接口ICalculator {//加法运算 公共int添加(int, int b);//减法 公共int减去(int, int b); //乘法 公共int相乘(int, int b);//除法 公共int除号(int, int b); } <前> 公共类CalculatorImpl实现ICalculator { @Override 公共int添加(int, int b) { 返回一个+ b; } @Override 公共int减去(int, int b) { 返回一个- b; } @Override 公共int相乘(int, int b) { 返回一个* b; } @Override 公共int除号(int, int b) { 返回a/b; } }如何在不改动原来计算器类内部代码的情况下记录计算器各个方法使用的总次数呢?
有了动态代理后,其实就很简单了,先创建一个类并实现InvocationHandler接口,覆盖调用方法,
<前> 公共类TestHandler实现InvocationHandler { 私有对象targetObject; 私人int useTimes;//绑定委托对象,并返回代理类 公共对象绑定(对象targetObject) { 这一点。targetObject=targetObject; .getClassLoader返回Proxy.newProxyInstance (targetObject.getClass () (), targetObject.getClass () .getInterfaces ()); } @Override 公共对象调用对象代理、方法方法,对象[]args)抛出Throwable {//做某事 前(); 对象的结果=method.invoke (targetObject, args); 后(); 返回结果; } 私人空间在(){ system . out。println(“计算之前我们可以做点什么。”); } 私人无效后(){ useTimes + +; System.out.println(“已使用:“+ useTimes +“次”); } }别看代码好像有点多,其实主要的方法就是调用方法,里面对象的结果=method.invoke (targetObject, args);相当于继续用原来的参数执行原来方法。这里的之前和之后为自定义的函数,可以在目标代码执行前后做一些我们想要做的事情,比如这里的使用次数统计。
在绑定方法里,传入目标代理对象,并返回一个代理类实例。接下来我们看看如何使用:
<前> 公开课TestProxy { 公共静态void main (String [] args) { TestHandler代理=new TestHandler (); ICalculator计算器=(ICalculator)代理。绑定(新CalculatorImpl ()); int结果=calculator.add (1、2); system . out。println(“结果是:“+结果); 结果=calculator.subtract (3 2); system . out。println(“结果是:“+结果); 结果=calculator.multiply (4、6); system . out。println(“结果是:“+结果); 结果=calculator.devide (2); system . out。println(“结果是:“+结果); } }我们先定义一个TestHandler,然后通过绑定方法来获得一个代理实例,之后我们就可以直接使用这个实例了。运行结果如下: