AOP(Aspect Oriented Programming),即面向切面编程。

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

2、OOP缺陷

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

       先看如下的一张图:

3、Spring的AOP详解和案例

 

       上面这张图有三个类:Dog,Cat和Duck,他们都有一个方法run。按照OOP的设计理念,我们很容易就会想到抽象出一个Animal父类,同时让这三个子类继承Animal父类。这样的设计可以用如下的图示表示:

3、Spring的AOP详解和案例

 

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

3、Spring的AOP详解和案例

 

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

       了解了实现过程之后,我们在来看一下具体的代码。 

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

 

3、AOP简介

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

 

4、AOP实现实例

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

      首先是Dog类

3、Spring的AOP详解和案例
    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("小狗开始跳!");
        }        
    }
3、Spring的AOP详解和案例

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

3、Spring的AOP详解和案例
    public class MyProxy  implements InvocationHandler{
        private Object targetObject;        
        public Object createProxyInstance(Object targetObject) {
            this.targetObject = targetObject;
            return Proxy.newProxyInstance(targetObject.getClass().getClassLoader(), 
                                   targetObject.getClass().getInterfaces(), 
                                   this);
        }
        
        public Object invoke(Object proxy, Method method, Object[] args)
                throws Throwable {
            command();        
            Object ret = method.invoke(targetObject, args);
            award();
            return ret;
        }
        
        private void command() {
            System.out.println("驯兽师发出命令!");
        }
        
        private void award(){
            System.out.println("驯兽师给与奖励!");
        }
    }
3、Spring的AOP详解和案例
  上述代码实现完成之后,我们改如何调用呢?参考代码如下:

3、Spring的AOP详解和案例
    public class Client {
        public static void main(String[] args) {
            MyProxy hander = new MyProxy();
            Animal dog = (Animal)hander.createProxyInstance(new Dog());
            dog.run();
            dog.jump();
        }
    }
3、Spring的AOP详解和案例
  执行结果如下:

3、Spring的AOP详解和案例

 

       关于AOP编程的实例演示就完成了,接下来重新回顾一下AOP与OOP的相关概念。

 

5、AOP与OOP的关系

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

 

一、AOP案例如下:

1、创建如下项目结构

3、Spring的AOP详解和案例

3、Spring的AOP详解和案例

2、在com.entity包下创建User.java

 1 package com.entity;
 2 
 3 public class User {
 4     private Integer id; // 用户ID
 5     private String username; // 用户名
 6     private String password; // 密码
 7     private String email; // 电子邮件
 8 
 9     // getter & setter
10     public Integer getId() {
11         return id;
12     }
13 
14     public void setId(Integer id) {
15         this.id = id;
16     }
17 
18     public String getUsername() {
19         return username;
20     }
21 
22     public void setUsername(String username) {
23         this.username = username;
24     }
25 
26     public String getPassword() {
27         return password;
28     }
29 
30     public void setPassword(String password) {
31         this.password = password;
32     }
33 
34     public String getEmail() {
35         return email;
36     }
37 
38     public void setEmail(String email) {
39         this.email = email;
40     }
41 
42     @Override
43     public String toString() {
44         return "User [email=" + email + ", > password
45                 + ", username=" + username + "]";
46     }
47 
48 
49 
50 }
User.java

相关文章: