Spring框架 AOP(原理详解)(一)

上次的博文https://blog.csdn.net/qq_34288630/article/details/80223612(Spring框架 IOC(原理详解)(一))中,我为大家简单介绍了一下Spring框架核心内容中的IoC,接下来我们继续讲解另一个核心AOP(Aspect Oriented Programming),即面向切面编程。

1、OOP回顾

在介绍AOP之前先来回顾一下比较熟悉的OOP(Object Oriented Programming)。OOP主要是为了实现编程的重用性、灵活性和扩展性。他的几个特征分别是继承、封装、多态和抽象。OOP重点体现在编程架构,强调的是类之间的层次关系。

2、OOP的缺陷

为了更好的说明OOP的概念,接下来讲OOP的实例,重点分析OOP存在的哪些缺陷,以便更好的理解AOP的相关内容。

先看一张图:
《Spring框架 AOP(原理详解)(一)》

上面 这张图有三个类:Dog,Cat和Duck,他们都有一个run方法。按照OOP的设计理念,我们很容易会想到抽象出一个Animal父类,同时让这三个子类继承Animal父类,这样的设计可用下面图表示:
《Spring框架 AOP(原理详解)(一)》

在OOP思想中,我们会使用大量的类似上图的编程方式,对类进行抽象、继承、封装和多态来实现编程的重用性、灵活性和扩展性。但是这样编程任然有一定的局限,有时候,OOP并不能很好的解决我们在实际开发中遇到的问题。为了说明这个问题,看下图:
《Spring框架 AOP(原理详解)(一)》

看到上图,我们暂时还不能发现问题,但是为了便于理解,接下来给讲解上面类图的实现过程:描述如下:
马戏团有一条表演的小狗,这条小狗可以跑和跳,但是它完成跑和跳两个动作之前必须是在接到驯兽师发出的命令后,同时完成跑和跳的动作之后,驯兽师会给与响应的奖励,比如一块肉。
了解了实现过程之后,我们在来看一下具体的代码。

public class Dog {     
    public void run() {  
        System.out.println("驯兽师发出命令!")  
        System.out.println("小狗开始跑!");  
        System.out.pringln("驯兽师给与奖励");  
    }    
    public void jump() {  
        System.out.println("驯兽师发出命令!")  
        System.out.println("小狗开始跳!");  
        System.out.pringln("驯兽师给与奖励");  
    }  
}  

仔细看上面的代码,我们可以看出在run方法和jump方法中,存在一些相同的内容(驯兽师发出命令和给与奖励),这些内容并不能完全进行抽象,即不能按照OOP编程思想进行处理。类似这样的情况同样会出现在我们编程中的很多地方,例如:日志记录、性能统计、安全控制、事务处理、异常处理等等。但是这样的情况该如何解决呢?这就引入了AOP编程思想。

3、AOP简介

AOP为Aspect Oriented Programming的缩写,即面向切面编程(也叫面向方面),是一种可以通过预编译方式和运行期动态代理实现在不修改源代码的情况下给程序动态统一添加功能的一种技术。

4、AOP实现实例

为了大家更好的理解AOP如何实现,接下来我们优化一下上述代码。
首先是Dog类

public interface Animal {  
    public void run();  
    public void jump();  
}  

public class Dog implements Animal{  
    public void run(){  
        System.out.println("小狗开始跑!");  
    }     
    public void jump(){  
        System.out.println("小狗开始跳!");  
    }         
}  

对比之前的代码我们可以明显看出,我们将关于驯兽师的相关内容从run和jump中进行了抽取,接下来,我们如何在程序运行中将关于驯兽师的动作加入到程序中呢?这就是我们这次用到的AOP实现的核心技术动态代理(Dynamic Proxy)。具体代码如下:

import java.lang.reflect.InvocationHandler;  
import java.lang.reflect.Method;  
import java.lang.reflect.Proxy;  

public class MyProxy implements InvocationHandler{  

    private Object targetObject;  

    /** * 绑定委托对象并返回一个代理类 * @param target * @return */    
    public Object createProxyInstance(Object targetObject) {  
        this.targetObject = targetObject;         
        return Proxy.newProxyInstance(targetObject.getClass().getClassLoader(),   
                               targetObject.getClass().getInterfaces(),   
                               this);  
    }  

    /** * @param proxy:指被代理的对象。 * @param method:要调用的方法 * @param args:方法调用时所需要的参数 */   
    public Object invoke(Object proxy, Method method, Object[] args)  
            throws Throwable {  
        //注入需要调用的方法 
        command();        
        //执行被代理对象的方法,如果方法有返回值则赋值给ret 
        Object ret = method.invoke(targetObject, args);  
        //注入需要调用的方法 
        award();  
        return ret;  
    }  


    private void command() {  
        System.out.println("驯兽师发出命令!");  
    }  
    private void award(){  
        System.out.println("驯兽师给与奖励!");  
    }  
}  

上述代码实现完成之后,我们改如何调用呢?参考代码如下:

public class Client {  
    public static void main(String[] args) {  
        MyProxy hander = new MyProxy();  
        Animal dog = (Animal)hander.createProxyInstance(new Dog());  
        dog.run();  
        dog.jump();  
    }  
}  

执行结果如下:
《Spring框架 AOP(原理详解)(一)》

5、AOP与OOP的关系

OOP针对业务处理过程的实体(Dog、Cat、Duck)及其属性和行为(run)进行抽象封装,以获得更加清晰高效的逻辑单元划分。而AOP则是针对业务处理过程中(run或jump)的切面(command和award)进行提取,它所面对的是处理过程中的某个步骤或阶段,以获得逻辑过程中各部分之间低耦合性的隔离效果。这两种设计思想在目标上有着本质的差异。

    原文作者:AOP
    原文地址: https://blog.csdn.net/qq_34288630/article/details/80263054
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