Spring的AOP逐层深入——采用注解完成AOP(七)

Easter79
• 阅读 769

上篇博文AOP基本原理6我们介绍了AOP的基本原理,以及5种通知的类型,

AOP的两种配置方式:XML配置和Aspectj注解方式。

        这篇我们使用注解方式来实现一个AOP,我们先看一下项目的目录。

        Spring的AOP逐层深入——采用注解完成AOP(七)

         我们采用的是JDK代理,所以首先将接口和实现类代码附上:

[java] view plain copy

  1. package com.tgb.spring;  

  2. public interface UserManager {  

  3.     public void addUser(String userName,String password);  

  4.     public void delUser(int userId);  

  5.     public String findUserById(int userId);  

  6.     public void modifyUser(int userId,String userName,String password);  

  7. }

  

[java] view plain copy

  1. package com.tgb.spring;  

  2. public class UserManagerImpl implements UserManager {  

  3.     @Override  

  4.     public void addUser(String userName, String password) {  

  5.         System.out.println("----UserManagerImpl.add()----");  

  6.     }  

  7.     @Override  

  8.     public void delUser(int userId) {  

  9.         System.out.println("----UserManagerImpl.delUser()----");  

  10.     }  

  11.     @Override  

  12.     public String findUserById(int userId) {  

  13.         System.out.println("----UserManagerImpl.findUserById()----");  

  14.         if(userId <= 0){  

  15.             throw new IllegalArgumentException("该用户不存在");  

  16.         }  

  17.         return "jiuqiyuliang";  

  18.     }  

  19.     @Override  

  20.     public void modifyUser(int userId, String userName, String password) {  

  21.         System.out.println("----UserManagerImpl.modifyUser()----");  

  22.     }  

  23. }

  

       上面代码跟我们平时写的一样,关键看我们的切面类,同理,切面类可以换成安全性检测以及日志管理等等:

