Spring AOP技术(基于AspectJ)的Annotation开发

@(Spring)[aop, spring, xml, Spring, annotation, aspectJ]

  • Spring AOP技术基于AspectJ的Annotation开发

    • Spring AOP的Annotation的开发

      • Spring的基于AspectJ的AOP的Annotation开发

        • 第一步引入jar包
        • 第二步创建配置文件
        • 第三步创建需增强包和类
        • 第四步将类交给Spring管理
        • 第五步编写测试
        • 第六步编写切面类和通知
        • 第七步 配置切面类
        • 第八步开启AOP的自动代理
        • 第九步通过注解实现AOP
        • 第九步执行测试
      • 通知类型
        • 前置通知

          • 配置切面和通知
          • 单元测试
        • 后置通知
          • 配置切面和通知
          • 单元测试
        • 环绕通知
          • 配置切面和通知
          • 单元测试
        • 异常抛出通知
          • 配置切面和通知
          • 单元测试
        • 最终通知
          • 配置切面和通知
          • 单元测试
      • 切入点的注解
      • Spring AOP小项目

Spring AOP的Annotation的开发

Spring的基于AspectJ的AOP的Annotation开发

第一步引入jar包

第二步创建配置文件

  • 引入AOP的约束
<beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns:aop="http://www.springframework.org/schema/aop" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd"> </beans>

第三步创建需增强包和类

  • 创建接口
package com.pc.aop.dao;/*** 客户持久层接口* * @author Switch* @data 2016年11月23日* @version V1.0*/
public interface CustomerDao {/*** 保存用户*/public void save();
}
  • 创建实现类
package com.pc.aop.dao.impl;import com.pc.aop.dao.CustomerDao;/*** 用户持久层实现类* * @author Switch* @data 2016年11月23日* @version V1.0*/
public class CustomerDaoImpl implements CustomerDao {@Overridepublic void save() {System.out.println("保存用户了。。。");}
}

第四步将类交给Spring管理

<bean id="customerDao" class="com.pc.aop.dao.impl.CustomerDaoImpl" />

第五步编写测试

package com.pc.test;import javax.annotation.Resource;import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;import com.pc.aop.dao.CustomerDao;/*** 面向切面编程测试类* * @author Switch* @data 2016年11月23日* @version V1.0*/
// 配置Spring单元测试环境
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:applicationContext.xml")
public class SpringAOPTest {// 注入依赖@Resource(name = "customerDao")private CustomerDao customerDao;// 测试Spring单元测试集成@Testpublic void testSpring() {customerDao.save();}
}

输出

保存用户了。。。

PS:这时候没用使用AOP进行任何增强

第六步编写切面类和通知

package com.pc.aop.advice;
import org.aspectj.lang.ProceedingJoinPoint;
/*** 切面类* * @author Switch* @data 2016年11月23日* @version V1.0*/
public class MyAspect {// 通知:校验权限public void check() {System.out.println("校验权限。。。。。。");}
}

第七步 配置切面类

<!-- 配置切面类 -->
<bean id="myAspect" class="com.pc.aop.advice.MyAspect"/>

第八步开启AOP的自动代理

<!-- 开启AOP注解自动代理 -->
<aop:aspectj-autoproxy/>

第九步通过注解实现AOP

// 配置了自动AOP代理的,需要在类上配置该注解,不然无法被识别为切面
@Aspect
public class MyAspect {// 前置通知@Before("execution(* com.pc.aop.dao.impl.CustomerDaoImpl.save(..))")// 通知:校验权限public void check() {System.out.println("校验权限。。。。。。");}
}

第九步执行测试

package com.pc.test;import javax.annotation.Resource;import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;import com.pc.aop.dao.CustomerDao;/*** 面向切面编程测试类* * @author Switch* @data 2016年11月23日* @version V1.0*/
// 配置Spring单元测试环境
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:applicationContext.xml")
public class SpringAOPTest {// 注入依赖@Resource(name = "customerDao")private CustomerDao customerDao;// 测试Spring单元测试集成@Testpublic void testSpring() {customerDao.save();}
}

输出

校验权限。。。。。。
保存用户了。。。

通知类型

PS:因为在XML中已经给出了各个通知的完整测试代码,所以这里只给出通知代码和测试代码及其结果,如果想查看其他代码,请查找《Spring AOP技术(基于AspectJ)的XML开发》

前置通知

前置通知:在目标方法执行之前完成的增强。获得切入点信息。
注解:@Before
PS:接入点信息,其他类型的增强也可以通过这种方法使用。

配置切面和通知
// 配置了自动AOP代理的,需要在类上配置该注解,不然无法被识别为切面
@Aspect
public class MyAspect {// 前置通知@Before("execution(* com.pc.aop.dao.impl.CustomerDaoImpl.save(..))")// 通知:校验权限public void check(JoinPoint joinPoint) {System.out.println("校验权限。。。。。。");// 输出接入点信息System.out.println(joinPoint.toString());}
}
单元测试
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:applicationContext.xml")
public class SpringAOPTest {// 注入依赖@Resource(name = "customerDao")private CustomerDao customerDao;// 测试前置通知@Testpublic void testBefore() {customerDao.save();}
}

