Spring AOP几种方式的使用

骑猪看日落 2022-06-05 06:17 283阅读 0赞

引入依赖

  1. <spring-version>4.2.3.RELEASE</spring-version>
  2. <dependency>
  3. <groupId>junit</groupId>
  4. <artifactId>junit</artifactId>
  5. <version>4.11</version>
  6. <scope>test</scope>
  7. </dependency>
  8. <dependency>
  9. <groupId>org.springframework</groupId>
  10. <artifactId>spring-core</artifactId>
  11. <version>${spring-version}</version>
  12. <dependency>
  13. <groupId>org.springframework</groupId>
  14. <artifactId>spring-beans</artifactId>
  15. <version>${spring-version}</version>
  16. </dependency>
  17. <dependency>
  18. <groupId>org.springframework</groupId>
  19. <artifactId>spring-context</artifactId>
  20. <version>${spring-version}</version>
  21. </dependency>
  22. <dependency>
  23. <groupId>org.springframework</groupId>
  24. <artifactId>spring-test</artifactId>
  25. <version>${spring-version}</version>
  26. </dependency>
  27. <dependency>
  28. <groupId>org.aspectj</groupId>
  29. <artifactId>aspectjrt</artifactId>
  30. <version>1.8.8</version>
  31. </dependency>
  32. <dependency>
  33. <groupId>org.aspectj</groupId>
  34. <artifactId>aspectjweaver</artifactId>
  35. <version>1.8.8</version>
  36. </dependency>

Service

HelloService.class

  1. public interface HelloService {
  2. /**
  3. * hello method
  4. */
  5. void hello(String words);
  6. }

HelloServiceImpl .class

  1. @Service("helloServiceImpl")
  2. public class HelloServiceImpl implements HelloService {
  3. @Override
  4. public void hello(String words) {
  5. System.out.println(words);
  6. int i = 1 / 0;
  7. }
  8. }

方式一:使用MethodInterceptor

切面类 LogInterceptor.class

  1. import org.aopalliance.intercept.MethodInterceptor;
  2. import org.aopalliance.intercept.MethodInvocation;
  3. /**
  4. * @author yuyufeng
  5. * @date 2017/11/14
  6. */
  7. public class LogInterceptor implements MethodInterceptor {
  8. @Override
  9. public Object invoke(MethodInvocation invocation) throws Throwable {
  10. System.out.println("#before");
  11. Object ret = invocation.proceed();
  12. System.out.println("#after");
  13. return ret;
  14. }
  15. }

XML配置

  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"
  4. xmlns:context="http://www.springframework.org/schema/context"
  5. xsi:schemaLocation="http://www.springframework.org/schema/beans
  6. http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
  7. http://www.springframework.org/schema/context
  8. http://www.springframework.org/schema/context/spring-context-4.0.xsd">
  9. <context:component-scan base-package="learn.service.impl"/>
  10. <bean id="logInterceptor" class="learn.interceptor.LogInterceptor"></bean>
  11. <bean class="org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator">
  12. <property name="beanNames">
  13. <value>*ServiceImpl</value>
  14. </property>
  15. <!--强制代理目标类(cglib)-->
  16. <property name="proxyTargetClass" value="true"/>
  17. <property name="interceptorNames">
  18. <list>
  19. <value>logInterceptor</value>
  20. </list>
  21. </property>
  22. </bean>
  23. </beans>

测试

  1. @RunWith(SpringJUnit4ClassRunner.class)
  2. @ContextConfiguration({"classpath:spring/spring-service.xml"})
  3. public class Demo1 {
  4. @Autowired
  5. private HelloService helloService;
  6. @Test
  7. public void test() {
  8. System.out.println("Demo1.test");
  9. }
  10. @Test
  11. public void testHelloService() {
  12. try{
  13. helloService.hello("hello 你好~");
  14. }catch (Exception e){
  15. System.out.println("出现异常");
  16. }
  17. }
  18. }

执行结果

  1. #before
  2. hello 你好~
  3. 出现异常

方式二:使用@Aspect方式

