• SpringAOP的三种实现方式总结


    SpringAOP的实现方式

    1.使用原生SpringApi接口实现AOP:

    • 首先我们写个UserService接口和它的实现类

      public interface UserService {
          public void add();
      }
      
      public class UserServiceImpl implements UserService {
          @Override
          public void add() {
              System.out.println("add user");
          }
      }
      
    • 在applicationConte.xml导入命名空间。先搞切入点,再在切入点把Log.java切入进去。

        <bean id="userService" class="com.zhou.service.UserServiceImpl"/>
        <bean id="log" class="com.zhou.log.Log"/>
        <bean id="afterLog" class="com.zhou.log.AfterLog"/>
    <!--    方式一:执行原生SpringApi接口-->
        <aop:config>
    <!--        切入点 execution(第一个“*”表示返回值的类型任意 “com.zhou.service.UserServiceImpl”要执行的位置  “.*” 代表这个类下的所有方法  “..”代表可以有任意参数) -->
            <aop:pointcut id="pointcut" expression="execution(* com.zhou.service.UserServiceImpl.*(..))"/>
    
    <!--        执行环绕!  把log这个类切入到“* com.zhou.service.UserServiceImpl.*(..)”方法上面-->
            <aop:advisor advice-ref="log" pointcut-ref="pointcut"/>
            <aop:advisor advice-ref="afterLog" pointcut-ref="pointcut"/>
        </aop:config>
    
    • 前置和后置的Log
    Log.java:
    public class Log implements MethodBeforeAdvice {
        // method:方法
        //objects:参数
        //o:对象
        @Override
        public void before(Method method, Object[] objects, Object o) throws Throwable {
            System.out.println(o.getClass().getName()+"的"+method.getName()+"被执行了");//某某对象的方法被执行了
        }
    }
    
    
    AfterLog.java:    
    package com.zhou.log;
    
    public class AfterLog implements AfterReturningAdvice {
        @Override
        public void afterReturning(Object returnValue, Method method, Object[] objects, Object target) throws Throwable {
            System.out.println("执行了"+method.getName()+"返回的结果为"+returnValue);
        }
    }
    
    • 测试代码如下
    public class MyTest {
        public static void main(String[] args) {
            ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
            //PS:动态代理的是接口
            UserService userService = (UserService) context.getBean("userService");
            userService.add();
        }
        //报错了 因为没导入aspect依赖
    }
    
    • 输出结果

    com.zhou.service.UserServiceImpl的add被执行了
    add user
    执行了add返回的结果为null

    2.自定义类实现AOP

    • 先写一个简单MyPointCut类

      public class MyPointCut {
      
          public void before(){
              System.out.println("我在方法执行前面");
          }
      
          public void after(){
              System.out.println("我在方法执行后面");
          }
      }
      
    • 另一种方式配置applicationConte.xml

      <!--方式二:自定义类-->
          <bean id="diyPointCut" class="com.zhou.own.MyPointCut"/>
          <aop:config>
      <!--自定义切面 -->
              <aop:aspect ref="diyPointCut">
      <!--切入点-->
              <aop:pointcut id="pointcut" expression="execution(* com.zhou.service.UserServiceImpl.*(..))"/>
      <!-- 通知-->
                  <aop:before method="before" pointcut-ref="pointcut"/>
                  <aop:after method="after" pointcut-ref="pointcut"/>
              </aop:aspect>
          </aop:config>
      
    • 测试一下

      public class MyTest {
          public static void main(String[] args) {
              ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
              UserService userService = (UserService) context.getBean("userService");
              userService.add();
      
          }
      }
      

      输出结果:

      ​ 我在方法执行前面
      ​ add user
      ​ 我在方法执行后面

    • execution表达式:

      <aop:pointcut id="pointcut" expression="execution(* com.zhou.service.UserServiceImpl.*(..))"/>
      
      * 表示返回值的类型任意
      com.zhou.service.UserServiceImpl 横切的业务类路径
      .* 代表这个类下的所有方法
      (..) ()代表参数,两个点代表可以有任意参数

      3.使用注解实现AOP

    • MyPointCut.java

      @Aspect
      public class AnnotationPointCut {
          @Before("execution(* com.zhou.service.UserServiceImpl.*(..))")
          public void before() {
              System.out.println("我在方法执行前面");
          }
      
          @After("execution(* com.zhou.service.UserServiceImpl.*(..))")
          public void after() {
              System.out.println("我在方法执行后面");
          }
      
      
    • 关于环绕(@Around)

          //在环绕增强中 我们可以给定一个参数 代表我们要处理切入的点 JointPoint:与切入点匹配的执行点
          @Around("execution(* com.zhou.service.UserServiceImpl.*(..))")
          public void around(ProceedingJoinPoint joinPoint) throws Throwable {
              System.out.println("环绕前");
              Object proceed = joinPoint.proceed();//执行方法
              System.out.println("环绕后");
      
              //Signature signature = joinPoint.getSignature();
              //System.out.println("signature:" + signature.toString());
          }
      }
      
    • 配置文件

      <!--    方式三-->
          <bean id="annotationPointCut" class="com.zhou.own.AnnotationPointCut"/>
      <!--    开启注解支持-->
          <aop:aspectj-autoproxy/>
      
    • 输出结果:看看顺序= =

      环绕前
      我在方法执行前面
      add user
      我在方法执行后面
      环绕后

  • 相关阅读:
    最长上升子序列问题总结
    Problem C
    Problem C
    Problem P
    Problem P
    Problem H
    Problem H
    Problem D
    Problem D
    Linux系统调用--getrlimit()与setrlimit()函数详解
  • 原文地址:https://www.cnblogs.com/IMxinu/p/14332321.html
Copyright © 2020-2023  润新知