Spring学习笔记03

总结:

今天学习了一天的Spring中的AOP,首先学习了AOP底层实现的两种代理机制:

  • JDK的动态代理:针对实现了接口的类产生代理。
  • CGLB的动态代理:相当于对JDK动态代理的补充,相当于继承父类,不必实现同个接口,应用的是底层的字节码增强的技术生成当前类的子类对象。

接着学习编写了在XML中配置AOP和用注解配置AOP。以下给出完整的笔记以及代码。

AOP

1. AOP介绍

AOP( Aspect Oriented Programming),即面向切面编程,可以说是OOP( Object Oriented Programming,面向对 象编程)的补充和完善。OOP引入封装、继承、多态等概念来建立一种对象层次结构,用于模拟公共行为的一个集 合。
不过OOP允许开发者定义纵向的关系,但并不适合定义横向的关系,例如日志功能。日志代码往往横向地散布在所 有对象层次中,而与它对应的对象的核心功能毫无关系对于其他类型的代码,如安全性、异常处理和透明的持续性也 都是如此,这种散布在各处的无关的代码被称为横切( cross cutting),在OOP设计中,它导致了大量代码的重复,而 不利于各模块的重用。
A0P技术恰恰相反,它利用一种称为横切的技术,剖解开封装的对象内部,并将那些影响了多个类 的公共行为封装到 一个可重用模块,并将其命名为 Aspect",即切面。所谓“切面",简单说就是那些与业务无关,把业务模块所共同调 用的逻辑封装起来,便于减少系统的重复代码,降低模块之间的耦合度,并有利于未来的可操作性,和可维护性。使 用"横切"技术,AOP把软件系统分为两个部分:核心关注点和横切关注点。业务处理的主要流程是核心关注点,与之 关系不大的部分是横切关注点。横切关注点的一个特点是,他们经常发生在核心关注点的多处,而各处基本相似,比 如权限认证、日志、事务。AOP的作用在于分离系统中的各种关注点,将核心关注点和横切关注点分离开来。

2. AOP核心概念

连接点 (Joinpoint)

连接点 是程序执行的某一个特定位置如类开始初始化前类初始化后类某一个方法调用前/调用后,方法抛出异常后一 个类或一段程序代码拥有一些具有边界性质的特定点,这些代码中的特定点就称为“连接点" Spring仅支持方法连接点 即仅能在方法调用前,方法调用后,方法抛出异常时,以及方法调用前后,这些程序执行点织入增强。

切点( Pointcut)
每个程序类都拥有多个连接点,如一个拥有两个方法的类,这两个方法都是连接点即连接点是程序类中客观存在的事 物,但在众多连接点中如何定位某些感兴趣的连接点呢?AOP通过“切点“定位特定的连接点。

增强( Advice)
增强是织入目标类连接点上的一段程序代码,在 Spring中增强不仅可以描述程序代码还拥有另一个和连接点相关的 信息,这便是执行点的方位,结合执行点的方位信息和切点信息,就可以找到特定的连接,正因为增强既包含了用于 添加到目标连接点上的一段执行逻辑,又包含用于定位连接点的方位信息,所以 Spring所提供的增强接口都是带方 位名的。如BeforeAdvice, AfterReturning, ThrowsAdvice等, BeforeAdvice表示方法调用前的位置,而 AfterReturningAdivce表示访问返回后的位置,所以只有结合切点和增强才能确定特定的连接点并实施增强逻辑。

目标对象( Target)
增强逻辑的织入目标类如果没有AOP那么目标业务类需要自己实现所有逻辑,如果使用AOP可以把一些非逻辑性代码 通过AOP织入到主程序代码上。

引介 (introduction)
引介是一种特殊的增强,它为类添加一些属性和方法,这样即使一个业务类原本没有实现某一个接口,通过AOP的引 介功能,也可以动态地为该业务类添加接口的实现逻辑,让业务类成为这个接口的实现类。

织入 Weaving
织入是将增强添加到目标类具体连接点上的过程,AOP就像一台织布机将目标类增强或者引介天衣无缝的编织到一起 我们不能不说“织入这个词太精辟了,根据不同的实现技术AOP有3种织入方式

  • 编译期织入这要求使用特殊的java编译器
  • 类装载期织入这要求使用特殊的类装载器
  • 动态代理织入在运行期为目标类添加增强生成子类的方式

代理 (Proxy)
一个类被AOP织入增强后就产生了一个结果类,它是融合了原类和增强逻辑的代理类,根据不同的代理方式代理类既 可能是和原类具有相同接口的类,也可能就是原类的子类,所以可以采用与调用原类相同的方法调用代理类。

