Spring-AOP
AOP本质:在不改变原有业务逻辑的情况下增强横切逻辑。
AOP相关术语
Joinpoint(连接点):它指的是那些可以用于把增强代码加入到业务主线中的点。这些点指的就是方法,在方法执行的前后通过动态代理技术加入增强的代码。在Spring框架AOP思想的技术实现中,也只支持方法类型的连接点
Pointcut(切入点):它指的是那些已经把增强代码加入到业务主线进来之后的连接点
Advice(通知/增强):它指的是切面类中用于提供增强功能的方法。并且不同的方法增强的时机是不一样的。其分类有:前置通知 后置通知,异常通知 最终通知 环绕通知
Target(目标对象):它指的是代理的目标对象
Proxy(代理):它指的是一个类被AOP织入增强后,产生的代理类
Weaving(织入):它指的是把增强应用到目标对象来创建新的代理对象的过程。spring采用动态代理织入,而AspectJ采用编译期织入和类装载期织入
Aspect(切面):它指的是增强的代码所关注的方面,把这些相关的增强代码定义到一个类中,这个类就是切面类。
Spring中AOP配置方式
xml模式
<!--
Spring基于XML的AOP配置:
在Spring配置文件中加入aop约束
xmlns:aop="http://www.springframework.org/schema/aop"
http://www.springframework.org/schema/aop
https://www.springframework.org/schema/aop/spring-aop.xsd
-->
<!-- 把通知/增强bean交给spring管理 -->
<bean id="logUtil" class="com.hooda.utils.LogUtil"/>
<!-- 开始AOP配置 -->
<aop:config>
<!-- 配置切面 -->
<aop:aspect id="logAdvice" ref="logUtil">
<!-- 配置前置通知 -->
<aop:before method="printLog" pointcut="execution(public * com.hooda.service.impl.TransferServiceImpl.updateAccountByCardNo(com.hooda.pojo.Account))"/>
</aop:aspect>
</aop:config>
xml+注解方式
<!-- 开启spring对注解aop的支持-->
<aop:aspectj-autoproxy/>
@Component
@Aspect
public class LogUtil {
@Pointcut("execution(* com.hooda.service.impl.*.*(..))")
public void pointcut() {}
@Before("pointcut()")
public void before(JoinPoint jp) {}
@AfterReturning(value = "pointcut()", returning = "rtValue")
public void afterReturning(Object rtValue) {}
@AfterThrowing(value = "pointcut()", throwing="e")
public void afterThrowing(Throwable e) {}
@Around("pointcut()")
public Object around(ProceedingJoinPoint pjp) {}
}
纯注解模式
@Configuration
@ComponentScan("com.hooda")
@EnableAspectJAutoProxy
public class SpringConfiguration {
}
切入点表达式
访问修饰符 返回值 包名.包名.类名.方法名(参数列表)
全匹配方式
public void com.hooda.service.impl.TransferServiceImpl.updateAccountByCardNo(com.hooda.pojo.Account))
访问修饰符省略
void com.hooda.service.impl.TransferServiceImpl.updateAccountByCardNo(com.hooda.pojo.Account))
返回值使用*表示任意返回值
* com.hooda.service.impl.TransferServiceImpl.updateAccountByCardNo(com.hooda.pojo.Account))
包名可以使用.表示任意包,但是有几级包,必须写几个
* ....TransferServiceImpl.updateAccountByCardNo(com.hooda.pojo.Account))
包名可以使用..表示当前包及其子包
* ..TransferServiceImpl.updateAccountByCardNo(com.hooda.pojo.Account))
类名和方法名都可以使用.表示任意类,任意方法
* ...(com.hooda.pojo.Account))
参数列表可以使用具体类型。基本类型int,应用类型必须写全限定类名java.lang.String。参数列表可以使用*表示任意参数类型,但是必须有参数;参数列表可以使用..表示有无参数均可,有参数可以是任意类型
* *..*.*(*)
* *..*.*(..)
修改代理方式
- 使用aop:config标签配置
<aop:config proxy-target-class="true"/>
- 使用aop:aspectj-autoproxy标签配置
<aop:aspectj-autoproxy proxy-target-class="true"/>
通知/增强标签
aop:before aop:after-returning aop:after-throwing aop:after aop:around
这五类标签只能出现在aop:aspect标签的内部
method:用于指定通知的方法名称
pointcut:用于指定切入点表达式
pointcut-ref:用于指定切入点表达式的引用