Aspect
前言
Github:https://github.com/HealerJean
1、Aspect
1.1、pom依赖
<!-- aop 切面 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
1.2、Service
1.2.1、接口 DemoEntityService
package com.healerjean.proj.service;
import com.healerjean.proj.dto.Demo.DemoDTO;
public interface DemoEntityService {
DemoDTO getMmethod(DemoDTO demoEntity);
}
1.2.2、DemoEntityServiceImpl
@Service
@Slf4j
public class DemoEntityServiceImpl implements DemoEntityService {
@Override
public DemoDTO getMmethod(DemoDTO demoEntity) {
log.info("Service--------getMmethod");
// int i = 1/0;
return demoEntity;
}
}
1.3、Aspect
package com.healerjean.proj.config.aspect;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
@Component
@Aspect //当前类标识为一个切面供容器读取 ,、@Aspect放在类头上,把这个类作为一个切面。
@Order(2) // 控制多个Aspect的执行顺序,越小越先执行
@Slf4j
public class AspectStyleMethod {
/**
* @Pointcut 放在方法头上,定义一个可被别的方法引用的切入点表达式
*/
@Pointcut("execution(* com.healerjean.proj.service.*Service.*(..))")
private void anyMethod() {
}
/**
* @Before 标识一个前置增强方法
*/
@Before("anyMethod()")
public void before() {
log.info("@Before");
}
/**
* @After: final增强,不管是抛出异常或者正常退出都会执行
*/
@After("anyMethod()")
public void after() {
log.info("@After");
}
/**
* @AfterReturning :后置增强,方法正常退出时执行(有了异常就不会执行)
*/
@AfterReturning("anyMethod()")
public void afterReturning() {
log.info("@AfterReturning");
}
/**
* @AfterThrowing: 异常抛出增强,(有了异常才会执行,否则不能够执行(在around异常处理之前执行))
*/
@AfterThrowing("anyMethod()")
public void afterThrowing() {
log.info(" @AfterThrowing");
}
/**
* 正常调用
* @Around: 环绕增强
*/
@Around("anyMethod()")
public Object doBasicProfiling(ProceedingJoinPoint pjp) throws Throwable {
log.info("@Around pjp.proceed() 准备执行");
Object object = pjp.proceed();
//下面的log.info不会执行,因为AspectStyleService中有了异常,所以不会到这一步
log.info("@Around pjp.proceed() 执行完毕");
return object;
}
}
1.3.1、正常调用
@Before
,@After
是在方法pjp.proceed()
执行的前后
@Around pjp.proceed() 准备执行 com
@Before
Service--------getMmethod com.
@Around pjp.proceed() 执行完毕
@After
@AfterReturning
1.3.2、异常不捕获
@Around pjp.proceed() 准备执行
@Before
Service--------getMmethod
@After
@AfterThrowing
1.3.3、异常捕获
@Around
先捕获异常,然后才执行@After
,@AfterThrowing
/**
* 异常捕获
* @Around: 环绕增强
*/
@Around("anyMethod()")
public Object doBasicProfiling(ProceedingJoinPoint pjp) throws Throwable {
log.info("@Around pjp.proceed() 准备执行");
try {
Object object = pjp.proceed();
//下面的log.info不会执行,因为AspectStyleService中有了异常,所以不会到这一步
log.info("@Around pjp.proceed() 正常执行完毕");
return object;
} catch (Exception e) {
log.info("@Around pjp.proceed() 出错:{}", e.getMessage());
throw e;
}
}
@Around pjp.proceed() 准备执行
@Before
Service--------getMmethod
@Around pjp.proceed() 出错:/ by zero
@After
@AfterThrowing
1.4、@Pointcut
@Pointcut(“execution(* com.healerjean.proj.service.Service.(..))”)
* 匹配任意字符,但只能匹配一个元素
.. 匹配任意字符,可以匹配任意多个元素,表示类时,必须和*联合使用
+ 必须跟在类名后面,如Horseman+,表示类本身和继承或扩展指定类的所有类
1、类切面
@Pointcut("execution(* com.healerjean.proj.controller.*Controller.*(..))")
2、包切面
@Pointcut("execution(* com.jdd.baoxian.core.trade.merchant..*(..))")
1、execution(public * * (. .)) 任意公共方法被执行时,执行切入点函数。
2、execution( * set* (. .)) 任何以一个“set”开始的方法被执行时,执行切入点函数。
3、execution( * com.demo.service.AccountService.*(..)) 当接口AccountService 中的任意方法被执行时,执行切入点函数。
4、execution( * com.demo.service..*(..)) 当service 包中的任意方法被执行时,执行切入点函数。
多个切点
@Around("execution(* com.fintech.manager.controller.*.*Controller.*(..))" +
"|| execution(* com.fintech.manager.task.*Task.*(..))")