切面( Aspect)
在某方法 执行 前后 干某某(增强代码) 切面由切点和增强组成,它既包括横切逻辑的定义,也包括连接点的定义,也包括连接点的定义 。spring AOP就是 负责实施切面的框架。它将切面所定义的横切逻辑织入到连接点中。
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 的过程
然后举一个容易理解的例子:
看完了上面的理论部分知识, 我相信还是会有不少朋友感觉到 AOP 的概念还是很模糊, 对 AOP 中的各种概念理解的还不是很透彻. 其实这很正常, 因为 AOP 中的概念是在是太多了, 我当时也是花了老大劲才梳理清楚的.
下面我以一个简单的例子来比喻一下 AOP 中 Aspect, Joint point, Pointcut 与 Advice之间的关系.
让我们来假设一下, 从前有一个叫爪哇的小县城, 在一个月黑风高的晚上, 这个县城中发生了命案. 作案的凶手十分狡猾, 现场没有留下什么有价值的线索. 不过万幸的是, 刚从隔壁回来的老王恰好在这时候无意中发现了凶手行凶的过程, 但是由于天色已晚, 加上凶手蒙着面, 老王并没有看清凶手的面目, 只知道凶手是个男性, 身高约七尺五寸. 爪哇县的县令根据老王的描述, 对守门的士兵下命令说: 凡是发现有身高七尺五寸的男性, 都要抓过来审问. 士兵当然不敢违背县令的命令, 只好把进出城的所有符合条件的人都抓了起来.
来让我们看一下上面的一个小故事和 AOP 到底有什么对应关系.
首先我们知道, 在 Spring AOP 中 Joint point 指代的是所有方法的执行点, 而 point cut 是一个描述信息, 它修饰的是 Joint point, 通过 point cut, 我们就可以确定哪些 Joint point 可以被织入 Advice. 对应到我们在上面举的例子, 我们可以做一个简单的类比, Joint point 就相当于 爪哇的小县城里的百姓,pointcut 就相当于 老王所做的指控, 即凶手是个男性, 身高约七尺五寸, 而 Advice 则是施加在符合老王所描述的嫌疑人的动作: 抓过来审问.
为什么可以这样类比呢?
Joint point : 爪哇的小县城里的百姓: 因为根据定义, Joint point 是所有可能被织入 Advice 的候选的点, 在 Spring AOP中, 则可以认为所有方法执行点都是 Joint point. 而在我们上面的例子中, 命案发生在小县城中, 按理说在此县城中的所有人都有可能是嫌疑人.
Pointcut :男性, 身高约七尺五寸: 我们知道, 所有的方法(joint point) 都可以织入 Advice, 但是我们并不希望在所有方法上都织入 Advice, 而 Pointcut 的作用就是提供一组规则来匹配joinpoint, 给满足规则的 joinpoint 添加 Advice. 同理, 对于县令来说, 他再昏庸, 也知道不能把县城中的所有百姓都抓起来审问, 而是根据凶手是个男性, 身高约七尺五寸, 把符合条件的人抓起来. 在这里 凶手是个男性, 身高约七尺五寸 就是一个修饰谓语, 它限定了凶手的范围, 满足此修饰规则的百姓都是嫌疑人, 都需要抓起来审问.
Advice :抓过来审问, Advice 是一个动作, 即一段 Java 代码, 这段 Java 代码是作用于 point cut 所限定的那些 Joint point 上的. 同理, 对比到我们的例子中, 抓过来审问 这个动作就是对作用于那些满足 男性, 身高约七尺五寸 的爪哇的小县城里的百姓.
Aspect::Aspect 是 point cut 与 Advice 的组合, 因此在这里我们就可以类比: “根据老王的线索, 凡是发现有身高七尺五寸的男性, 都要抓过来审问” 这一整个动作可以被认为是一个 Aspect
作者:阿古拉斯啦啦
来源:CSDN
原文:https://blog.csdn.net/q982151756/article/details/80513340
版权声明:本文为博主原创文章,转载请附上博文链接!

3. Spring AOP实现

Spring的AoP底层用到两种代理机制

  • JDK的动态代理:针对实现了接口的类产生代理。
  • CGLB的动态代理:针对没有实现接口的类产生代理,应用的是底层的字节码增强的技术生成当前类的子类对 象。

4.JDK 动态代理

在这里插入图片描述
在这里插入图片描述

5.CGLIB 代理

在这里插入图片描述

6.Spring AOP实现

