Spring中可以使用注解或XML文件配置的方式实现AOP。
1、导入jar包

  • com.springsource.net.sf.cglib -2.2.0.jar
  • com.springsource.org.aopalliance-1.0.0 .jar
  • com.springsource.org.aspectj.weaver-1.6.8 .RELEASE.jar
  • commons-logging-1.1.3. jar
  • spring-aop-4.0.0.RELEASE.jar
  • spring-aspects-4.0.0.RELEASE.jar
  • spring-beans-4.0.0.RELEASE.jar
  • spring-context-4.0.0.RELEASE.jar
  • spring-core-4.0.0.RELEASE.jar
  • spring-expression-4.0.0.RELEASE.jar

aspectaop相关jar包 ---> 资源目录--->jar包资源--->AOP日志打印相关jar包(切面类)

Spring相关jar包 ---> 资源目录--->jar包资源--->Spring相关jar包

2、开启基于注解的AOP功能

在Spring的配置文件中加入

<context:component-scan base-package="com.bwlu.aop"></context:component-scan>
<aop:aspectj-autoproxy></aop:aspectj-autoproxy>

3、声明一个切面类,并把这个切面类加入到IOC容器中

 @Component//加入IOC容器
@Aspect//表示这是一个切面类
public class LogAspect{
//value中为切入点表达式
@Before(value="execution(public void com.bwlu.common.MathCalculatorImpl.*(..))")//前置通知
public void showBeginLog(){
System.out.println("AOP日志开始");
}
@After(value="execution(public void com.bwlu.common.MathCalculatorImpl.*(..))")//后置通知
public void showReturnLog(){
System.out.println("AOP方法结束");
}
@AfterThrowing(value="execution(public void com.bwlu.common.MathCalculatorImpl.*(..))")//异常通知
public void showExceptionLog(){
System.out.println("AOP方法异常");
}
@AfterReturning(value="execution(public void com.bwlu.common.MathCalculatorImpl.*(..))")//返回通知
public void showAfterLog(){
System.out.println("AOP方法最终返回");
}
}

4、被代理的对象也需要加入IOC容器

 @Component
public class MathCalculator {
public void add(int i, int j) {
int result=i+j;
System.out.println("目标方法add(int)执行了");
}
public void sub(int i, int j) {
int result=i-j;
System.out.println("目标方法sub执行了");
}
public void mult(int i, int j) {
int result=i*j;
System.out.println("目标方法mult执行了");
}
public void div(int i, int j) {
int result=i/j;
System.out.println("目标方法div执行了");
}
}

MathCalculator

5、新建Junit测试类进行测试

 ApplicationContext ioc=new ClassPathXmlApplicationContext("applicationContext.xml");
@Test
public void test() {
//需要进行强转,如果该类实现了一个接口(并且切入点表达式指向这个类),那么获取到的将不是该类的对象,需要强转
//MathCalculatorImpl实现了MathCalculator接口,则
//MathCalculator bean = (MathCalculator)ioc.getBean("mathCalculatorImpl");
MathCalculator bean = (MathCalculator)ioc.getBean("mathCalculator");
bean.add(10, 5);
System.out.println();
bean.add(10.0, 5);
System.out.println();
bean.sub(10, 5);
System.out.println();
bean.mult(10, 5);
System.out.println();
bean.div(10, 0);
}

6、切入点表达式

  • 切入点表达式的语法格式

execution([权限修饰符] [返回值类型] [简单类名/全类名] [方法名]([参数列表]))

  • 切入点表达式支持通配符
  • 两种切入表达式
    • 最详细的切入点表达式:

execution(public void com.bwlu.aop.MathCalculator.add(int, int))

    • 最模糊的切入点表达式:

execution (* *.*(..))

execution(public void com.bwlu.aop.MathCalculator.add(int, int)):只有add方法加入了4个通知,

execution(public void com.bwlu.aop.MathCalculator.*(int, int)):任意方法,参数为int,int

execution(public void com.bwlu.aop.MathCalculator.*(..)):MathCalculator中的任意方法,任意参数列表

execution(public * com.bwlu.aop.MathCalculator.*(..)):MathCalculator中的任意方法,任意参数列表,任意返回值

execution( * com.bwlu.aop.MathCalculator.*(..)):MathCalculator中的任意方法,任意参数列表,任意返回值,任意访问修饰符

execution (* *.*(..)):任意匹配

需要注意的是:权限是不支持写通配符的,当然你可以写一个*表示所有权限所有返回值!

7、优化

用@PointCut注解统一声明,然后在其它通知中引用该统一声明即可!

 @Component
