热门标签 | HotTags
当前位置:  开发笔记 > Android > 正文

spring中AOP注解开发示例详解

这篇文章主要介绍了spring中AOP注解开发的相关资料,文中介绍的很详细,需要的朋友可以参考借鉴,下面来一起看看吧。

一、简介

AOP主要包含了通知、切点和连接点等术语,介绍如下:

通知(advice)

通知定义了切面是什么以及何时调用,何时调用包含以下几种

  • Before 在方法被调用之前调用通知
  • After 在方法完成之后调用通知,无论方法执行是否成功
  • After-returning 在方法成功执行之后调用通知
  • After-throwing 在方法抛出异常后调用通知
  • Around 通知包裹了被通知的方法,在被通知的方法调用之前和调用之后执行自定义的行为

切点(PointCut)

通知定义了切面的什么和何时,切点定义了何处,切点的定义会匹配通知所要织入的一个或多个连接点,
我们通常使用明确的类的方法名称来指定这些切点,或是利用正则表达式定义匹配的类和方法名称来指定这些切点。

连接点(JoinPoint)

连接点是在应用执行过程中能够插入切面的一个点,这个点可以是调用方法时,抛出异常时,甚至是修改一个字段时,
切面代码可以利用这些连接点插入到应用的正常流程中,并添加新的行为,如日志、安全、事务、缓存等。

  • joinPoint.getSignature().getDeclaringTypeName() 可以获取到调用方法的类名(包括包名),
  • joinPoint.getSignature().getName()    可以获取方法名,
  • Arrays.toString(joinPoint.getArgs())   得到的是方法调用的参数列表,
  • joinPoint.proceed()   可以得到方法的返回结果

二、注解开发

声明一个切面,只需要在类名上添加@Aspect属性即可,具体的连接点,我们用@Pointcut和@Before、@After等标注。
在声明前 我们需要依赖配置pom


 org.aspectj
 aspectjrt
 1.6.11


 org.aspectj
 aspectjweaver
 1.6.11

例子

package com.ganji.demo.service.aspect;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Service;
/**
 * Created by admin on 2015/9/2.
 */
@Aspect
@Service
public class XmlAopDemoUserLog {
// 配置切点 及要传的参数 
 @Pointcut("execution(* com.ganji.demo.service.user.UserService.GetDemoUser(..)) && args(id)")
 public void pointCut(int id)
 {
 }
// 配置连接点 方法开始执行时通知
 @Before("pointCut(id)")
 public void beforeLog(int id) {
  System.out.println("开始执行前置通知 日志记录:"+id);
 }
// 方法执行完后通知
 @After("pointCut(id)")
 public void afterLog(int id) {
  System.out.println("开始执行后置通知 日志记录:"+id);
 }
// 执行成功后通知
 @AfterReturning("pointCut(id)")
 public void afterReturningLog(int id) {
  System.out.println("方法成功执行后通知 日志记录:"+id);
 }
// 抛出异常后通知
 @AfterThrowing("pointCut(id)")
 public void afterThrowingLog(int id) {
  System.out.println("方法抛出异常后执行通知 日志记录"+id);
 }
// 环绕通知
 @Around("pointCut(id)")
 public Object aroundLog(ProceedingJoinPoint joinpoint,int id) {
  Object result = null;
  try {
   System.out.println("环绕通知开始 日志记录"+id);
   long start = System.currentTimeMillis();
   //有返回参数 则需返回值
   result = joinpoint.proceed();
   long end = System.currentTimeMillis();
   System.out.println("总共执行时长" + (end - start) + " 毫秒");
   System.out.println("环绕通知结束 日志记录");
  } catch (Throwable t) {
   System.out.println("出现错误");
  }
  return result;
 }
}

AOP切面中的同步问题

在WebLogAspect切面中,分别通过doBefore和doAfterReturning两个独立函数实现了切点头部和切点返回后执行的内容,
若我们想统计请求的处理时间,就需要在doBefore处记录时间,并在doAfterReturning处通过当前时间与开始处记录的时间计算
得到请求处理的消耗时间。

那么我们是否可以在WebLogAspect切面中定义一个成员变量来给doBefore和doAfterReturning一起访问呢?是否会有同步问题呢?

的确,直接在这里定义基本类型会有同步问题,所以我们可以引入ThreadLocal对象,像下面这样进行记录:

@Aspect
@Component
public class WebLogAspect {
 private Logger logger = Logger.getLogger(getClass());
 ThreadLocal startTime = new ThreadLocal<>();
 @Pointcut("execution(public * com.juzi.web..*.*(..))")
 public void webLog(){}
 @Before("webLog()")
 public void doBefore(JoinPoint joinPoint) throws Throwable {
  startTime.set(System.currentTimeMillis());
  // 省略日志记录内容
 }
 @AfterReturning(returning = "ret", pointcut = "webLog()")
 public void doAfterReturning(Object ret) throws Throwable {
  // 处理完请求,返回内容
  logger.info("RESPONSE : " + ret);
  logger.info("SPEND TIME : " + (System.currentTimeMillis() - startTime.get()));
 }
}

