简单的aop实现日志打印(切入点表达式)
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实现日志打印(切入点表达式)的更多相关文章
- Spring事务管理—aop:pointcut expression 常见切入点表达式及事务说明
Spring事务管理—aop:pointcut expression 常见切入点表达式及事物说明 例: <aop:config> <aop:pointcut expression= ...
- 基于XML配置的AOP实现日志打印
Spring中可以使用注解或XML文件配置的方式实现AOP.1.导入jar包 com.springsource.net.sf.cglib -2.2.0.jar com.springsource.org ...
- Spring事务管理—aop:pointcut expression 常见切入点表达式及事物说明
例: <aop:config> <aop:pointcut expression="execution(* com.xy.service.*.*(..))" ...
- spring的基于xml的AOP配置案例和切入点表达式的一些写法
<?xml version="1.0" encoding="UTF-8"?><beans xmlns="http://www.spr ...
- AOP统一日志打印处理
在日常开发工作中,我们免不了要打印很多log.而大部分需要输出的log又是重复的(例如传入参数,返回值).因此,通过AOP方式来进行日志管理可以减少很多代码量,也更加优雅. Springboot通过A ...
- 使用Spring AOP 实现日志管理(简单教程)
有时候,我们在做项目时会遇到这样的需求: 给XXX.java中的所有方法加上指定格式的日志输出. 针对这种指定类.或者指定方法进行共性操作的功能,我们完全可以使用Spring AOP来实现. 本文使用 ...
- 【Java EE 学习 76 下】【数据采集系统第八天】【通过AOP实现日志管理】【日志管理功能分析和初步实现】
一.日志管理相关分析 1.日志管理是一种典型的系统级别的应用,非常适合使用spring AOP实现. 2.使用日志管理的目的:对系统修改的动作进行记录,比如对权限.角色.用户的写操作.修改操作.删除操 ...
- Spring(三)--AOP【面向切面编程】、通知类型及使用、切入点表达式
1.概念:Aspect Oriented Programming 面向切面编程 在方法的前后添加方法 2.作用:本质上来说是一种简化代码的方式 继承机制 封装方法 动 ...
- [原创]java WEB学习笔记105:Spring学习---AOP介绍,相关概念,使用AOP,利用 方法签名 编写 AspectJ 切入点表达式
本博客的目的:①总结自己的学习过程,相当于学习笔记 ②将自己的经验分享给大家,相互学习,互相交流,不可商用 内容难免出现问题,欢迎指正,交流,探讨,可以留言,也可以通过以下方式联系. 本人互联网技术爱 ...
随机推荐
- NATS源代码分析之auth目录
NATS是一个轻量的消息发布-订阅系统.NATS的核心是Event machine. 项目Server端源代码地址: github.com/nats-io/gnatsd 在auth目录中, multi ...
- 【BZOJ4543】[POI2014]Hotel加强版 长链剖分+DP
[BZOJ4543][POI2014]Hotel加强版 Description 同OJ3522数据范围:n<=100000 Sample Input 7 1 2 5 7 2 5 2 3 5 6 ...
- Powershell Exchange Server UP Time
Server up time Get-ExchangeServer | where{$_.name -like'wendy*'} | %{ if(Test-Connection $_.name -Co ...
- Phonetic Symbols&Rules of Pronunciation
音标 Phonetic Symbols http://yinbiao.tingclass.net/ 1.1元音 1.1.元音:元音有20个,其中单元音12个,双元音8个. (1)“短”单元音 [i] ...
- window下使用mysql,报未定义标识符"SOCKET"
解决方法一: 这个错误是在VC中使用MySQL数据库时出现在mysql_com.h文件中的 my_socket fd; 说明未my_socket未定义,这时只需要在引用mysql.h头文件之前引用# ...
- 版本号风格为 Major.Minor.Patch
旧版本兼容 · 小程序 https://developers.weixin.qq.com/miniprogram/dev/framework/compatibility.html 微信客户端和小程序基 ...
- 转!!ftp的主动模式(port)与被动模式(PASV)
转自 http://www.phpweblog.net/killjin/archive/2008/01/06/2653.html ftp中主动模式(port)与被动模式(PASV) 目录 开场白 ...
- django的项目创建简明流程
个人理解,不妥之处请指出 创建项目:django-admin startproject user_sys 创建APP:python manage.py startapp auth 测试项目创建是否成功 ...
- java-序列化-001-原生介绍
一.什么是对象序列化 java平台允许我们在内存中创建可复用的Java对象,但一般情况下,只有当JVM处于运行时,这些对象才可能存在,即,这些对象的生命周期不会比JVM的生命周期更长.但在现实应用中, ...
- DBMS_MONITOR程序开启10046事件
在具有连接池或共享服务器的多层环境中,一个会话可以跨越多个进程,甚至跨越多个实例.DBMS_MONITOR是在Oracle 10g中引入的内置的程序包,通过该程序包可以跟踪从客户机到中间层.再到后端数 ...