面向切面编程

背景

地点:长沙飞思

时间:2023/11/13~17

大致内容:AOP

前言

AOP,即面向切面编程,是OOP的延续,不改变目标方法代码前提,增强目标方法。是Spring框架中的一个重要内容,利用AOP可以对业务逻辑的各个部分进行隔离,从而使得业务逻辑各部分之间的耦合度降低,提高程序的可重用性,同时提高了开发的效率。

AOP

AOP 采取横向抽取机制(动态代理),取代了传统纵向继承机制的重复性代码,其应用主要体现在事务处理日志管理权限控制异常处理等方面。

主要作用是分离功能性需求和非功能性需求,使开发人员可以集中处理某一个关注点或者横切逻辑,减少对业务代码的侵入,增强代码的可读性和可维护性。

Spring Aop

基于AspectJ的AOP实现

专业术语

Aspect(切面):Aspect 声明类似于 Java 中的类声明,在 Aspect 中会包含着一些 Pointcut 以及                               相应的 Advice。
Joint point(连接点):表示在程序中明确定义的点,典型的包括方法调用,对类成员的访问以及                                        异常处理程序块的执行等等,它自身还可以嵌套其它 joint point。
Pointcut(切点):表示一组 joint point,这些 joint point 或是通过逻辑关系组合起来,或是通过                                   通配、正则表达式等方式集中起来,它定义了相应的 Advice 将要发生的地                                       方。
Advice(增强):Advice 定义了在 Pointcut 里面定义的程序点具体要做的操作,它通过 before、                               after 和 around 来区别是在每个 joint point 之前、之后还是代替执行的代码。
Target(目标对象):织入 Advice 的目标对象。
Weaving(织入):将 Aspect 和其他对象连接起来, 并创建 Adviced object 的过程。

切入点

切入点表达式: 方法签名描述

方法签名: 访问修饰符 返回值类型 [包.类.]方法名(参数列名) throws 异常声明;

语法:

execution(修饰符? 返回值 方法名(参数) 异常?)

注意:

?: 0或者1个

通配符:

*: 任意 返回值, 方法名, 类名

..: 任意 包中使用: ..: 表示该包,以及该包后代包 参数: ..: 任意个数,任意类型的参数

  • execution(* *(..)) 匹配所有spring管理对象所有方法, 第一个*任意返回值 ,第二个*任意方法, .. 任意参数

  • execution(* org.suke.spring..*.*(..) ):匹配org.suke.spring包及其子包所有类的所有方法

  • execution(* org.suke.spring.*.*(..) ):匹配org.suke.spring包所有类的所有方法

  • execution(* org.suke.spring.*.add*(..) ):匹配org.suke.spring包所有类的所有以add开头的方法

  • execute( public * addUser(entity.User)) 匹配addUser方法,返回值任意,参数为entity包User对象

  • execute( public void *(entity.User)) 匹配返回值为void,参数为entity包User的所有方法

  • execute( public void addUser(..)) 匹配返回值为void,参数任意的addUser方法

使用 

依赖导入

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <maven.compiler.source>1.8</maven.compiler.source>
        <maven.compiler.target>1.8</maven.compiler.target>
        <spring.version>5.2.15.RELEASE</spring.version>
    </properties>


    <dependencies>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>${spring.version}</version>
        </dependency>

        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-aop</artifactId>
            <version>${spring.version}</version>
        </dependency>
        <!--导入第三方的aspectj框架-->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-aspects</artifactId>
            <version>${spring.version}</version>
        </dependency>

        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-log4j12</artifactId>
            <version>1.7.36</version>
        </dependency>

        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
            <scope>test</scope>
        </dependency>

        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-test</artifactId>
            <version>${spring.version}</version>
        </dependency>
    </dependencies>

</project>

通知类型

  • 前置通知/增强

  • 后置通知

  • 异常通知

  • 最终通知

  • 环绕通知

基于xml

 <bean id="userService" class="com.fs.service.impl.UserServiceImpl"></bean>

    <bean id="logAdvice" class="com.fs.advice.LogAdvice"></bean>
    <aop:config>
        <!--织入-->
        <!--配置切入点: 对那些类那些方法进行增强
           id: 唯一标识符
           expression: 切入点表达式
        -->
        <aop:pointcut id="myPointcut" expression="execution(* com.fs.service..*.*User(..))"/>

        <!--织入
        ref: 增强类bean对象
        -->
        <aop:aspect ref="logAdvice">
<!--            <aop:before method="before" pointcut-ref="myPointcut" />-->
            <!--
              后置增强:正常执行
              属性:
              returning: 目标方法返回值传递给增强方法那个参数,  接收返回值的参数名
            -->
<!--            <aop:after-returning method="afterReturn" pointcut-ref="myPointcut" returning="rs" />-->


            <!--异常增强: 目标方法产生异常
              throwing: 目标方法执行产生异常对象被增强方法那个参数接收
            -->
<!--            <aop:after-throwing method="afterThrowing" pointcut-ref="myPointcut"  throwing="ex"/>-->

<!--            <aop:after-throwing method="afterThrowing2" pointcut-ref="myPointcut"  throwing="ex"/>-->

            <!--最终增强配置-->
<!--            <aop:after method="after" pointcut-ref="myPointcut"/>-->

            <!--环绕增强-->
            <aop:around method="around" pointcut-ref="myPointcut"/>
        </aop:aspect>
    </aop:config>

基于注解

在增强方法上提供相关的注解:

@Before: 前置增强配置

@AfterThrowing: 异常增强配置

@AfterReturning: 后置增强配置

@After: 最终增强配置

@Around: 环绕增强配置

@Aspect: 标记类是一个通知类

可以把切入点表达式定义在一个方法上, 在其他增强方法上, 切入点表达式写到方法名()

总结

仰天大笑出门去,我辈岂是蓬蒿人

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值