[java] view plain copy

  1. package com.tgb.spring;  

  2. import org.aspectj.lang.JoinPoint;  

  3. import org.aspectj.lang.ProceedingJoinPoint;  

  4. import org.aspectj.lang.annotation.After;  

  5. import org.aspectj.lang.annotation.AfterReturning;  

  6. import org.aspectj.lang.annotation.AfterThrowing;  

  7. import org.aspectj.lang.annotation.Around;  

  8. import org.aspectj.lang.annotation.Aspect;  

  9. import org.aspectj.lang.annotation.Before;  

  10. import org.aspectj.lang.annotation.Pointcut;  

  11. @Aspect  

  12. public class AspectJAdvice {  

  13.     /** 

  14.      * Pointcut 

  15.      * 定义Pointcut,Pointcut的名称为aspectjMethod(),此方法没有返回值和参数 

  16.      * 该方法就是一个标识,不进行调用 

  17.      */  

  18.     @Pointcut("execution(* find*(..))")  

  19.     private void aspectjMethod(){};  

  20.     /**  

  21.      * Before 

  22.      * 在核心业务执行前执行,不能阻止核心业务的调用。 

  23.      * @param joinPoint  

  24.      */    

  25.     @Before("aspectjMethod()")    

  26.     public void doBefore(JoinPoint joinPoint) {    

  27.         System.out.println("-----doBefore.invoke-----");  

  28.         System.out.println(" 此处意在执行核心业务逻辑前,做一些安全性的判断等等");  

  29.         System.out.println(" 可通过joinPoint来获取所需要的内容");  

  30.         System.out.println("-----End of doBefore()------");  

  31.     }  

  32.     /**  

  33.      * Around  

  34.      * 手动控制调用核心业务逻辑,以及调用前和调用后的处理, 

  35.      *  

  36.      * 注意:当核心业务抛异常后,立即退出,转向AfterAdvice 

  37.      * 执行完AfterAdvice,再转到ThrowingAdvice 

  38.      * @param pjp 

  39.      * @return 

  40.      * @throws Throwable 

  41.      */   

  42.     @Around(value = "aspectjMethod()")    

  43.     public Object doAround(ProceedingJoinPoint pjp) throws Throwable {    

  44.         System.out.println("-----doAround.invoke-----");  

  45.         System.out.println(" 此处可以做类似于Before的事情");  

  46.         //调用核心逻辑  

  47.         Object retVal = pjp.proceed();  

  48.         System.out.println(" 此处可以做类似于After的事情");  

  49.         System.out.println("-----End of doAround()------");  

  50.         return retVal;  

  51.     }    

  52.     /**  

  53.      * After  

  54.      * 核心业务逻辑退出后(包括正常执行结束和异常退出),执行此Advice 

  55.      * @param joinPoint 

  56.      */  

  57.     @After(value = "aspectjMethod()")    

  58.     public void doAfter(JoinPoint joinPoint) {    

  59.         System.out.println("-----doAfter.invoke-----");  

  60.         System.out.println(" 此处意在执行核心业务逻辑之后,做一些日志记录操作等等");  

  61.         System.out.println(" 可通过joinPoint来获取所需要的内容");  

  62.         System.out.println("-----End of doAfter()------");  

  63.     }    

  64.     /**  

  65.      * AfterReturning  

  66.      * 核心业务逻辑调用正常退出后,不管是否有返回值,正常退出后,均执行此Advice 

  67.      * @param joinPoint 

  68.      */   

  69.     @AfterReturning(value = "aspectjMethod()", returning = "retVal")    

  70.     public void doReturn(JoinPoint joinPoint, String retVal) {    

  71.         System.out.println("-----doReturn().invoke-----");  

  72.         System.out.println("Return Value: " + retVal);   

  73.         System.out.println(" 此处可以对返回值做进一步处理");  

  74.         System.out.println(" 可通过joinPoint来获取所需要的内容");  

  75.         System.out.println("-----End of doReturn()------");  

  76.     }  

  77.     /** 

  78.      * 核心业务逻辑调用异常退出后,执行此Advice,处理错误信息 

  79.      *  

  80.      * 注意:执行顺序在Around Advice之后 

  81.      * @param joinPoint 

  82.      * @param ex 

  83.      */  

  84.     @AfterThrowing(value = "aspectjMethod()", throwing = "ex")    

  85.     public void doThrowing(JoinPoint joinPoint, Exception ex) {    

  86.         System.out.println("-----doThrowing().invoke-----");  

  87.         System.out.println(" 错误信息:"+ex.getMessage());  

  88.         System.out.println(" 此处意在执行核心业务逻辑出错时,捕获异常,并可做一些日志记录操作等等");  

  89.         System.out.println(" 可通过joinPoint来获取所需要的内容");  

  90.         System.out.println("-----End of doThrowing()------");    

  91.     }    

  92. }

  

       我们配置完切面类之后,还需要将Spring的IOC和AOP结合:

[html] view plain copy

  1.   

  2. <beans xmlns="http://www.springframework.org/schema/beans"  

  3.          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  

  4.          xmlns:aop="http://www.springframework.org/schema/aop"  

  5.          xmlns:tx="http://www.springframework.org/schema/tx"  

  6.          xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.1.xsd  

  7.            http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.1.xsd  

  8.            http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.1.xsd">  

  9.       

  10.     aop:aspectj-autoproxy  

  11.       

  12.       

  

         所有都完成之后,最重要的一步就是编写客户端,进行测试,看是否和我们预想的结果一致。

[java] view plain copy

  1. package com.tgb.spring;  

  2. import org.springframework.beans.factory.BeanFactory;  

  3. import org.springframework.context.support.ClassPathXmlApplicationContext;  

  4. public class Client {  

  5.     public static void main(String[] args) {  

  6.         BeanFactory factory = new ClassPathXmlApplicationContext("applicationContext.xml");  

  7.         UserManager userManager = (UserManager) factory.getBean("userManager");  

  8.         //可以查找张三  

  9.         userManager.findUserById(1);  

  10.         System.out.println("=====我==是==分==割==线=====");  

  11.         try {  

  12.             // 查不到数据,会抛异常,异常会被AfterThrowingAdvice捕获  

  13.             userManager.findUserById(0);  

  14.         } catch (IllegalArgumentException e) {  

  15.         }  

  16.     }  

  17. }

  

