Spring AOP(Aspect Oriented Programming)面向切面编程(配置方式)

    xiaoxiao2025-01-14  14

    AOP和继承的区别

    继承是横向的,当父类名称更改的时候,子类方法里面也需要更改 aop是横向的,通过创建动态代理对象(不是真正的对象,但是可以实现功能)来实现

    AOP原理

    底层都是是用动态代理实现,不修改源代码,只是增强功能。


    AOP操作术语

    public class User { public void add() { } public void update() { } public void delete() { } public void findAll() { } }

    Joinpoint(连接点)

    类里面的哪些方法可以被增强,这些方法就叫做连接点,例如上面的这些方法都可以作为接入点。

    Pointcut(切入点)

    在类里面有很多方法可以被增强,但是在实际中,被增强的方法叫做切入点 比如add方法和update方法被增强。

    Advice(通知/增强)

    实际增强的逻辑,比如扩展日志的功能,那么这个日志功能就叫做增强 增强/通知分为:

    前置通知:在方法之前执行后置通知:在方法之后执行异常通知:方法出现异常执行最终通知:后置之后执行finally环绕通知:方法之前和之后都会执行,例如计算方法时间

    Aspect(切面)

    把增强应用到具体切入点的过程 比如在日志功能用在add方法上面过程

    Introduction(引介)

    动态添加属性或者方法,一般不用

    Target(目标对象)

    需要增强的对象(User)

    Weaving(织入)

    把advice应用到target的过程

    Proxy(代理)

    一个类被AOP织入增强后,就产生一个结果代理类


    Spring里AOP的操作

    Spring里面使用AspectJ来实现AOP操作 AspectJ是一个单独的AOP框架,本身不是Spring的一部分 Spring2.0之后,增加对AspectJ的支持

    使用AcpectJ有两种操作:

    基于xml方式基于注解的方式

    AOP准备工作

    导入AOP相关的jar包在核心配置文件导入AOP的约束

    配置文件的方式实现AOP

    首先需要配置约束:

    <?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-2.5.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.1.xsd "><!-- 要添加最后2行 -->

    下载aspectj的jar包: https://www.eclipse.org/aspectj/downloads.php

    有两个对象:

    public class Book { public void add() { System.out.println("add......"); } } public class MyBook { public void before() { System.out.println("前置增强"); } }

    我们想要在执行Book的add方法之前,先执行MyBook的before方法。 传统的方式是需要在代码里面创建新的对象。

    表达式配置切入点:

    execution(* aop.Book.add(..))

    前面使用*表示任意访问修饰符 后面接方法名的全路径

    第二种写法:

    execution(* aop.Book.*(..))

    表示对类里面的所有方法增强 第三种写法:

    execution(* *.*(..))

    所有的方法

    AspectJ的AOP操作

    首先需要配置对象。

    <bean id="book" class="aop.Book"></bean> <bean id="myBook" class="aop.MyBook"></bean>

    配置AOP的操作

    配置切入点(使用表达式的方式表示对哪个类进行增强)配置切面(把增强用在方法上) <aop:config> <!--配置切入点--> <aop:pointcut id="addPointCut" expression="execution(* aop.Book.*(..))"/> <!--配置切面--> <aop:aspect ref="myBook"> <!--配置增强类型--> </aop:aspect> </aop:config>

    可以看到有很多种增强类型。

    <aop:config> <!--配置切入点--> <aop:pointcut id="addPointCut" expression="execution(* aop.Book.*(..))"/> <!--配置切面--> <aop:aspect ref="myBook"> <!--配置增强类型--> <aop:before method="before" pointcut-ref="addPointCut"></aop:before> </aop:aspect> </aop:config>

    这里,如果报错,是因为没有导入这个包 添加方式:

    编程测试

    public class MyTest { @Test public void testAop() { ApplicationContext context = new ClassPathXmlApplicationContext("bean3.xml"); Book book = (Book) context.getBean("book"); System.out.println(book); book.add(); } }

    由测试结果可以看到,add方法作为切入点,已经被前置增强了

    后置增强

    <aop:config> <!--配置切入点--> <aop:pointcut id="addPointCut" expression="execution(* aop.Book.*(..))"/> <!--配置切面--> <aop:aspect ref="myBook"> <!--配置增强类型--> <aop:before method="before" pointcut-ref="addPointCut"/> <aop:after-returning method="after" pointcut-ref="addPointCut"/> </aop:aspect> </aop:config>

    上面这个地方,用aop:after也是可以的。。。

    环绕通知

    增强代码

    public void around(ProceedingJoinPoint proceedingJoinPoint) throws Throwable { //方法之前 System.out.println("方法之前"); //执行被增强的方法 proceedingJoinPoint.proceed(); //方法之后 System.out.println("方法之后"); }

    配置增强

    <aop:config> <!--配置切入点--> <aop:pointcut id="addPointCut" expression="execution(* aop.Book.*(..))"/> <!--配置切面--> <aop:aspect ref="myBook"> <!--配置增强类型--> <aop:before method="before" pointcut-ref="addPointCut"/> <aop:after-returning method="after" pointcut-ref="addPointCut"/> <aop:around method="around" pointcut-ref="addPointCut"/> </aop:aspect> </aop:config>

    在方法之前和之后做同样操作 但是在before之后 after之前

    最新回复(0)