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 最终通知
}
posted @ 2019-09-01 21:50  Posase  阅读(193)  评论(0编辑  收藏  举报