输出

校验权限。。。。。。
execution(void com.pc.aop.dao.CustomerDao.save())
保存用户了。。。

后置通知

后置通知:在目标方法执行之后完成的增强。获得方法的返回值。
注解:@AfterReturning

配置切面和通知
// 配置了自动AOP代理的,需要在类上配置该注解,不然无法被识别为切面
@Aspect
public class MyAspect {// 后置通知@AfterReturning(value = "execution(* com.pc.aop.dao.impl.CustomerDaoImpl.delete(..))", returning = "retVal")// 通知:打印日志public void printLog(String retVal) {System.out.println("打印日志。。。。。");System.out.println("返回值为:" + retVal);}
}
单元测试
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:applicationContext.xml")
public class SpringAOPTest {// 注入依赖@Resource(name = "customerDao")private CustomerDao customerDao;// 测试后置通知@Testpublic void testAfterRunning() {String delete = customerDao.delete();System.out.println(delete);}
}

输出

删除用户了。。。
打印日志。。。。。
返回值为:delete
delete

环绕通知

环绕通知:在目标方法执行前和执行后完成的增强。阻止目标方法的执行,获得方法参数。
注解:@Around

配置切面和通知
// 配置了自动AOP代理的,需要在类上配置该注解,不然无法被识别为切面
@Aspect
public class MyAspect {// 环绕通知@Around("execution(* com.pc.aop.dao.impl.CustomerDaoImpl.update(..))")// 通知:计算方法耗时public void calTime(ProceedingJoinPoint joinPoint) throws Throwable {System.out.println("方法执行前。。。。。。");// 打印参数System.out.println("参数为:" + joinPoint.getArgs()[0]);// 执行目标方法joinPoint.proceed();System.out.println("方法执行后。。。。。。");}
}
单元测试
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:applicationContext.xml")
public class SpringAOPTest {// 注入依赖@Resource(name = "customerDao")private CustomerDao customerDao;// 测试环绕通知@Testpublic void testAround() {customerDao.update(6166);}
}

输出

方法执行前。。。。。。
参数为:6166
更新用户了。。。
方法执行后。。。。。。

异常抛出通知

异常抛出通知:在目标方法执行出现异常的时候完成的增强。获得异常的信息。
注解:@AfterThrowing

配置切面和通知
// 配置了自动AOP代理的,需要在类上配置该注解,不然无法被识别为切面
@Aspect
public class MyAspect {// 异常通知@AfterThrowing(value = "execution(* com.pc.aop.dao.impl.CustomerDaoImpl.find(..))", throwing = "ex")// 通知:异常处理public void throwHandler(Throwable ex) {System.out.println("异常处理。。。。。。" + ex.getMessage());}
}
单元测试
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:applicationContext.xml")
public class SpringAOPTest {// 注入依赖@Resource(name = "customerDao")private CustomerDao customerDao;// 测试异常通知@Testpublic void testAfterThrowing() {customerDao.find();}
}

输出

查询用户了。。。
异常处理。。。。。。/ by zero

最终通知

最终通知:无论目标方法是否出现异常总是执行的增强。
注解:@After

PS:该案例和异常测试案例对同一个target进行增强。

配置切面和通知
// 配置了自动AOP代理的,需要在类上配置该注解,不然无法被识别为切面
@Aspect
public class MyAspect {// 最终通知@After("execution(* com.pc.aop.dao.impl.CustomerDaoImpl.find(..))")// 通知:关闭资源public void close() {System.out.println("关闭资源。。。。。。");}
}
单元测试
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:applicationContext.xml")
public class SpringAOPTest {// 注入依赖@Resource(name = "customerDao")private CustomerDao customerDao;// 测试最终通知@Testpublic void testFinally() {customerDao.find();}
}

输出

查询用户了。。。
关闭资源。。。。。。
异常处理。。。。。。/ by zero

切入点的注解

在上面的案例中,都是在通知上面直接定义切入点。这样有一个比较麻烦的问题,也就是如果我们需要修改多个通知相同的切入点,那么需要改大量的切入点代码。

上面的问题,可以通过使用切入点注解@Pointcut解决。

案例:

package com.pc.aop.advice;import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;/*** 切面类* * @author Switch* @data 2016年11月23日* @version V1.0*/
// 配置了自动AOP代理的,需要在类上配置该注解,不然无法被识别为切面
@Aspect
public class MyAspect {// 异常通知@AfterThrowing(value = "com.pc.aop.advice.MyAspect.pointcut1()", throwing = "ex")// 通知:异常处理public void throwHandler(Throwable ex) {System.out.println("异常处理。。。。。。" + ex.getMessage());}// 最终通知@After("com.pc.aop.advice.MyAspect.pointcut1()")// 通知:关闭资源public void close() {System.out.println("关闭资源。。。。。。");}// 配置切入点@Pointcut("execution(* com.pc.aop.dao.impl.CustomerDaoImpl.find(..))")public void pointcut1() {}
}

