分享一个自己写的最为简单的Spring AOP的应用,其实,本人也是学习Spring不久,只是把一些个人的理解分享下,供参考。可能很多人刚开始不太理解到底啥是AOP,其实它也是相对 OOP来说的,类似OOP其实也是一种编程思想吧。本人暂且把Spring 中的AOP理解成一种方法的拦截器(可能有所片面,主要是方便理解)。

个人通俗理解,就好比你去自动取款机取钱,边上装了个摄像头在监视着。你取你的钱,不用管那摄像头干嘛,只是对于摄像头来说,已经把你取钱的这一过 程记录了下来。你取钱的这一过程我们可以从OOP角度分析,而对于摄像头来说,就是从AOP角度去分析了。反映到我下面要讲的示例就是系统日志的记录。

 

我要讲的示例大致是这样的,从OOP角度分析,就是说现在有一个User对象,然后你要调用业务逻辑实现去保存(或者其他行为)这个User对象, 或者说是做持久化操作,把User对象相关信息写进数据库。那么从AOP角度来看,就是在你进行保存对象这一行为发生的时候进行日志记录。就是说,你在进 行业务操作的时候,不需要去关心系统背后到底做了啥,Spring AOP它已经帮你搞定了。

Spring AOP 简单入门示例_AOP

(图一、个人对于OOP与AOP在本人示例中的理解)

 

  上图说表示的东西是个人的理解理解,纵向为主业务逻辑这里表现为对User对象的持久化操作,横向为AOP实现,这里表现为系统日志记录。

 

以下是代码具体实现:(采用Spring2.5,Myeclipse6.5)

Java代码  Spring AOP 简单入门示例_AOP_02
  1. (一)、从AOP角度分析:  
  2.   
  3. package org.wiki.spring.aspect;  
  4.   
  5. import org.aspectj.lang.JoinPoint;  
  6.   
  7. /** 
  8.  * 定义切面类,将系统中的横切性关注点模块化 
  9.  *  
  10.  * @author Wiki.M 
  11.  *  
  12.  */  
  13. public class Aspect {  
  14.   
  15.     /** 
  16.      * 定义advice,即切面类中方法具体实现, 这里主要是用于记录日志,只做简单处理。 
  17.      *  
  18.      * @param joinPoint,可以取得被拦截方法的一些信息 
  19.      */  
  20.     public void logging(JoinPoint joinPoint) {  
  21.         //得到被拦截方法参数,并打印  
  22.         Object[] args = joinPoint.getArgs();  
  23.         for (int i = 0; i < args.length; i++) {  
  24.             System.out.println("method arg" + i + " -- " + args[i]);  
  25.         }  
  26.           
  27.         //得到被拦截方法签名  
  28.         System.out.println(joinPoint.getSignature().getName());  
  29.           
  30.         //记录系统日志具体实现  
  31.         System.out.println("----logging-----");  
  32.     }  
  33. }  
  34.   
  35. (二)从DAO,数据持久化角度分析:  
  36. package org.wiki.spring.dao;    
  37.   
  38. import org.wiki.spring.domain.User;  
  39.   
  40. /** 
  41.  * 定义IUserDAO接口,目的是为了灵活实现UserDAO不同的操作。 
  42.  * @author Wiki.M 
  43.  * 
  44.  */  
  45. public interface IUserDAO {  
  46.       
  47.     public void addUser(User user);  
  48.       
  49.     public void deleteUser(int id);  
  50.       
  51.     public void updateUser(int id);  
  52. }  
  53.   
  54.   
  55. //==================================================  
  56.   
  57. package org.wiki.spring.dao;    
  58.   
  59. import org.wiki.spring.domain.User;  
  60.   
  61. /** 
  62.  * IUserDAO接口的具体实现,这里只做简单处理 
  63.  * @author Wiki.M 
  64.  * 
  65.  */  
  66. public class UserDAOImpl implements IUserDAO {  
  67.   
  68.     @Override  
  69.     public void addUser(User user) {  
  70.         System.out.println("----addUser----");  
  71.   
  72.     }  
  73.   
  74.     @Override  
  75.     public void deleteUser(int id) {  
  76.         System.out.println("----deleteUser----");  
  77.   
  78.     }  
  79.   
  80.     @Override  
  81.     public void updateUser(int id) {  
  82.         System.out.println("----updateUser----");  
  83.   
  84.     }  
  85. }  
  86.   
  87. (三)域模型分析  
  88. package org.wiki.spring.domain;    
  89.   
  90. /** 
  91.  * 领域模型User 
  92.  * @author Wiki.M 
  93.  * 
  94.  */  
  95. public class User {  
  96.       
  97.     private int id;  
  98.       
  99.     private String name;  
  100.       
  101.     private String password;  
  102.       
  103.     public int getId() {  
  104.         return id;  
  105.     }  
  106.   
  107.     public void setId(int id) {  
  108.         this.id = id;  
  109.     }  
  110.   
  111.     public String getName() {  
  112.         return name;  
  113.     }  
  114.       
  115.     public void setName(String name) {  
  116.         this.name = name;  
  117.     }  
  118.       
  119.     public String getPassword() {  
  120.         return password;  
  121.     }  
  122.       
  123.     public void setPassword(String password) {  
  124.         this.password = password;  
  125.     }  
  126.   
  127. }  
  128.   
  129. (四)、从业务层分析:  
  130. package org.wiki.spring.service;    
  131.   
  132. import org.wiki.spring.domain.User;  
  133.   
  134. /** 
  135.  * 定义User业务逻辑相关的一个接口, 
  136.  * 目的是为了在客户端自由调用接口实现 
  137.  * @author Wiki.M 
  138.  * 
  139.  */  
  140. public interface IUserService {  
  141.       
  142.    public void saveUser(User user);  
  143.      
  144.    public void deleteUser(int id);  
  145.      
  146.    public void updateUser(int id);   
  147. }  
  148.   
  149. //=========================================  
  150.   
  151.  package org.wiki.spring.service;    
  152.   
  153. import org.wiki.spring.dao.IUserDAO;  
  154. import org.wiki.spring.domain.User;  
  155.   
  156. /** 
  157.  * 业务逻辑接口IUserService的具体实现 
  158.  * @author Wiki.M 
  159.  * 
  160.  */  
  161. public class UserServiceImpl implements IUserService {  
  162.   
  163.     private IUserDAO userDAO;  
  164.       
  165.     public void setUserDAO(IUserDAO userDAO) {  
  166.         this.userDAO = userDAO;  
  167.     }  
  168.       
  169.     @Override  
  170.     public void deleteUser(int id) {  
  171.         userDAO.deleteUser(id);  
  172.     }  
  173.   
  174.     @Override  
  175.     public void saveUser(User user) {  
  176.         userDAO.addUser(user);  
  177.   
  178.     }  
  179.   
  180.     @Override  
  181.     public void updateUser(int id) {  
  182.         userDAO.updateUser(id);  
  183.     }  
  184.   
  185. }  
  186.   
  187. (五)从客户端调用分析:  
  188. package org.wiki.spring.client;    
  189.   
  190. import org.springframework.beans.factory.BeanFactory;  
  191. import org.springframework.context.support.ClassPathXmlApplicationContext;  
  192. import org.wiki.spring.domain.User;  
  193. import org.wiki.spring.service.IUserService;  
  194.   
  195. public class Client {  
  196.       
  197.     /** 
  198.      * 客户端调用,用于测试 
  199.      * @param args 
  200.      */  
  201.     public static void main(String[] args){  
  202.           
  203.         BeanFactory factory = new ClassPathXmlApplicationContext("*.xml");  
  204.           
  205.         //得到UserService具体实现,用于操作业务逻辑  
  206.         IUserService userService = (IUserService)factory.getBean("userServiceImpl");  
  207.           
  208.         User user = new User();  
  209.         user.setId(1);  
  210.         user.setName("Wiki");  
  211.         user.setPassword("123");  
  212.           
  213.         //测试1,记录日志  
  214.         userService.saveUser(user);  
  215.           
  216.         //测试2,记录日志  
  217.         userService.deleteUser(1);  
  218.     }  
  219. }  

 

    Spring配置文件:

