环绕通知的基本概念

它是通过拦截目标方法的方式,在目标方法的前后增强功能的通知。它是功能最强大的通知,一般事务使用此通知。它可以轻易的改变目标方法的返回值。

环绕通知执行流程分析

环绕通知的方法 (切面方法的返回值(就是目标方法的返回值) myAruond (切面方法的参数(就是目标方法本身)))

目标方法的前切功能的实现

目标方法

  1. public String doSome(){
  2. return "abcd";
  3. }

调用目标方法

  1. Object obj = doSome();

目标方法的后切功能的实现

环绕通知代码实现

业务

  1. package com.chentianyu.s03;
  2. public interface SomeService {
  3. String doSome(String name,int age);
  4. }

业务实现类

  1. package com.chentianyu.s03;
  2. import org.springframework.stereotype.Service;
  3. @Service
  4. public class SomeServiceImpl implements SomeService {
  5. @Override
  6. public String doSome(String name, int age) {
  7. System.out.println("doSome业务方法被执行了..."+name);
  8. return "abcd";
  9. }
  10. }

切面类

  1. package com.chentianyu.s03;
  2. import org.aspectj.lang.ProceedingJoinPoint;
  3. import org.aspectj.lang.annotation.Aspect;
  4. import org.springframework.stereotype.Component;
  5. @Aspect
  6. @Component
  7. public class MyAspect {
  8. /**
  9. * 环绕通知方法的规范
  10. * 1.访问权限:public
  11. * 2.切面方法有返回值,此返回值就是目标方法的返回值
  12. * 3.方法名自定义
  13. * 4.方法有参数,此参数就是目标方法本身
  14. * 5.回避异常Throwable(目标方法传过来,通过反射去调用)
  15. * 6.使用@Around声明是环绕通知
  16. * value: 指定切入点表达式
  17. */
  18. @Around(value = "execution(* com.chentianyu.s03.*.*(..))")
  19. public Object myAround(ProceedingJoinPoint/*通过这个接口的实现类去我们需要的目标方法*/ pjp) throws Throwable {
  20. //前切功能实现
  21. System.out.println("环绕通知中的前置功能实现...");
  22. //目标方法调用
  23. Object obj = pjp.proceed(pjp.getArgs());
  24. //后切功能实现
  25. System.out.println("环绕通知中的后置功能实现...");
  26. return obj.toString().toUpperCase();//改变了目标方法的返回值
  27. }
  28. }

配置文件

  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <beans xmlns="http://www.springframework.org/schema/beans"
  3. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop"
  4. xmlns:context="http://www.springframework.org/schema/context"
  5. xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/aop https://www.springframework.org/schema/aop/spring-aop.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd">
  6. <aop:aspectj-autoproxy></aop:aspectj-autoproxy>
  7. <context:component-scan base-package="com.chentianyu.s03" />
  8. </beans>

测试类

@Test
public void test03(){
    ApplicationContext applicationContext = new ClassPathXmlApplicationContext("s03/applicationContext.xml");
    com.chentianyu.s03.SomeService someService = (com.chentianyu.s03.SomeService) applicationContext.getBean("someServiceImpl");
    String s = someService.doSome("张三", 23);
    System.out.println("在测试方法中的目标方法返回值:" + s);
}

结果

环绕通知中的前置功能实现...
doSome业务方法被执行了...张三
环绕通知中的后置功能实现...
在测试方法中的目标方法返回值:ABCD