@Aspect
public class LogAspect{
@Pointcut(value="execution(* *.*(..))")
public void showLog(){}
@Before(value="showLog()")
public void showBeginLog(){
System.out.println("AOP日志开始");
}
@After(value="showLog()")
public void showReturnLog(){
System.out.println("AOP方法结束");
}
@AfterThrowing(value="showLog()")
public void showExceptionLog(){
System.out.println("AOP方法异常");
}
@AfterReturning(value="showLog()")
public void showAfterLog(){
System.out.println("AOP方法最终返回");
}
}

LogAspect

8、通知方法的细节

(1)在通知中获取目标方法的方法名和参数列表

  • 在通知方法中声明一个JoinPoint类型的形参
  • 调用JoinPoint对象的getSignature()方法获取目标方法的签名
  • 调用JoinPoint对象的getArgs()方法获取目标方法的实际参数列表

(2)在返回通知中获取方法的返回值

  • 在@AfterReturning注解中添加returning属性:@AfterReturning (value="showLog()", returning= "result")
  • 在返回通知的通知方法中声明一个形参,形参名和returning属性的值一致:showReturnLog(JoinPoint joinPoint, Object result)

(3)在异常通知中获取异常对象

  • 在@ AfterThrowing注解中添加throwing属性:@AfterThrowing (value="showLog()",throwing= "throwable" )
  • 在异常通知的通知方法中声明一个形参,形参名和throwing属性值一致:showExceptinLog(JoinPoint joinPoint, Throwable throwable)
 @Component
@Aspect
public class LogAspect{
@Pointcut(value="execution(* *.*(..))")
public void showLog(){}
@Before(value="showLog()")
public void showBeginLog(JoinPoint jPoint){
Object[] args = jPoint.getArgs();
List<Object> asList = Arrays.asList(args);
Signature signature = jPoint.getSignature();
String name = signature.getName();
System.out.println("AOP日志开始");
System.out.println("目标方法名:"+name+",参数列表:"+asList);
}
@After(value="showLog()")
public void showReturnLog(){
System.out.println("AOP方法结束");
}
@AfterThrowing(value="showLog()",throwing="ex")
public void showExceptionLog(Exception ex){
System.out.println("AOP方法异常");
System.out.println("异常信息:"+ex.getMessage());
}
@AfterReturning(value="showLog()",returning="result")
public void showAfterLog(Object result){
System.out.println("方法返回值:"+result);
System.out.println("AOP方法最终返回");
}
}

LogAspect

9、环绕通知@Around

环绕通知需要在方法的参数中指定JoinPoint的子接口类型ProceedingJoinPoint为参数:

public void around(ProceedingJoinPoint joinPoint){}

环绕通知能够替代其他4个通知。
注意:@Around修饰的方法一定要将方法的返回值返回!本身相当于代理!

 @Component
@Aspect
public class LogAspect{
@Around(value="execution(* *.*(..))")
public Object showLog(ProceedingJoinPoint point){
Object[] args = point.getArgs();
List<Object> asList = Arrays.asList(args);
Signature signature = point.getSignature();
String name = signature.getName();
Object result = null;
try {
try {
//目标方法之前要执行的操作,相当于@before
System.out.println("[环绕日志]"+name+"开始了,参数为:"+asList);
//调用目标方法
result = point.proceed(args);
} finally {
//方法最终结束时执行的操作,相当于@after
System.out.println("[环绕日志]"+name+"结束了!");
}
//目标方法正常执行之后的操作,相当于@AfterReturning
System.out.println("[环绕日志]"+name+"返回了,返回值为:"+result);
} catch (Throwable e) {
//目标方法抛出异常信息之后的操作,相当于@AfterThrowing
System.out.println("[环绕日志]"+name+"出异常了,异常对象为:"+e);
throw new RuntimeException(e.getMessage());
}
return result;
}
}

LogAspect

10、切面的优先级

对于同一个代理对象,可以同时有多个切面共同对它进行代理。
可以在切面类上通过@Order (value=50)注解来进行设置,值越小优先级越高!

@Aspect

@Component

@Order(value=40)

public class LogAspect {}

