继承是横向的,当父类名称更改的时候,子类方法里面也需要更改 aop是横向的,通过创建动态代理对象(不是真正的对象,但是可以实现功能)来实现
底层都是是用动态代理实现,不修改源代码,只是增强功能。
类里面的哪些方法可以被增强,这些方法就叫做连接点,例如上面的这些方法都可以作为接入点。
在类里面有很多方法可以被增强,但是在实际中,被增强的方法叫做切入点 比如add方法和update方法被增强。
实际增强的逻辑,比如扩展日志的功能,那么这个日志功能就叫做增强 增强/通知分为:
前置通知:在方法之前执行后置通知:在方法之后执行异常通知:方法出现异常执行最终通知:后置之后执行finally环绕通知:方法之前和之后都会执行,例如计算方法时间把增强应用到具体切入点的过程 比如在日志功能用在add方法上面过程
动态添加属性或者方法,一般不用
需要增强的对象(User)
把advice应用到target的过程
一个类被AOP织入增强后,就产生一个结果代理类
Spring里面使用AspectJ来实现AOP操作 AspectJ是一个单独的AOP框架,本身不是Spring的一部分 Spring2.0之后,增加对AspectJ的支持
使用AcpectJ有两种操作:
基于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: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.*(..))表示对类里面的所有方法增强 第三种写法:
execution(* *.*(..))所有的方法
首先需要配置对象。
<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>这里,如果报错,是因为没有导入这个包 添加方式:
由测试结果可以看到,add方法作为切入点,已经被前置增强了
上面这个地方,用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之前