开源框架spring详解-----AOP的深刻理解
创始人
2024-07-29 09:00:17
0

AOP的理解

1、AOP的概述

AOP是一种不同于OOP(面向对象编程)的编程模式,它不是OOP的替代,而是对OOP的一种有益补充。

2、spring AOP的原理

3、spring AOP的实现

在spring2.5中,常用的AOP实现方式有两种。第一种是基于xml配置文件方式的实现,第二种是基于注解方式的实现。

接下来,以具体的是理智讲解这两种方式的使用。

Java代码

  1. package com.zxf.service;     
  2.     
  3. /**    
  4.  * 业务逻辑接口    
  5.  * @author z_xiaofei168    
  6.  */    
  7. public interface AccountService {     
  8.     public void save(String loginname, String password);     
  9. }     
  10.     
  11. 它的实现类     
  12.     
  13. package com.zxf.service;     
  14. import com.zxf.dao.AccountDao;     
  15.     
  16. /**    
  17.  * AccountService的实现类    
  18.  * @author z_xiaofei168    
  19.  */    
  20. public class AccountServiceImpl implements AccountService {     
  21.     private  AccountDao accountDao;     
  22.          
  23.     public AccountServiceImpl() {}     
  24.          
  25.     /** 带参数的构造方法 */    
  26.     public AccountServiceImpl(AccountDao accountDao){     
  27.         this.accountDao = accountDao;     
  28.     }     
  29.          
  30.     public void save(String loginname, String password) {     
  31.         accountDao.save(loginname, password);     
  32.         throw new RuntimeException("故意抛出一个异常。。。。");     
  33.     }     
  34.          
  35.     /** set方法 */    
  36.     public void setAccountDao(AccountDao accountDao) {     
  37.         this.accountDao = accountDao;     
  38.     }     
  39. }  

 

对于业务系统来说,AccountServiceImpl类就是目标实现类,它的业务方法,如save()方法的前后或代码会出现异常的地方都是AOP的连接点。

下面是日志服务类的代码:

Java代码

  1. package com.zxf.aspect;     
  2.     
  3. import org.aspectj.lang.JoinPoint;     
  4. import org.aspectj.lang.ProceedingJoinPoint;     
  5.     
  6. /**    
  7.  * 日志切面类    
  8.  * @author z_xiaofei168    
  9.  */    
  10. public class LogAspect {     
  11.     
  12.     //任何通知方法都可以将第一个参数定义为 org.aspectj.lang.JoinPoint类型      
  13.     public void before(JoinPoint call) {     
  14.         //获取目标对象对应的类名     
  15.         String className = call.getTarget().getClass().getName();     
  16.         //获取目标对象上正在执行的方法名     
  17.         String methodName = call.getSignature().getName();     
  18.              
  19.         System.out.println("前置通知:" + className + "类的" + methodName + "方法开始了");     
  20.     }     
  21.          
  22.     public void afterReturn() {     
  23.         System.out.println("后置通知:方法正常结束了");     
  24.     }     
  25.          
  26.     public void after(){     
  27.         System.out.println("最终通知:不管方法有没有正常执行完成,一定会返回的");     
  28.     }     
  29.          
  30.     public void afterThrowing() {     
  31.         System.out.println("异常抛出后通知:方法执行时出异常了");     
  32.     }     
  33.          
  34.     //用来做环绕通知的方法可以第一个参数定义为org.aspectj.lang.ProceedingJoinPoint类型     
  35.     public Object doAround(ProceedingJoinPoint call) throws Throwable {     
  36.         Object result = null;     
  37.         this.before(call);//相当于前置通知     
  38.         try {     
  39.             result = call.proceed();     
  40.             this.afterReturn(); //相当于后置通知     
  41.         } catch (Throwable e) {     
  42.     
  43.             this.afterThrowing();  //相当于异常抛出后通知     
  44.             throw e;     
  45.         }finally{     
  46.             this.after();  //相当于最终通知     
  47.         }     
  48.              
  49.         return result;     
  50.     }     
  51. }   

 

这个类属于业务服务类,如果用AOP的术语来说,它就是一个切面类,它定义了许多通知。Before()、afterReturn()、after()和afterThrowing()这些方法都是通知。

#p#

<1>.基于xml配置文件的AOP实现

这种方式在实现AOP时,有4个步骤。

Xml代码

  1.     
  2.         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"    
  3.         xmlns:aop="http://www.springframework.org/schema/aop"    
  4.         xsi:schemaLocation="     
  5.             http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd     
  6.             http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd>    
  7.     
  8.         
  9.          
  10.         
  11.             
  12.     bean>    
  13.     
  14.         
  15.         
  16.          
  17.         
  18.         
  19.             
  20.             
  21.                 
  22.                             expression="execution(* com.zxf.service.*.*(..))"/>    
  23.                      
  24.                 
  25.                 
  26.                 
  27.                 
  28.                 
  29.                 
  30.                 
  31.                 
  32.                  
  33.                 
  34.                 
  35.         aop:aspect>    
  36.     aop:config>    
  37. beans>    

 

 

 

上述配置针对切入点应用了前置、后置、最终,以及抛出异常后通知。这样在测试执行AccountServiceImpl类的save()方法时,控制台会有如下结果输出。

前置通知:com.zxf.service.AccountServiceImpl类的save方法开始了。

针对MySQL的AccountDao实现中的save()方法。

后置通知:方法正常结束了。

