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. [LintCode] 有效回文串

    class Solution { public: /** * @param s A string * @return Whether the string is a valid palindrome ...

  2. delphi xe-intarweb 功能记录

    IWServerController.HistoryEnabled := True; //使浏览器后退.前进按钮有效TIWForm2.Create(WebApplication).Show;  //建 ...

  3. Sublime text找不到.so文件

    在使用Sublime text打开一个android项目的时候,你会发现找不到.so文件. 解决方法: 点击Sublime text的Preferences,然后点击Settings,这时候出现设置的 ...

  4. transaction 数据库事务 roolback 回滚

    事务是恢复和并发控制的基本单位 https://baike.baidu.com/item/数据库事务/9744607 事务有三种模型: 1.隐式事务是指每一条数据操作语句都自动地成为一个事务,事务的开 ...

  5. 【转】Spring中@Component的作用

    今天在写程序的时候看见一个以前没有见过的注解(@Component),在网上查找过后,经过实践,决定把它记录下来. 1.@controller 控制器(注入服务) 用于标注控制层,相当于struts中 ...

  6. MQ中间件对比

  7. stopPropagation(), preventDefault() , return false 事件

    因为有父, 子节点同在, 因为有监听事件和浏览器默认动作之分. 使用 JavaScript 时为了达到预期效果经常需要阻止事件和动作执行. 一般我们会用到三种方法, 分别是 stopPropagati ...

  8. Maven 整合SSH框架

    1. 传递依赖冲突 1.1 传递依赖:A(项目)依赖B,B依赖C(1.1版本),B是A的直接依赖,C是A的传递依赖; A(项目)又依赖D,D依赖C(1.2版本),此时,C有两个版本,产生冲突; 1.2 ...

  9. java基础08 双重循环打印图形

    public class Double01 { /** * 若有3个班级各4名学员参赛, * 如何计算每个班级参赛学员的平均分? */ public static void main(String[] ...

  10. 我的Android进阶之旅------>解决AES加密报错:java.security.InvalidKeyException: Unsupported key size: 18 bytes

    1.错误描述 今天使用AES进行加密时候,报错如下所示: 04-21 11:08:18.087 27501-27501/com.xtc.watch E/AESUtil.decryptAES:55: j ...