AOP通知
1、通知类型
- 前置通知:方法执行前调用。
- 后置通知:方法执行后调用,无论是否有异常,都会执行。
- 返回通知:方法返回值返回前执行,如果有异常,无返回值,不会执行。
- 异常通知:出现异常时候的通知。可以指定异常的具体子类型。
- 环绕通知:类似代理整个过程的实现。一般不和其他几种通知同时使用。
2、 示例
pom.xml
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.mine</groupId>
<artifactId>spring-study</artifactId>
<version>0.0.1-SNAPSHOT</version>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.0.3.RELEASE</version>
</parent>
<dependencies>
<!-- SpringBoot整合Web组件 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
<!-- log -->
<!-- log4j通过slf4j来代理 -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>log4j-over-slf4j</artifactId>
</dependency>
<!-- apache commons logging通过slf4j来代理 -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>jcl-over-slf4j</artifactId>
</dependency>
<!-- java.util.logging 通过slf4j来代理 -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>jul-to-slf4j</artifactId>
</dependency>
<!-- log -->
</dependencies>
</project>
Caculator
package com.mine.aspectj.annotation.service;
public interface Caculator {
public int add(int i, int j);
public int sub(int i, int j);
public int mul(int i, int j);
public int div(int i, int j);
}
CaculatorImpl
package com.mine.aspectj.annotation.service.impl;
import org.springframework.stereotype.Service;
import com.mine.aspectj.annotation.service.Caculator;
@Service
public class CaculatorImpl implements Caculator {
public int add(int i, int j) {
return i + j;
}
public int sub(int i, int j) {
return i - j;
}
public int mul(int i, int j) {
return i * j;
}
public int div(int i, int j) {
return i / j;
}
}
LoggingAspect
package com.mine.aspectj.annotation.aspectj;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;
import lombok.extern.slf4j.Slf4j;
@Component
@Aspect
@Slf4j
public class LoggingAspect {
/**
* 声明切入点表达式
*/
@Pointcut("execution(* com.mine.aspectj.annotation.service..*.*(..))")
public void exec() {
}
/**
* 前置通知
*/
@Before("exec()")
public void before(JoinPoint joinpoit) {
String methodName = joinpoit.getSignature().getName();
log.info("before " + methodName);
}
/**
* 后置通知
*/
@After("exec()")
public void after(JoinPoint joinpoit) {
String methodName = joinpoit.getSignature().getName();
log.info("after " + methodName);
}
/**
* 返回通知
*/
@AfterReturning(value="exec()", returning="result")
public void afterReturning(JoinPoint joinpoit, Object result) {
String methodName = joinpoit.getSignature().getName();
log.info(methodName + " method return :" + result);
}
/**
* 异常通知
*/
@AfterThrowing(value = "exec()",throwing = "ex")
public void afterThrowing(JoinPoint joinpoit, ArithmeticException ex) {
String methodName = joinpoit.getSignature().getName();
log.info(methodName + " occur exception:" + ex);
}
/**
* 环绕通知
*/
@Around(value = "exec()")
public Object around(ProceedingJoinPoint joinpoit) {
String methodName = joinpoit.getSignature().getName();
try {
// 前置通知
log.info("around 前置通知 " + methodName);
// 执行方法
Object[] args = joinpoit.getArgs();
Object result = joinpoit.proceed(args);
// 返回通知
log.info("around 返回通知 " + methodName);
return result;
} catch (Throwable e) {
// 异常通知
log.error("around 异常通知 " + methodName);
e.printStackTrace();
} finally {
// 后置通知
log.info("around 后置通知 " + methodName);
}
return null;
}
}
AspectController
package com.mine.aspectj.annotation.controller;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.mine.aspectj.annotation.service.Caculator;
@RestController
@RequestMapping("/aspectj")
public class AspectController {
@Autowired
private Caculator caculator;
@RequestMapping("/add")
public int add(int i, int j) {
int result = caculator.add(i, j);
return result;
}
@RequestMapping("/sub")
public int sub(int i, int j) {
int result = caculator.sub(i, j);
return result;
}
@RequestMapping("/mul")
public int mul(int i, int j) {
int result = caculator.mul(i, j);
return result;
}
@RequestMapping("/div")
public int div(int i, int j) {
int result = caculator.div(i, j);
return result;
}
}