gitee地址:SpringBoot面向切面编程
<parent> <artifactId>spring-boot-starter-parent</artifactId> <groupId>org.springframework.boot</groupId> <version>2.1.0.RELEASE</version> </parent> <dependencies> <!--测试--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> </dependency> <!--切面依赖--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-aop</artifactId> </dependency> </dependencies>
public interface ExampleService { String findAll(String name); boolean save(); boolean update(); boolean delete(); }
import com.qq.annotation.Sign; import com.qq.service.ExampleService; import org.springframework.stereotype.Service; /** * @author 黔程似景 * @description 业务代码 * @date 2021/12/5 9:55 **/ @Service public class ExampleServiceImpl implements ExampleService { @Override public String findAll(String name) { System.out.println("---------------------所有数据-------------------------"); return name; } @Sign @Override public boolean save() { System.out.println("---------------------保存成功-------------------------"); return true; } @Override public boolean update() { System.out.println("---------------------修改成功-------------------------"); return true; } @Override public boolean delete() { System.out.println("---------------------删除成功-------------------------"); return true; } }
import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; @Target({ElementType.METHOD,ElementType.TYPE}) @Retention(RetentionPolicy.RUNTIME) public @interface Sign { }
import org.aspectj.lang.JoinPoint; import org.aspectj.lang.ProceedingJoinPoint; import org.aspectj.lang.Signature; import org.aspectj.lang.annotation.*; import org.springframework.stereotype.Component; import java.util.Arrays; /** * @author 黔程似景 * @description 切面类 * @date 2021/12/5 9:58 **/ @Aspect // 标注此类为切面类 @Component public class AopConfig { /** * 切入点 */ @Pointcut("@annotation(com.qq.annotation.Sign) || execution(* com.qq.service..*.find*(..))") public void pointcut(){ } /** * 前置通知:在执行方法前执行 */ @Before(value = "pointcut()") public void before(JoinPoint joinPoint){ System.out.println("--------------前置通知-----------------"); Signature signature = joinPoint.getSignature(); System.out.println("获取方法:"+signature); Object[] args = joinPoint.getArgs(); System.out.println("获取传入参数:"+Arrays.toString(args)); } /** * 异常通知:在执行方法出现异常时执行 */ @AfterThrowing(value = "pointcut()") public void afterThrow(JoinPoint joinPoint){ System.out.println("--------------异常通知------------------"); System.out.println("异常方法:"+joinPoint.getSignature()); } /** * 后置通知:在执行方法后执行,无论是否出现异常,则都会执行 */ @After(value = "pointcut()") public void after(){ System.out.println("---------------后置通知-----------------"); } /** * 最终通知:当出现异常,则不会执行 */ @AfterReturning(value = "pointcut()" , returning = "result") public void afterReturning(Object result){ System.out.println("目标方法返回值:"+result); } // /** // * 环绕通知(包含前置通知,后置通知,异常通知,最终通知) // * 执行顺序:前置通知--->后置通知(异常通知)--->最终通知 // * @param joinPoint // * @return // */ // @Around(value = "pointcut()") // public Object around(ProceedingJoinPoint joinPoint) { // // Object rvt = null;//不改变参数 // try { // System.out.println("----------------前置通知------------------"); // rvt = joinPoint.proceed(); Object rvt = jp.proceed(new String[] { "被改变的参数" }); // System.out.println("----------------后置通知------------------"); // } catch (Throwable throwable) { // System.out.println("----------------异常通知------------------"); // throwable.printStackTrace(); // }finally { // System.out.println("----------------最终通知------------------"); // } // // return rvt + " 新增的内容"; // } }
import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; @SpringBootApplication public class AopApplication { public static void main(String[] args) { SpringApplication.run(AopApplication.class, args); } }
import com.qq.service.ExampleService; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.test.context.junit4.SpringRunner; import javax.annotation.Resource; /** * @author 黔程似景 * @description 测试类 * @date 2021/12/5 10:03 **/ @RunWith(SpringRunner.class) @SpringBootTest public class TestExampleService { @Resource public ExampleService exampleService; /** * 切面测试 */ @Test public void test() { exampleService.findAll("法外狂徒"); System.out.println("\n\n\n"); exampleService.save(); System.out.println("\n\n\n"); exampleService.update(); } }
切入点函数 | 作用 |
---|---|
execution | 细粒度函数,精确到方法 |
within | 粗粒度,只能精确到类 |
bean | 粗粒度,精确到类,从容器中通过id获取对象 |
@annotation | 包含注解的所有类和方法 |
execution(* *(..)) 匹配所有的类和方法 !execution(* save(..)) 除了方法名是save的所有方法 方法参数设置: () 没有参数 (*) 1个或多个参数 (..) 0个或多个参数 例如:find()----->无参方法
execution(* save(..)) || execution(* update(..)) 匹配方法名是save或update的方法
within(com.qq..*) 匹配包和子包中所有的类
bean(exampleService) 从容器中获取一个id为accountService的类中所有方法
bean(*Service) 从容器中获取所有Service的方法
@annotation(com.qq.annotation.Sign) 匹配包含注解的所有类和方法