最终通知:不管方法有没有正常执行完成,一定会返回的。

<2>基于注解的AOP的实现

首先创建一个用来作为切面的类LogAnnotationAspect,同时把这个类配置在spring的配置文件中。

在spring2.0以后引入了JDK5.0的注解Annotation的支持,提供了对AspectJ基于注解的切面的支持,从而 更进一步地简化AOP的配置。具体的步骤有两步。

Spring的配置文件是如下的配置:

Xml代码

  1.     
  2.         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"    
  3.         xmlns:aop="http://www.springframework.org/schema/aop"    
  4.         xsi:schemaLocation="     
  5.             http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd     
  6.             http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd>    
  7.     
  8.         
  9.         
  10.             
  11.     bean>    
  12.         
  13.         
  14.         
  15.         
  16. beans>   

 

 

这是那个切面的类LogAnnotationAspect

Java代码

  1. package com.zxf.aspect;     
  2.     
  3. import org.aspectj.lang.JoinPoint;     
  4. import org.aspectj.lang.ProceedingJoinPoint;     
  5. import org.aspectj.lang.annotation.After;     
  6. import org.aspectj.lang.annotation.AfterReturning;     
  7. import org.aspectj.lang.annotation.AfterThrowing;     
  8. import org.aspectj.lang.annotation.Aspect;     
  9. import org.aspectj.lang.annotation.Before;     
  10. import org.aspectj.lang.annotation.Pointcut;     
  11.     
  12. /**    
  13.  * 日志切面类    
  14.  */    
  15. @Aspect  //定义切面类     
  16. public class LogAnnotationAspect {     
  17.     @SuppressWarnings("unused")     
  18.     //定义切入点     
  19.     @Pointcut("execution(* com.zxf.service.*.*(..))")     
  20.     private void allMethod(){}     
  21.          
  22.     //针对指定的切入点表达式选择的切入点应用前置通知     
  23.     @Before("execution(* com. zxf.service.*.*(..))")     
  24.     public void before(JoinPoint call) {     
  25.              
  26.         String className = call.getTarget().getClass().getName();     
  27.         String methodName = call.getSignature().getName();     
  28.              
  29.         System.out.println("【注解-前置通知】:" + className + "类的"      
  30.                 + methodName + "方法开始了");     
  31.     }     
  32.     //访问命名切入点来应用后置通知     
  33.     @AfterReturning("allMethod()")     
  34.     public void afterReturn() {     
  35.         System.out.println("【注解-后置通知】:方法正常结束了");     
  36.     }     
  37.          
  38.     //应用最终通知     
  39.     @After("allMethod()")     
  40.     public void after(){     
  41.         System.out.println("【注解-最终通知】:不管方法有没有正常执行完成,"      
  42.                 + "一定会返回的");     
  43.     }     
  44.          
  45.     //应用异常抛出后通知     
  46.     @AfterThrowing("allMethod()")     
  47.     public void afterThrowing() {     
  48.         System.out.println("【注解-异常抛出后通知】:方法执行时出异常了");     
  49.     }     
  50.          
  51.     //应用周围通知     
  52.     //@Around("allMethod()")     
  53.     public Object doAround(ProceedingJoinPoint call) throws Throwable{     
  54.         Object result = null;     
  55.         this.before(call);//相当于前置通知     
  56.         try {     
  57.             result = call.proceed();     
  58.             this.afterReturn(); //相当于后置通知     
  59.         } catch (Throwable e) {     
  60.             this.afterThrowing();  //相当于异常抛出后通知     
  61.             throw e;     
  62.         }finally{     
  63.             this.after();  //相当于最终通知     
  64.         }     
  65.              
  66.         return result;     
  67.     }     
  68. }    

 

备注:输出结果和前面的一样。

【编辑推荐】

  1. Spring Hibernate简单讨论
  2. OSGi与Spring:设置Spring DM开发环境
  3. 使用Spring DM创建Hello World,以及OSGi服务
  4. Spring MVC总结:善用注解,生活更轻松
  5. 概括spring hibernate集成

相关内容

热门资讯

如何允许远程连接到MySQL数... [[277004]]【51CTO.com快译】默认情况下,MySQL服务器仅侦听来自localhos...
如何利用交换机和端口设置来管理... 在网络管理中,总是有些人让管理员头疼。下面我们就将介绍一下一个网管员利用交换机以及端口设置等来进行D...
施耐德电气数据中心整体解决方案... 近日,全球能效管理专家施耐德电气正式启动大型体验活动“能效中国行——2012卡车巡展”,作为该活动的...
Windows恶意软件20年“... 在Windows的早期年代,病毒游走于系统之间,偶尔删除文件(但被删除的文件几乎都是可恢复的),并弹...
20个非常棒的扁平设计免费资源 Apple设备的平面图标PSD免费平板UI 平板UI套件24平图标Freen平板UI套件PSD径向平...
德国电信门户网站可实时显示全球... 德国电信周三推出一个门户网站,直观地实时提供其安装在全球各地的传感器网络检测到的网络攻击状况。该网站...
为啥国人偏爱 Mybatis,... 关于 SQL 和 ORM 的争论,永远都不会终止,我也一直在思考这个问题。昨天又跟群里的小伙伴进行...
《非诚勿扰》红人闫凤娇被曝厕所... 【51CTO.com 综合消息360安全专家提醒说,“闫凤娇”、“非诚勿扰”已经被黑客盯上成为了“木...