Xml代码  Spring AOP 简单入门示例_AOP_02
  1. <?xml version="1.0" encoding="UTF-8"?>  
  2.   
  3. <beans xmlns="http://www.springframework.org/schema/beans"  
  4.     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  
  5.     xmlns:aop="http://www.springframework.org/schema/aop"  
  6.     xmlns:tx="http://www.springframework.org/schema/tx"  
  7.     xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd  
  8.            http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.0.xsd  
  9.            http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.0.xsd">  
  10.       
  11.     <!-- 配置UserDAOImpl -->  
  12.     <bean id="userDAO" class="org.wiki.spring.dao.UserDAOImpl"/>  
  13.       
  14.     <!-- 配置UserServiceImpl -->  
  15.     <bean id="userServiceImpl"  
  16.         class="org.wiki.spring.service.UserServiceImpl">  
  17.         <!-- 注入userDAO,实际为UserDAOImpl,即对数据持久化的具体实现 -->  
  18.         <property name="userDAO" ref="userDAO" />  
  19.     </bean>  
  20.       
  21.     <!-- 配置aspect切面类 -->  
  22.     <bean id="userAspect" class="org.wiki.spring.aspect.Aspect" />  
  23.   
  24.     <!-- 配置AOP -->  
  25.     <aop:config>  
  26.         <!-- 配置aspect切面类 -->  
  27.         <aop:aspect ref="userAspect">  
  28.             <!-- 配置pointcut,即切入点,对哪些类的哪些方法起到AOP的作用 -->  
  29.             <aop:pointcut id="userServiceMethods"  
  30.                 expression="execution(* org.wiki.spring.service.UserServiceImpl.*(..))" />     
  31.             <!-- 配置advice,即Aspect类中的logging()方法,这里采用在业务方法执行前进行拦截 -->  
  32.             <aop:before method="logging" pointcut-ref="userServiceMethods" />  
  33.         </aop:aspect>  
  34.           
  35.     </aop:config>  
  36. </beans>  

 

可能用到的Jar包: commons-logging.jar,  log4j.jar, spring.jar, aspectjrt.jar, aspectjweaver.jar

 

另附本人测试代码。

 

注:如使用Annotation方式最好请修改Aspect这个类的类名,命名的时候疏忽了,可能会更aspectjrt.jar中的类冲突。