通知分类

  • 前置通知: 在目标方法前执行的增强。
  • 后置通知: 在目标方法执行后的增强。
  • 返回通知: 在目标方法返回时执行的增强。
  • 异常通知: 在目标方法执行发生异常时,执行的通知。
  • 环绕通知: 涵盖目标方法执行整个生命周期,需要执行的增强

Pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.xx</groupId>
    <artifactId>spring02</artifactId>
    <packaging>pom</packaging>
    <version>1.0-SNAPSHOT</version>
    <modules>
        <module>Spring-ioc-di</module>
        <module>Spring-annotation</module>
        <module>HomeWork-5-30</module>
        <module>Spring-test</module>
        <module>Aop</module>
    </modules>


    <dependencies>


    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-context</artifactId>
        <version>5.1.5.RELEASE</version>
    </dependency>

    <dependency>
        <groupId>org.projectlombok</groupId>
        <artifactId>lombok</artifactId>
        <version>1.16.20</version>
    </dependency>

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


    <!-- https://mvnrepository.com/artifact/org.springframework/spring-test -->
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-test</artifactId>
        <version>5.1.5.RELEASE</version>
        <scope>test</scope>
    </dependency>

        <!-- https://mvnrepository.com/artifact/cglib/cglib -->
        <dependency>
            <groupId>cglib</groupId>
            <artifactId>cglib</artifactId>
            <version>3.2.5</version>
        </dependency>

        <!-- https://mvnrepository.com/artifact/org.aspectj/aspectjweaver -->
        <dependency>
            <groupId>org.aspectj</groupId>
            <artifactId>aspectjweaver</artifactId>
            <version>1.8.13</version>
        </dependency>

    </dependencies>


</project>

AOP切面类

package com.cd.aspect;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Component;

import java.util.Arrays;


@Component
@Aspect
public class Aop {

    @Pointcut("execution(* com.cd.service..*.*(..))")
    public static void mycut(){

    }

    @Before("mycut()")
    public void mybefore(JoinPoint jp){
        System.out.println("开始执行方法"+jp.getSignature()+ Arrays.toString(jp.getArgs()));
    }
    @After("mycut()")
    public void myafter(JoinPoint jp){
        System.out.println("结束执行方法"+jp.getSignature()+ Arrays.toString(jp.getArgs()));
    }

    @AfterReturning(pointcut = "mycut()",returning = "re")
    public Object myreturn(Object re) {
        System.out.println("方法返回值为" + re);
        return re;
    }

    @AfterThrowing(pointcut = "mycut()",throwing = "ex")
    public void myExption(Exception ex) {
        System.out.println("出现异常" + ex.getMessage());
    }
   /* //环绕通知
    public Object myArroud(ProceedingJoinPoint pjp) {
        System.out.println("--begin--");
        try {
            Object obj = pjp.proceed(pjp.getArgs());
            System.out.println("--return--");
            return obj;
        } catch (Throwable throwable) {
            System.out.println("--exception--" + throwable.getMessage());
        } finally {
            System.out.println("--after--");

        }
        return  null;
    }*/
}
  • XML配置方式
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd">


    <bean class="com.cd.service.Impl.UserServiceImpl" name="userService"></bean>
    <bean class="com.cd.aspect.Aop" name="aop"/>

    <aop:config>


        <aop:pointcut id="mypointcut" expression="execution(* com.cd.service.Impl.UserServiceImpl.*(..))"/>

        <aop:aspect ref="aop">

            <aop:before method="mybefore" pointcut-ref="mypointcut"/>
            <aop:after method="myafter" pointcut-ref="mypointcut"/>
            <aop:after-returning method="myreturn" pointcut-ref="mypointcut" returning="re"/>
            <aop:after-throwing method="myExption" pointcut-ref="mypointcut" throwing="ex"/>


        </aop:aspect>

    </aop:config>


</beans>
  • 注解配置方式
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:aop="http://www.springframework.org/schema/aop"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd">

 <!--扫描包-->
    <context:component-scan base-package="com.cd"/>
 <!--开启aop注解配置--> 
    <aop:aspectj-autoproxy/>
</beans>

execution表达式
execution(modifiers-pattern? ret-type-pattern declaring-type-pattern?name-pattern(parampattern) throws-pattern?)
pattern分别表示修饰符匹配(modifier-pattern?)、返回值匹配(ret-type-pattern)、类路径匹配(declaring-type-pattern?)、方法名匹配(name-pattern)、参数匹配((param-pattern))、异常类型匹配(throws-pattern?),其中后面跟着“?”的是可选项

猜你喜欢

转载自blog.csdn.net/dingcai12003/article/details/90724975
今日推荐