配置Aspect类

  1. import org.aspectj.lang.JoinPoint;
  2. import org.aspectj.lang.ProceedingJoinPoint;
  3. import org.aspectj.lang.annotation.*;
  4. import org.springframework.stereotype.Component;
  5. import java.lang.reflect.Method;
  6. /**
  7. * @author yuyufeng
  8. * @date 2017/11/14
  9. */
  10. @Aspect
  11. public class LogAspect {
  12. /**
  13. * 方法前执行
  14. * @param point
  15. */
  16. @Before("execution(* learn.service.impl.*.*(..))")
  17. public void methodBefore(JoinPoint point) {
  18. handleMethod(point);
  19. System.out.println("LogAspect.methodBefore");
  20. }
  21. /**
  22. * 无论方法以何种方式结束,都会执行(类似于finally)
  23. * @param point
  24. */
  25. @After("execution(* learn.service.impl.*.*(..))")
  26. public void methodAfter(JoinPoint point) {
  27. System.out.println("LogAspect.methodAfter");
  28. }
  29. /**
  30. * 环绕执行
  31. * @param proceedingJoinPoint
  32. * @return
  33. * @throws Throwable
  34. */
  35. @Around(value = "execution(* learn.service.impl.*.*(..))")
  36. public Object aroundAdvice(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
  37. handleMethod(proceedingJoinPoint);
  38. //调用核心逻辑
  39. System.out.println("-----Start of aroundAdvice()-----");
  40. Object retVal = proceedingJoinPoint.proceed();
  41. System.out.println("-----End of aroundAdvice()------");
  42. return retVal;
  43. }
  44. /**
  45. * Throw后执行
  46. * @param point
  47. * @param ex
  48. */
  49. @AfterThrowing(pointcut = "execution(* learn.service.impl.*.*(..))", throwing = "ex")
  50. public void doAfterThrowingTask(JoinPoint point,Exception ex) {
  51. System.out.println(ex.toString());
  52. }
  53. /**
  54. * 运行方法后执行
  55. * @param joinPoint
  56. * @param retVal
  57. */
  58. @AfterReturning(value = "execution(* learn.service.impl.*.*(..))",returning="retVal")
  59. public void doAfterReturning(JoinPoint joinPoint,Object retVal){
  60. System.out.println("LogAspect.doAfterReturning:"+retVal);
  61. }
  62. /**
  63. * 获取方法名称
  64. *
  65. * @param joinPoint
  66. * @return
  67. * @throws Exception
  68. */
  69. public static String handleMethod(JoinPoint joinPoint){
  70. Class<?> clazz = joinPoint.getTarget().getClass();
  71. String name = joinPoint.getSignature().getName();
  72. Object[] parameterTypes = joinPoint.getArgs();
  73. System.out.println(name);
  74. for (Object parameterType : parameterTypes) {
  75. System.out.println("# "+parameterType);
  76. }
  77. for (Method method : clazz.getDeclaredMethods()) {
  78. System.out.println("* "+method.getName());
  79. }
  80. return "";
  81. }
  82. }

XML配置

  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"
  4. xmlns:context="http://www.springframework.org/schema/context"
  5. xmlns:aop="http://www.springframework.org/schema/aop"
  6. xsi:schemaLocation="http://www.springframework.org/schema/beans
  7. http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
  8. http://www.springframework.org/schema/context
  9. http://www.springframework.org/schema/context/spring-context-4.0.xsd
  10. http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd">
  11. <context:component-scan base-package="learn.service.impl"/>
  12. <!--强制代理目标类(cglib) proxy-target-class="true"-->
  13. <aop:aspectj-autoproxy />
  14. <bean id="logAspect" class="learn.aspect.LogAspect"></bean>
  15. </beans>

运行测试执行类Demo1.class,得到结果

  1. hello
  2. # hello 你好~
  3. * hello
  4. -----Start of aroundAdvice()-----
  5. hello
  6. # hello 你好~
  7. * hello
  8. LogAspect.methodBefore
  9. hello 你好~
  10. LogAspect.methodAfter
  11. java.lang.ArithmeticException: / by zero
  12. 出现异常

备注

切入点表达式 execution (* com.sample.service.impl...(..))
整个表达式可以分为五个部分:
1、execution(): 表达式主体。
2、第一个号:表示返回类型,号表示所有的类型。
3、包名:表示需要拦截的包名,后面的两个句点表示当前包和当前包的所有子包,com.sample.service.impl包、子孙包下所有类的方法。
4、第二个号:表示类名,号表示所有的类。
5、(..):最后这个星号表示方法名,号表示所有的方法,后面括弧里面表示方法的参数,两个句点表示任何参数。

发表评论

表情:
评论列表 (有 0 条评论,283人围观)

还没有评论,来说两句吧...

相关阅读

    相关 AOP增强方式

    2.AOP常用的几种增强方式,各自的特点(代码辅助)? 1.前置增强(又称前置通知)前置增强使用[@Befor注解标识][Befor],增强方法优先于目标方法执行。