AOP切面的优先级

由于通过AOP实现,程序得到了很好的解耦,但是也会带来一些问题,比如:我们可能会对Web层做多个切面,校验用户,
校验头信息等等,这个时候经常会碰到切面的处理顺序问题。

所以,我们需要定义每个切面的优先级,我们需要@Order(i)注解来标识切面的优先级。i的值越小,优先级越高。
假设我们还有一个切面是CheckNameAspect用来校验name必须为didi,我们为其设置@Order(10),
而上文中WebLogAspect设置为@Order(5),所以WebLogAspect有更高的优先级,这个时候执行顺序是这样的:

在@Before中优先执行@Order(5)的内容,再执行@Order(10)的内容

在@After和@AfterReturning中优先执行@Order(10)的内容,再执行@Order(5)的内容

所以我们可以这样子总结:

  1. 在切入点前的操作,按order的值由小到大执行
  2. 在切入点后的操作,按order的值由大到小执行

总结

以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作能带来一定的帮助,如果有疑问大家可以留言交流。


推荐阅读
  • 本文详细介绍了如何在Linux系统上安装和配置Smokeping,以实现对网络链路质量的实时监控。通过详细的步骤和必要的依赖包安装,确保用户能够顺利完成部署并优化其网络性能监控。 ... [详细]
  • 本文详细介绍了Java编程语言中的核心概念和常见面试问题,包括集合类、数据结构、线程处理、Java虚拟机(JVM)、HTTP协议以及Git操作等方面的内容。通过深入分析每个主题,帮助读者更好地理解Java的关键特性和最佳实践。 ... [详细]
  • 基于KVM的SRIOV直通配置及性能测试
    SRIOV介绍、VF直通配置,以及包转发率性能测试小慢哥的原创文章,欢迎转载目录?1.SRIOV介绍?2.环境说明?3.开启SRIOV?4.生成VF?5.VF ... [详细]
  • 将Web服务部署到Tomcat
    本文介绍了如何在JDeveloper 12c中创建一个Java项目,并将其打包为Web服务,然后部署到Tomcat服务器。内容涵盖从项目创建、编写Web服务代码、配置相关XML文件到最终的本地部署和验证。 ... [详细]
  • Android LED 数字字体的应用与实现
    本文介绍了一种适用于 Android 应用的 LED 数字字体(digital font),并详细描述了其在 UI 设计中的应用场景及其实现方法。这种字体常用于视频、广告倒计时等场景,能够增强视觉效果。 ... [详细]
  • RecyclerView初步学习(一)
    RecyclerView初步学习(一)ReCyclerView提供了一种插件式的编程模式,除了提供ViewHolder缓存模式,还可以自定义动画,分割符,布局样式,相比于传统的ListVi ... [详细]
  • 本文介绍如何在 Unity 的 XML 配置文件中,将参数传递给自定义生命周期管理器的构造函数。我们将详细探讨 CustomLifetimeManager 类的实现及其配置方法。 ... [详细]
  • 本文详细介绍了 Java 中 org.apache.xmlbeans.SchemaType 类的 getBaseEnumType() 方法,提供了多个代码示例,并解释了其在不同场景下的使用方法。 ... [详细]
  • 本文详细介绍了如何解决MyBatis中常见的BindingException错误,提供了多种排查和修复方法,确保Mapper接口与XML文件的正确配置。 ... [详细]
  • 解决JAX-WS动态客户端工厂弃用问题并迁移到XFire
    在处理Java项目中的JAR包冲突时,我们遇到了JaxWsDynamicClientFactory被弃用的问题,并成功将其迁移到org.codehaus.xfire.client。本文详细介绍了这一过程及解决方案。 ... [详细]
  • 本文探讨了在通过 API 端点调用时,使用猫鼬(Mongoose)的 findOne 方法总是返回 null 的问题,并提供了详细的解决方案和建议。 ... [详细]
  • 探讨如何真正掌握Java EE,包括所需技能、工具和实践经验。资深软件教学总监李刚分享了对毕业生简历中常见问题的看法,并提供了详尽的标准。 ... [详细]
  • 本文介绍如何使用布局文件在Android应用中排列多行TextView和Button,使其占据屏幕的特定比例,并提供示例代码以帮助理解和实现。 ... [详细]
  • 本文探讨了在Windows Server 2008环境下配置Tomcat使用80端口时遇到的问题,包括端口被占用、多项目访问失败等,并提供详细的解决方法和配置建议。 ... [详细]
  • 本文详细介绍了Java Web应用程序中的过滤器(Filter)功能,包括其作用、实现方式及配置方法。过滤器可以在请求到达目标资源之前对其进行预处理,并在响应返回给客户端之前进行后处理。 ... [详细]
author-avatar
hbwgz2009
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有