zoukankan      html  css  js  c++  java
  • Spring学习笔记(四)----AOP

    AOP

    AOP 概述

    1. AOP 即面向切面编程
    2. AOP 采取横向抽取机制
    3. AOP 使用动态代理实现

    AOP 原理

    public class User {
        public void addUser() {
            // TODO
        }
    }
    // 扩展功能:添加日志功能(什么时候添加的用户)
    
    // 方案一
    直接在 TODO 中修改源代码,添加日志逻辑
    
    // 方案二 纵向抽取机制
    public class BaseUser {
        public void writeLog() {
            // TODO
        }
    }
    public class User extend BaseUser{
        public void addUser() {
            // TODO
            // 调用父类方法实现日志功能
            super.writeLog();
            // 当父类方法名改变,仍然需要修改源代码
        }
    }
    
    // 方案三 横向抽取机制(AOP)
    // 情况一(有接口)
    public interface Dao {
        public void addUser();
    }
    public class DaoImpl implements Dao {
        public void addUser() {
            // TODO 旧逻辑
        }
    }
    // 使用动态代理的方式创建接口实现类的代理对象
    // 即创建与 DaoImpl 类的平级对象,增强旧逻辑功能
    // 实现与 DaoImpl 相同的功能
    // Jdk 动态代理
    // 情况二 无接口
    // 没有接口情况,同样使用动态代理
    // 使用子类的代理对象调用父类的方法完成增强
    // Cglib 动态代理
    

    AOP 操作术语

    public class User {
        public void add() {
    
        }
        public void update() {
    
        }
        public void findAll() {
    
        }
    }
    
    1. Joinpiont(连接点)

      可以被增强的方法,如 add()等

    2. Pointcut(切入点)

      实际被增强的方法

    3. Adcice(通知/增强)

      即扩展(增强)的功能(逻辑)

      • 前置通知:方法之前执行
      • 后置通知:方法之后执行
      • 异常通知:方法出现异常时执行
      • 最终通知:后置之后执行
      • 环绕通知:方法之前之后都执行

      前置-> 环绕-> 后置 -> 最终

    4. Aspect(切面)

      把增强应用到方法上称之为切面

    5. Introduction(引介)

      可以用于动态添加属性或方法

    6. Target(目标对象)

      增强逻辑所在的类

    7. Weaving(织入)

      增强的过程

    8. Proxy(代理)

      织入后的类称之为代理类

    AOP 操作

    使用 Aspect 框架实现
    只有 Spring 2.x 以上支持

    准备

    1. 导入 Jar 包
      • aopalliance
      • aspectjweaver
      • spring-aop
      • spring-sepects
    2. 添加约束
      • aop
      • spring-aop

    使用表达式配置切入点

    execution(<访问修饰符>?<返回类型><方法名>(<参数>)<异常>)
    例如:
    execution(* xin.jeson.User.show(..)) // 增强 User 类中的show方法
    execution(* xin.jeson.User.*(..))    // 增强 User 类中的所有方法
    execution(* *.*(..))                 // 增强所有类中的所有方法
    execution(* xx*(..))                 // 增强所有 xx 开头的方法
    

    使用 Aspect 实现 AOP 的两种方式

    1. xml 配置文件进行增强
    // 需要被增强的类
    public class User {
        public void show() {
            System.out.println("User");
        }
    }
    // 增强逻辑的类
    public class MyUser {
        // 前置通知
        public void beforeShow() {
            System.out.println("Before");
        }
        // 后置通知
        public void afterShow() {
            System.out.println("After");
        }
        // 环绕通知
        public void aroundShow(proceedingJoinPoint proceedingJoinPoint) {
            // 方法之前
            System.out.println("BeforeByAround");
    
            // 执行被增强的方法
            proceedingJoinPoint.proceed();
    
            // 方法之后
            System.out.println("AfterByAround");
        }
    }
    
    <!-- 配置对象 -->
    <bean id="user" class="xin.jeson.User"/>
    <bean id="myUser" class="xin.jeson.MyUser"/>
    <!-- 配置 AOP 操作 -->
    <aop:config>
        <!-- 配置切入点 -->
        <aop:pointcut expression="execution(* xin.jeson.User.*(..))" id="pointcut"/>
        <!-- 配置切面 -->
        <aop:aspect ref="myUser">
            <!-- 将 myUser 中的方法配置到切入点 -->
            <aop:before method="beforeShow" pointcut-ref="pointcut"/>
            <aop:after-returning method="afterShow" pointcut-ref="pointcut"/>
            <aop:around method="aroundShow" pointcut-ref="pointcut"/>
        </aop:aspect>
    </aop:config>
    
    1. 使用注解进行 AOP 操作
    <!-- 开启 AOP 操作 -->
    <aop:aspectj-autoproxy/>
    
    // 需要被增强的类
    @Component(value="user")
    public class User {
        public void show() {
            System.out.println("User");
        }
    }
    // 增强逻辑的类
    @Component(value="myUser")
    @Aspect
    public class MyUser {
        // 前置通知
        @Before(value="execution(* xin.jeson.User.show(..))")
        public void beforeShow() {
            System.out.println("Before");
        }
    
        // 后置通知
        @AfterReturning(value="execution(* xin.jeson.User.show(..))")
        public void afterShow() {
            System.out.println("After");
        }
        // 环绕通知
        @Around(value="execution(* xin.jeson.User.show(..))")
        public void aroundShow(proceedingJoinPoint proceedingJoinPoint) {
            // 方法之前
            System.out.println("BeforeByAround");
    
            // 执行被增强的方法
            proceedingJoinPoint.proceed();
    
            // 方法之后
            System.out.println("AfterByAround");
        }
        // @After 最终通知
    }
    
  • 相关阅读:
    mysql ACID与四种隔离级别归纳总结
    python django查询12306火车票
    python json dumps与loads有可能犯的错误
    python出现UnicodeEncodeError有可能产生的另一个原因
    python安装新版本及pip
    Django添加防跨站请求伪造中间件
    python List的一些相关操作
    mysql中varbinary、binary、char、varchar异同
    (原创)如何使用boost.asio写一个简单的通信程序(一)
    (原创)用c++11实现简洁的ScopeGuard
  • 原文地址:https://www.cnblogs.com/qq188380780/p/11443840.html
Copyright © 2011-2022 走看看