Spring AOP 提供全面的 AOP 解決方案。Spring 將 Spring AOP 和 IOC 與 AspectJ 無縫集成,以便在一致的 Spring-based application architecture 中知足 AOP 的全部使用需求。java
maven依賴添加以下
<!--引入SpringBoot的Web模塊-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!--引入AOP依賴-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
複製代碼
注意:在完成了引入AOP依賴包後,不須要去作其餘配置。AOP的默認配置屬性中,spring.aop.auto屬性默認是開啓的,也就是說只要引入了AOP依賴後,默認已經增長了@EnableAspectJAutoProxy,不須要在程序主類中增長@EnableAspectJAutoProxy來啓用。web
切面類使用@Aspect標註,必須加 @Component,使得切面類注入IOC容器管理spring
@Aspect
@Component
@Slf4j
public class TestLog {
@Pointcut("execution(* com.yuntian.example.controller.*.*(..))")
public void testLog() {
}
/**
* 前置通知,方法執行以前執行
* @param jp
*/
@Before("testLog()")
public void doBefore(JoinPoint jp) {
// ...
log.info("方法執行前:.............");
}
/**
* 後置通知,方法執行以後執行(無論是否發生異常)
* @param jp
*/
@After("testLog()")
public void doAfter(JoinPoint jp) {
// ...
log.info("方法執行後:.............");
}
/**
* 返回通知,方法正常執行完畢以後執行
* @param jp
*/
@AfterReturning("testLog()")
public void doAfterReturning(JoinPoint jp) {
// ...
log.info("方法執行後返回通知:.............");
}
/**
* 異常通知,在方法拋出異常以後執行
* @param jp
* @param e
*/
@AfterThrowing(value="testLog()",throwing="e")
public void doAfterThrowing(JoinPoint jp,Exception e) {
// ...
log.info("方法執行後異常:.............");
}
}
複製代碼
package com.yuntian.example.controller;
import com.yuntian.example.base.Result;
import com.yuntian.example.entity.dto.OrderDTO;
import com.yuntian.example.entity.vo.OrderVO;
import com.yuntian.example.service.OrderService;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;
/**
* @author yuntian.
* @date Created in 18:13 2019/8/7
* @description
*/
@RestController
@RequestMapping("order")
public class OrderController {
@Resource
private OrderService orderService;
@PostMapping("/createOrder")
public Result createOrder(OrderDTO dto){
OrderVO orderVO= orderService.createOrder(dto);
Result<OrderVO> result=new Result<>();
result.setData(orderVO);
result.setCode(99);
return result;
}
}
複製代碼
結果app
能夠看到切面類,實現邏輯同時,而對業務代碼毫無侵入。maven
@Aspect
@Component
@Slf4j
public class TestLogAround {
@Pointcut("execution(* com.yuntian.example.controller.*.*(..))")
public void testLogAround() {
}
/**
* 使用環繞通知
* @param pjp
* @return
*/
@Around("testLogAround()")
public Object doAround(ProceedingJoinPoint pjp){
Object obj=null;
try{
log.info("前置通知:執行以前");
obj=pjp.proceed();
log.info("返回通知:執行以後");
} catch(Throwable e){
log.info("異常通知:........!");
}
return obj;
}
}
複製代碼
結果spring-boot
@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface MTransaction {
@AliasFor("transactionManager")
String value() default "";
@AliasFor("value")
String transactionManager() default "";
int timeout() default -1;
boolean readOnly() default false;
Class<? extends Throwable>[] rollbackFor() default {};
String[] rollbackForClassName() default {};
Class<? extends Throwable>[] noRollbackFor() default {};
String[] noRollbackForClassName() default {};
}
@Component
@Slf4j
@Aspect
public class TransactionAspect {
@Pointcut("@annotation(com.yuntian.example.annotation.MTransaction)")
public void transactionAspect() {
}
/**
* 使用環繞通知
*
* @param pjp
* @return
*/
@Around("transactionAspect()")
public Object doAround(ProceedingJoinPoint pjp) {
//得到執行方法的類名
MethodSignature methodSignature = (MethodSignature) pjp.getSignature();
Method method = methodSignature.getMethod();
Object[] args= pjp.getArgs();
Object obj = null;
try {
log.info("前置通知:開啓事務...");
MTransaction transaction = method.getAnnotation(MTransaction.class);
if (transaction != null) {
log.info("註解信息:" + transaction.value());
}
log.info("參數:"+JSON.toJSONString(args));
obj = pjp.proceed();
log.info("返回通知:關閉事務...");
} catch (Throwable e) {
log.info("異常通知:事務回滾...");
}
return obj;
}
}
複製代碼
結果this
切入點是範圍內的全部類的方法spa
@Pointcut("execution(* com.yuntian.example.controller.*.*(..))")
複製代碼
切入點是註解的方法.net
@Pointcut("@annotation(com.yuntian.example.annotation.MTransaction)")
複製代碼
指示器 | 描述 |
---|---|
arg() | 限制鏈接點匹配參數爲指定類型的執行方法 |
@args() | 限制鏈接點匹配參數爲指定註解標註的執行方法 |
execution() | 用於匹配是鏈接點的執行方法 |
this() | 限制鏈接點匹配參數爲指定註解標註的執行方法 |
target | 限制鏈接點匹配目標對象爲指定類型的類 |
within() | 限制鏈接點匹配指定的類型 |
@within() | 限制鏈接點匹配指定註解鎖標註的類型(當使用Spring Aop時,方法定義由指定的註解所標註的類) |
@annotation | 限制匹配帶有指定註解的鏈接點 |