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;
}
}