运行结果如图:

Spring的AOP逐层深入——采用注解完成AOP(七)     Spring的AOP逐层深入——采用注解完成AOP(七)

              正常运行,无异常抛出(一)                                                                                         不正常运行,有异常抛出(二)

         上面两张图的目的为了给大家描述Advice五种类型的运行顺序,让大家对他们有一个更加清晰的认识。

         使用注解方式可以很好的帮助我们理解AOP的原理,如果对AOP的原理不是特别清晰,可以看一下上篇博文的图。下面我们采用xml方式再实现一遍AOP。

点赞
收藏
评论区
推荐文章
blmius blmius
3年前
MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1
文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s
皕杰报表之UUID
​在我们用皕杰报表工具设计填报报表时,如何在新增行里自动增加id呢?能新增整数排序id吗?目前可以在新增行里自动增加id,但只能用uuid函数增加UUID编码,不能新增整数排序id。uuid函数说明:获取一个UUID,可以在填报表中用来创建数据ID语法:uuid()或uuid(sep)参数说明:sep布尔值,生成的uuid中是否包含分隔符'',缺省为
待兔 待兔
4个月前
手写Java HashMap源码
HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程22
Wesley13 Wesley13
3年前
java面试中被问到的问题
 技术面1) Spring 的注解有哪些?2) 你如何理解 spring IOC 技术,如果不使用spring,你有哪些方式来加载 bean?3) spring aop 的原理是什么?它是怎样一个写法?关键配置项是什么?4) springmvc 的注解有哪些?@ModelAttribute 重点提及
Stella981 Stella981
3年前
Spring Aspect Oriented Programming
  本文是一篇SpringAOP的基础知识分析文章,其中不牵扯源码分析,只包含AOP中重要概念的讲解,分析,以及SpringAOP的用法。    Spring从2.0版本引入了更加简单却强大的基于xml和AspectJ注解的面向切面的编程方式。在深入了解如何用Spring进行面向切面的编程前,我们先了解AOP中的几个重要的基本概念,这几个概念
Easter79 Easter79
3年前
Spring的AOP的注解的通知类型,切入点的注解
Spring的注解的AOP的通知类型@Before:前置通知@AfterReturning:后置通知@Around:环绕通知@AfterThrowing:异常抛出通知@After:最终通知@Pointcut:切入点的注解1/
Wesley13 Wesley13
3年前
Java——基于AspectJ的AOP开发
1.AspectJ简介AspectJ是一个基于Java语言的AOP框架。Spring2.0以后新增了对AdpectJ切点表达式的支持。@AspectJ是AspectJ1.5新增功能,通过JDK5注解技术,允许直接在Bean类中定义切面。新版本Spring框架,建议使用AspectJ方式来开发AOP。使用AspectJ需要导
Easter79 Easter79
3年前
Spring中的AOP(三)——基于Annotation的配置方式(一)
    AspectJ允许使用注解用于定义切面、切入点和增强处理,而Spring框架则可以识别并根据这些注解来生成AOP代理。Spring只是使用了和AspectJ5一样的注解,但并没有使用AspectJ的编译器或者织入器,底层依然使用SpringAOP来实现,依然是在运行时动态生成AOP代理,因此不需要增加额外的编译,也不需要AspectJ的织入器支持。
Stella981 Stella981
3年前
Spring3核心技术之AOP配置
在Spring配置文件中,所有AOP相关定义必须放在<aop:config标签下,该标签下可以有<aop:pointcut、<aop:advisor、<aop:aspect标签,配置顺序不可变。!(http://static.oschina.net/uploads/img/201511/25003650_G0NP.jpg)●
Wesley13 Wesley13
3年前
MySQL部分从库上面因为大量的临时表tmp_table造成慢查询
背景描述Time:20190124T00:08:14.70572408:00User@Host:@Id:Schema:sentrymetaLast_errno:0Killed:0Query_time:0.315758Lock_
Easter79
Easter79
Lv1
今生可爱与温柔,每一样都不能少。
文章
2.8k
粉丝
5
获赞
1.2k