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. docker 从容器中拷文件到宿主机器中

    sudo docker cp 1d051604e0ea:/root/data /home/developer/zhanghui/data

  2. 使用ShardingJdbc分表

    项目中做个统一订单的基础服务(只记录订单的基本的公共信息),1.便与后续各种其他业务的接入~ 2.同时APP端提供统一订单信息的查询入口,后续其他业务不用升级 由于统一的订单服务,所以订单量会很大,所 ...

  3. 推荐一个CSS类库

    animate.css 一个封装好的动画效果类

  4. ESX 5.0 上运行虚拟ESX

    如何在ESX上安裝ESX需注意幾點: 1.Guest OS選Linux / Red Hat Enterprise Linux 5 (64-bit) 2.使用SSH連線實體ESX主機下指令 添加*.vm ...

  5. attempt to index a nil value (global 'luasql')

    require ’socket‘ require ’luasql.mysql' 上述返回结果都是正常 但是执行 env = luasql.mysql(),报错: stdin:1: attempt to ...

  6. visual studio 下 C++生成dump文件

    1 lib配置 项目-->属性-->配置属性-->链接器-->输入-->附加依赖项 增加dbghelp.lib 2 头文件 #include <imagehlp.h ...

  7. "AppServer"--->UDP--->"LogWriteServer"

    w 是否应该将日志的“写”独立至局域网的一台或一群专门服务于“写日志”的服务器?这样让“app服务器”专职地处理用户的请求,而不必因为“写日志甚至异步分析日志”来降低用户体验? Spencer老师 其 ...

  8. Java 之网络编程

    网络模型 OSI 模型, 把网络通信的工作分为七层. TCP/IP 模型, 把网络通信的工作分为四层 应用层 传输层 网际层 主机至网络层 网络通信要素 (java.net 包) - IP 地址 (I ...

  9. Unity3d 面向对象设计思想(六)(Unity3d网络异步数据)

    在MonoBehavior类中有一个方法是StartCoroutine.里面要求的是一个接口为IEnumerator协同的返回值, 在Unity3d中,协同的作用是马上返回结果的.而不影响其它程序的运 ...

  10. (4.9)SQL Server 数据库规范

    SQL Server 数据库规范 一.       命名规范 常用对象命名规范,使用帕斯卡命名法(Pascal,单词首字母大写),统一使用英文. 1.        表.英文单数名词,尽量写完整单词名 ...