ITKeyword,专注技术干货聚合推荐

注册 | 登录

Spring AOP学习笔记(2):AOP前置通知&后置通知

lmy86263 分享于 2016-02-27

推荐:Spring AOP学习笔记(3):AOP返回通知&异常通知&环绕通知

一、 返回通知 返回通知,顾名思义,是在方法执行完成后,并且能够得到正常返回结果时要执行的代码,使用起来也非常简单,看下面的示例: @AfterReturning(value

2019阿里云全部产品优惠券(新购或升级都可以使用,强烈推荐)
领取地址https://promotion.aliyun.com/ntms/yunparter/invite.html

一、 使用AOP之前的配置

我使用Spring来完成AOP的配置,AOP和IoC作为Spring两项最主要的特点受到良好的支持,另外使用Maven作为构建工具,在使用AOP前,先加入依赖包,完成pom.xml文件。
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-beans</artifactId>
    <version>4.2.2.RELEASE</version>
</dependency>
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-context</artifactId>
    <version>4.2.2.RELEASE</version>
</dependency>
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-core</artifactId>
    <version>4.2.2.RELEASE</version>
</dependency>
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-aop</artifactId>
    <version>4.2.2.RELEASE</version>
</dependency>
<dependency>
    <groupId>org.aspectj</groupId>
    <artifactId>aspectjrt</artifactId>
    <version>1.8.8</version>
</dependency>
<dependency>
    <groupId>org.aspectj</groupId>
    <artifactId>aspectjweaver</artifactId>
    <version>1.8.8</version>
</dependency>

二、 AOP前置通知

在上一节中已经说到,连接点由表示连接的位置和程序执行点决定,这里首先说明前置通知,即在业务逻辑之前执行的功能。 先配置Spring的配置文件aop.xml:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:aop="http://www.springframework.org/schema/aop"
       xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
       http://www.springframework.org/schema/context  http://www.springframework.org/schema/context/spring-context.xsd
        http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd
        "
        >
    <context:component-scan base-package="com.spring"/>
    <aop:aspectj-autoproxy/>
</beans>
<context:component-scan base-package="**"/>这就不用说了吧,基本上用过Spring的都知道,但是这里有一个问题,是我自己犯傻了,在base-package中的包表示的是一类,即,如上代码中,不仅com.spring包能被扫描到,任何前缀是它的包都能被扫描,所以我把这开始时写的很细,导致切面类没有包含进去,傻傻地还一直在找错误。 <aop:aspectj-autoproxy /> 光是看名字就知道它是什么作用,它使Aspectj的注解起作用,并且自动为满足切点的类生成在理对象,必须配置。 然后建立一个简单的业务功能,例如计算器;
package com.spring.service;

import org.springframework.stereotype.Component;

@Component
public class Calculator {

    public int add(int i, int j){
        return i+j;
    }

    public int sub(int i, int j){
        return i-j;
    }

    public int time(int i, int j){
        return i*j;
    }

    public int divide(int i, int j){
        return i/j;
    }
}
然后新建一个切面类:
@Component
@Aspect
public class LoggingAspect {
    protected Logger logger = LoggerFactory.getLogger(this.getClass());
    /**/
}
切面类必须用@Aspect注解标明这是一个切面类,同时还需要把该切面类放到Spring的IoC容器中,

推荐:Spring详解-----------AOP通知、代理

通知参数  前边章节已经介绍了声明通知,但如果想获取被被通知方法参数并传递给通知方法,该如何实现呢?接下来我们将介绍两种获取通知参数的方式。 使用JoinPoi

所以这里用@Component注解标识,同时用slf4j来完成日志功能。 下面就是主要的内容,完成前置通知,前置通知就是在目标方法前执行,实现很简单,就是一个注释的使用。除了用注解还有xml配置方式,具体内容看下面的链接。
@Before("execution(public int com.spring.service.Calculator.*(int, int))")
public void loggingBefore(JoinPoint joinPoint){
    logger.info("method begin with name {} and args {}", joinPoint.getSignature().getName(), joinPoint.getArgs());
}
这个@Before和junit@Before千万不能弄混了,每次自动导入时都可能出现这样的问题。 @Before中需要写的是要绑定该Advice的切点表达式。这里用的是
execution(public int com.spring.service.Calculator.*(int, int))
关于切点表达式的内容很多,这里不具体讲,但是用到的最多的就是这里的execution表达式,它用来匹配方法执行的连接点,许多其他的表达式可以在本文下面给出的链接中找。 另外可以通过JoinPoint来访问目标Target信息,包括各种标识符和参数,非常方便。 下面可以对代码进行测试一下:
ApplicationContext context = new ClassPathXmlApplicationContext("aop.xml");
Calculator service = context.getBean(Calculator.class);
int result = service.add(1,2);
System.out.println(result);
得到结果如下:

三、 AOP后置通知

有前置通知,就有后置通知,其他的和前置通知没有什么区别,只是换了一个注解而已,代替@Before使用@After, 后置通知在目标方法执行后 执行,无论是否发生异常都会执行
@After("execution(public int com.spring.service.Calculator.*(int, int))")
public void loggingAfter(JoinPoint joinPoint){
    logger.info("method end");
}
测试代码类似上边如下:
ApplicationContext context = new ClassPathXmlApplicationContext("aop.xml");
Calculator service = context.getBean(Calculator.class);
int result = service.divide(1,2);
System.out.println(result);
结果如下:
但是又有另外的结果如下:对于这个我不是很明白,是不是后置通知在另外的线程运行,我不是很确定,如果有大神能够指出,感激不尽。
另外在发生异常时,依然能够完成通知,结果如下:
另外要注意的 在后置通知中不能访问目标方法执行后返回的结果,要实现这一点要看下一节。
相关文章:

推荐:spring aop 环绕通知 基于@aspectJ

前言:      Spring 的环绕通知和前置通知,后置通知有着很大的区别,主要有两个重要的区别: 1) 目标方法的调用由环绕通知决定,即你可以决定是否调用目标方法

一、 使用AOP之前的配置 我使用Spring来完成AOP的配置,AOP和IoC作为Spring两项最主要的特点受到良好的支持,另外使用Maven作为构建工具,在使用AOP前,先加入依赖包,完成pom.xml文件。 <depen

相关阅读排行


用户评论

游客

相关内容推荐

最新文章

×

×

请激活账号

为了能正常使用评论、编辑功能及以后陆续为用户提供的其他产品,请激活账号。

您的注册邮箱: 修改

重新发送激活邮件 进入我的邮箱

如果您没有收到激活邮件,请注意检查垃圾箱。