简单的aop实现日志打印(切入点表达式)的更多相关文章

  1. Spring事务管理—aop:pointcut expression 常见切入点表达式及事务说明

    Spring事务管理—aop:pointcut expression 常见切入点表达式及事物说明 例: <aop:config>  <aop:pointcut expression= ...

  2. 基于XML配置的AOP实现日志打印

    Spring中可以使用注解或XML文件配置的方式实现AOP.1.导入jar包 com.springsource.net.sf.cglib -2.2.0.jar com.springsource.org ...

  3. Spring事务管理—aop:pointcut expression 常见切入点表达式及事物说明

    例: <aop:config>  <aop:pointcut expression="execution(* com.xy.service.*.*(..))"   ...

  4. spring的基于xml的AOP配置案例和切入点表达式的一些写法

    <?xml version="1.0" encoding="UTF-8"?><beans xmlns="http://www.spr ...

  5. AOP统一日志打印处理

    在日常开发工作中,我们免不了要打印很多log.而大部分需要输出的log又是重复的(例如传入参数,返回值).因此,通过AOP方式来进行日志管理可以减少很多代码量,也更加优雅. Springboot通过A ...

  6. 使用Spring AOP 实现日志管理(简单教程)

    有时候,我们在做项目时会遇到这样的需求: 给XXX.java中的所有方法加上指定格式的日志输出. 针对这种指定类.或者指定方法进行共性操作的功能,我们完全可以使用Spring AOP来实现. 本文使用 ...

  7. 【Java EE 学习 76 下】【数据采集系统第八天】【通过AOP实现日志管理】【日志管理功能分析和初步实现】

    一.日志管理相关分析 1.日志管理是一种典型的系统级别的应用,非常适合使用spring AOP实现. 2.使用日志管理的目的:对系统修改的动作进行记录,比如对权限.角色.用户的写操作.修改操作.删除操 ...

  8. Spring(三)--AOP【面向切面编程】、通知类型及使用、切入点表达式

    1.概念:Aspect Oriented Programming 面向切面编程 在方法的前后添加方法   2.作用:本质上来说是一种简化代码的方式      继承机制      封装方法      动 ...

  9. [原创]java WEB学习笔记105:Spring学习---AOP介绍,相关概念,使用AOP,利用 方法签名 编写 AspectJ 切入点表达式

    本博客的目的:①总结自己的学习过程,相当于学习笔记 ②将自己的经验分享给大家,相互学习,互相交流,不可商用 内容难免出现问题,欢迎指正,交流,探讨,可以留言,也可以通过以下方式联系. 本人互联网技术爱 ...

随机推荐

  1. NATS源代码分析之auth目录

    NATS是一个轻量的消息发布-订阅系统.NATS的核心是Event machine. 项目Server端源代码地址: github.com/nats-io/gnatsd 在auth目录中, multi ...

  2. 【BZOJ4543】[POI2014]Hotel加强版 长链剖分+DP

    [BZOJ4543][POI2014]Hotel加强版 Description 同OJ3522数据范围:n<=100000 Sample Input 7 1 2 5 7 2 5 2 3 5 6 ...

  3. Powershell Exchange Server UP Time

    Server up time Get-ExchangeServer | where{$_.name -like'wendy*'} | %{ if(Test-Connection $_.name -Co ...

  4. Phonetic Symbols&Rules of Pronunciation

    音标 Phonetic Symbols http://yinbiao.tingclass.net/ 1.1元音 1.1.元音:元音有20个,其中单元音12个,双元音8个. (1)“短”单元音 [i] ...

  5. window下使用mysql,报未定义标识符"SOCKET"

    解决方法一: 这个错误是在VC中使用MySQL数据库时出现在mysql_com.h文件中的  my_socket fd; 说明未my_socket未定义,这时只需要在引用mysql.h头文件之前引用# ...

  6. 版本号风格为 Major.Minor.Patch

    旧版本兼容 · 小程序 https://developers.weixin.qq.com/miniprogram/dev/framework/compatibility.html 微信客户端和小程序基 ...

  7. 转!!ftp的主动模式(port)与被动模式(PASV)

    转自 http://www.phpweblog.net/killjin/archive/2008/01/06/2653.html   ftp中主动模式(port)与被动模式(PASV) 目录 开场白 ...

  8. django的项目创建简明流程

    个人理解,不妥之处请指出 创建项目:django-admin startproject user_sys 创建APP:python manage.py startapp auth 测试项目创建是否成功 ...

  9. java-序列化-001-原生介绍

    一.什么是对象序列化 java平台允许我们在内存中创建可复用的Java对象,但一般情况下,只有当JVM处于运行时,这些对象才可能存在,即,这些对象的生命周期不会比JVM的生命周期更长.但在现实应用中, ...

  10. DBMS_MONITOR程序开启10046事件

    在具有连接池或共享服务器的多层环境中,一个会话可以跨越多个进程,甚至跨越多个实例.DBMS_MONITOR是在Oracle 10g中引入的内置的程序包,通过该程序包可以跟踪从客户机到中间层.再到后端数 ...