PS:切入点的注解需要定义在方法上,切入点方法一般是无意义的。如果需要使用切入点方法,只需要在通知声明中写入包名.类型.方法名(),如果通知和切入点在一个类中,那么也可以直接写入方法名()

Spring AOP小项目

GitHub:Spring AOP小项目
GitHub:MyStore-netease

Spring AOP技术(基于AspectJ)的Annotation开发相关推荐

  1. Spring AOP技术(基于AspectJ)的XML开发

    Spring AOP技术(基于AspectJ)的XML开发 @(Spring)[aop, spring, xml, Spring, annotation, aspectJ] Spring AOP技术基 ...

  2. Spring AOP之---基于JDK动态代理和CGLib动态代理的AOP实现

    AOP(面向切面编程)是OOP的有益补充,它只适合那些具有横切逻辑的应用场合,如性能监测,访问控制,事物管理,日志记录等.至于怎么理解横切逻辑,敲完实例代码也就明白了. 为什么要使用AOP,举个栗子: ...

  3. 如何理解 Spring AOP 以及使用 AspectJ?

    作者 | 阿文 责编 | 屠敏 出品 | CSDN(ID:CSDNnews) 在 Spring 中 AOP 是一个非常非常重要的概念,那么什么是AOP呢? AOP 即面向切面编程,也可以叫做面向方向编 ...

  4. Spring Aop实例之AspectJ注解配置

    上篇博文<Spring Aop实例之xml配置>中,讲解了xml配置方式,今天来说说AspectJ注解方式去配置spring aop. 依旧采用的jdk代理,接口和实现类代码请参考上篇博文 ...

  5. 关于Spring AOP中切点修饰符@annotation、@args与args约束说明

    前言 于其说这是一篇文章,不如说这是一篇笔记,主要介绍了@annotation.@args和args的作用以及一些坑点.这里主要记录一些项目用到的,没有成一套体系,网上其他文章对Spring AOP的 ...

  6. 简单好用!利用Spring AOP技术10分钟实现一个数据库读写分离方案

    前言 最近我们的APP在线用户越来越多,接口的响应速度也是越来越慢,经过运维排查发现是由于并发查询太多导致的数据库压力比较大,架构师经过调研给出了数据库读写分离的解决方案,为了快速解决问题,我们最终采 ...

  7. 简单好用!利用Spring AOP技术10分钟实现一个读写分离方案

    点击上方 好好学java ,选择 星标 公众号 重磅资讯.干货,第一时间送达今日推荐:2020年7月程序员工资统计,平均14357元,又跌了,扎心个人原创100W+访问量博客:点击前往,查看更多 作者 ...

  8. 【Spring AOP】基于注解的 AOP 编程

    Spring AOP 基于注解的 AOP 编程的开发 开发步骤 切入点复用 切换动态代理的创建方式(JDK.Cglib) AOP 开发中的一个坑(业务方法互相调用) AOP 知识总结 更多内容请查看笔 ...

  9. 实例简述Spring AOP之对AspectJ语法的支持

    Spring的AOP可以通过对@AspectJ注解的支持和在XML中配置来实现,本文通过实例简述如何在Spring中使用AspectJ. 一:使用AspectJ注解: 1,启用对AspectJ的支持: ...

最新文章

  1. php输出带的字符串吗,php输出含有“#”字符串的方法
  2. MATLAB常见语法错误分析及解决办法
  3. 【PAT (Advanced Level) Practice】1037 Magic Coupon (25 分)
  4. 028_jdbc-mysql大文本
  5. 前端如何实现音乐盒胶盘的转动_干货来袭!web前端开发工程师必看之如何使用CSS3实现瀑布流效果?...
  6. python解zuobiaoxi方程_滑坡稳定性分析程序初探---Python版!
  7. 学习hadoop需要什么基础
  8. HTTP 响应的分块传输
  9. python程序打包exe
  10. 一键安装lamp环境 centos
  11. spython_spython
  12. 一文读懂复权—不复权、前复权、后复权
  13. Unity3D世界坐标和局部坐标的关系,之间转换浅谈
  14. Guitar Pro8最新2023中文免费吉他乐谱作曲练习工具
  15. 程序员公众号用什么工具写?
  16. linux系统怎么连接显示器,Linux下笔记本外接显示器 · Eulerlee
  17. Java将OFD文件转PDF文件
  18. MemSQL性能测试结果
  19. 使用递归函数计算1到n之和
  20. Python解析html获取超链接地址并下载解析

热门文章

  1. idea的总部_Studio Didea新总部办公室,意大利 / Studio Didea
  2. 04737 c++ 自学考试2019版 第二章课后程序设计题 2
  3. 【Nginx那些事】nginx配置实例(三)动静分离
  4. NodeJs 的安装及配置环境变量
  5. 从头开始开发gis_DevRel工程师一:从头开始建立开发人员关系团队
  6. 亚马逊云服务开通指南_亚马逊弹性容器服务初学者指南
  7. Android获取通讯录速度,在android中获取联系人非常慢
  8. python怎么设计奥运五环_python 相关语法 图形绘制 奥运五环
  9. Linux编辑只读文件
  10. Common下MadieHelper.cs