AOP的理解

来源:互联网 发布:拉姆赞卡德罗夫 知乎 编辑:程序博客网 时间:2024/06/07 07:10

    AOP也就是传说中的“面向切面编程”,是一种新的方法论,也是对传统的OOP的补充,AOP的主要的编程对象是切面,切面模块化横切关注点。

    以上的就是比较专业的概述了什么是AOP,当然还有一大堆术语像切点,连接点,切面啥的我就不累赘了,这些东西编程的次数多了自然就熟悉了,这里我用比较浅显易懂的方式和大家说一下什么是AOP。

    AOP是面向切面的,编写的传统的C++和JAVA程序是面向对象的,也就是OOP了,之所以一开始大家(我也一样)对AOP的概念非常模糊,看了很多博客也不能很清晰的说出了个一二三来,原因很简单,就是没有自己去写一个AOP的程序,编程这块我觉得动手才是最重要的,一会儿我会用一个简单的程序去说明AOP。在此之前呢,还是大概说一下对AOP的理解,当然我不会用术语尽量说的明白。

    大家都知道,写出的代码很注重所谓的“重用性”,要是想让自己的程序能够反复的利用,那必须做到一点,每次修改的时候只是修改一部分,而不是脱胎换骨。虽然面向对象的提出解决了很多的问题,但是也不能做的完美无缺,比如:比如我们要对两个数进行数学运算:加减乘除。但是有个要求,那就是加入日志,在运算之前要记录两个数,在运算之后要记录运算结果。为了方便就直接输出相应的信息就好了,那么我们先定义一个接口:

public interface ArithmeticCalculator {int add(int i,int j);int sub(int i,int j);int mul(int i,int j);int div(int i,int j);}
那么我们在去写一个类去实现这个接口(用传统的方法):

public class ArithmeticCalculatorLoggingImpl implements ArithmeticCalculator {@Overridepublic int add(int i, int j) {System.out.println("the method add begins with["+ i +","+ j +"]");int result = i+j;System.out.println("the method add ends with " + result);return result;}@Overridepublic int sub(int i, int j) {System.out.println("the method sub begins with["+ i +","+ j +"]");int result = i-j;System.out.println("the method sub ends with " + result);return result;}@Overridepublic int mul(int i, int j) {System.out.println("the method mul begins with["+ i +","+ j +"]");int result = i*j;System.out.println("the method mul ends with " + result);return result;}@Overridepublic int div(int i, int j) {System.out.println("the method div begins with["+ i +","+ j +"]");int result = i/j;System.out.println("the method div ends with " + result);return result;}}
    想必在这里大家都能看懂,这很符合要求是不是,但是大家发现一个问题了没有,每个方法中我们都为了日志输出了两次,但是每个方法的输出时候很相似的,如果这时候我想改变输出的语句,是不是每个方法都要重新写一遍,这样是很麻烦的。于是我们就想,能不能在运行的时候插入我们想要的呢?而不是直接在函数和里面写。在外面看起来就像是在一个类中插入了相应的代码,那这个OOP就不能实现了。于是一咬牙一跺脚,AOP出来吧!于是所谓的面向切面编程就诞生了,从这里大家应该对这个所谓的“切面”有所了解了吧,或者说有点感觉了,其实这个“切面”可以理解成针对与一个类中的某个部分(也许不怎么恰当,先将就着看吧)。

    说了半天,那么这个程序如果用面向切面的思想来写会是什么样的呢?

    首先实现接口的类变了,变成啥了嗯?看看代码:

package calculate;public class ArithmeticCalculatorImpl implements ArithmeticCalculator {@Overridepublic int add(int i, int j) {int result = i+j;return result;}@Overridepublic int sub(int i, int j) {int result = i-j;return result;}@Overridepublic int mul(int i, int j) {int result = i*j;return result;}@Overridepublic int div(int i, int j) {int result = i/j;return result;}}
    很明显,没有了那些繁杂的输出语句,剩下的这些add,sub,mul,div函数可以叫做业务逻辑。那么去掉的那些前置日志,后置日志呢叫啥呢?那就是切面了。好了那么怎么实现之前的功能呢?那就要写一个代理类了。

public class ArithmeticCalculatorLogginProxy {//要代理的对象private ArithmeticCalculator target;public ArithmeticCalculatorLogginProxy(ArithmeticCalculator target){this.target = target;}public ArithmeticCalculator getLoggingProxy(){ArithmeticCalculator proxy = null;//代理对象由哪个类加载器负责加载ClassLoader loader = target.getClass().getClassLoader();//代理对象的类型,即其中有哪些方法Class[] interfaces = new Class[]{ArithmeticCalculator.class};//当调用代理对象其中的方法时,该执行的代码InvocationHandler h = new InvocationHandler(){/* * proxy:正在返回的那个代理对象,一般情况下,在invoke方法中都不是用该对象 * method:正在被调用的方法 * args:调用方法时,传入的参数 */@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {String methodName = method.getName();//日志1System.out.println("the method "+ methodName + " begins with " + Arrays.asList(args));//执行方法Object result = method.invoke(target, args);//日志2System.out.println("The method " + methodName + " ends with " + result);return result;}};proxy = (ArithmeticCalculator)Proxy.newProxyInstance(loader, interfaces, h);return proxy;}}
    也许大家对这个proxy东西不怎么熟悉,没事,其实这玩意就是起到一个代理的功能。主要是编写invoke函数来帮我们完成应该完成的任务。这里可以看出,如果再想改变输出语句的内容,只需要该两行函数就好了。是不是很方便!

    那么写一个测试程序测试一下呗。

public class Main{public static void main(String[] args) {/*ArithmeticCalculator arithmeticCalculator = null;arithmeticCalculator = new ArithmeticCalculatorLoggingImpl();*/ArithmeticCalculator target = new ArithmeticCalculatorImpl();ArithmeticCalculator proxy = new ArithmeticCalculatorLogginProxy(target).getLoggingProxy();int result = proxy.add(1, 2);System.out.println("result------>" + result);}}

      上面注释的就是测试之前最传统的写法的,得到的结果肯定都是一样的。


       这就是所谓的AOP了,不知道看了有没有比之前对AOP有感觉了没有哈哈。

       另外说一句,AOP和IOC都是学Spring的时候接触也是才开始学的,毕竟Spring是基于这两个玩意的,好消息是Sping的AOP实现比较简单,不需要像我一样去写一个代理类。封装就是好呀,哈哈大笑





0 0
原创粉丝点击