Spring AOP
面向切面编程
面向切面编程(AOP)就和字面上的意思一样,Spring为我们提供的一把横向的刀,可以把所有bean需要的公共方法以切面的形式注入到指定的bean。这样做使得代码更加简洁,只需要写个切面方法然后通过xml或者注解进行配置即可,大大增加了代码的灵活性和可读性。
1 AOP中的术语
⑴通知(advice):切面的工作称为通知,通知定义了切面是什么以及何时使用。
Spring中的5中通知:
Before:在方法被调用前调用通知;
After:在方法调用之后调用通知,无论方法是否执行成功;
After-returning:在方法成功执行之后调用通知;
After-throwing:在方法抛出异常后调用通知;
Around:通知包裹了被通知的方法,在被通知方法调用之前和调用之后执行之定义的行为;
⑵连接点(Joinpoint):是在应用执行过程中能够插入切面的一个点。
⑶切点(Poincut):切点的定义会匹配通知所要织入的一个或多个连接点。
⑷切面(Aspect):切面是通知和切点的结合。
⑸引入(Introduction):引入允许我们向现有的类添加新方法或属性。
⑹织入(Weaving):织入是将切面应用到目标对象来创建新的代理对象的过程。

2 Spring中AOP的支持
Spring中AOP代理由Spring的IOC容器负责生成、管理,其依赖关系也由IOC容器负责管理。因此,AOP代理可以直接使用容器中的其它bean实例作为目标,这种关系可由IOC容器的依赖注入提供。Spring创建代理的规则为:
1、默认使用Java动态代理来创建AOP代理,这样就可以为任何接口实例创建代理了
2、当需要代理的类不是代理接口的时候,Spring会切换为使用CGLIB代理,也可强制使用CGLIB
AOP编程其实是很简单的事情,纵观AOP编程,程序员只需要参与三个部分:
1、定义普通业务组件
2、定义切入点,一个切入点可能横切多个业务组件
3、定义增强处理,增强处理就是在AOP框架为普通业务组件织入的处理动作
所以进行AOP编程的关键就是定义切入点和定义增强处理,一旦定义了合适的切入点和增强处理,AOP框架将自动生成AOP代理,即:代理对象的方法=增强处理+被代理对象的方法。
使用aop时 需要在xml中引入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:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-4.2.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-4.2.xsd">
</beans>
3 Spring中AOP的使用
xml中使用的AOP的标签说明:

切点表达式:
Spring使用的是AspectJ的切点表达式:

在spring中execution()是我们编写切点定义主要使用的指示器,我们在此基础上使用其他指示器来限制匹配的切点。
<aop:config>
<aop:aspect id="printTime" ref="printTime">
<aop:pointcut id="student" expression="execution(* com.my.study.Student.*(..))"/>
<aop:before method="printTime" pointcut-ref="student"/>
<aop:after method="printTime" pointcut-ref="student"/>
</aop:aspect>
</aop:config>
Spring 中环绕通知的使用:
在通知的方法参数中加入ProceedingJoinPoint:
public void printFunctionTime(ProceedingJoinPoint joinPoint){
try {
Date startTime = new Date();
joinPoint.proceed();
Date endTime = new Date();
System.out.println("时间耗时"+(endTime.getTime()-startTime.getTime()));
}catch (Throwable throwable) {
throwable.printStackTrace();
}
}
在xml中配置:
<aop:config>
<aop:aspect id="printTime" ref="printTime">
<aop:pointcut id="student" expression="execution(* com.my.study.Student.study(..))"/>
<aop:around method="printFunctionTime" pointcut-ref="student"/>
</aop:aspect>
</aop:config>
4 注解切面
使用注解切面,看下面代码:
package com.my.study;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import java.util.Date;
@Aspect
public class AopPrintTime {
/*切点表达式*/
@Pointcut("execution(* com.my.study.Student.study(..))")
public void studyAspect(){}
/*前置切面 使用args标签传入参数*/
@Before("studyAspect()&&args(studyObject)")
/*后置切面 使用args标签传入参数*/
@After("studyAspect()&&args(studyObject)")
public void printTime(String studyObject){
System.out.println(studyObject+"time is "+new Date().getTime());
}
@Around("studyAspect()&&args(studyObject)")
public void printFunctionTime(ProceedingJoinPoint joinPoint,String studyObject){
try {
Date startTime = new Date();
joinPoint.proceed();
Date endTime = new Date();
System.out.println(studyObject+"学习时间耗时"+(endTime.getTime()-startTime.getTime()));
}catch (Throwable throwable) {
throwable.printStackTrace();
}
}
}
需要在xml中配置:
<!--设置AOP自动扫描-->
<aop:aspectj-autoproxy />
<!--配置切面的bean-->
<bean id="printTime" class="com.my.study.AopPrintTime"/>
在pom.xml中配置:
<!-- https://mvnrepository.com/artifact/aopalliance/aopalliance -->
<dependency>
<groupId>aopalliance</groupId>
<artifactId>aopalliance</artifactId>
<version>1.0</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.aspectj/aspectjweaver -->
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.6.10</version>
</dependency>
ps:在学习中遇到了异常spring error at ::0 can't find referenced pointcut
是aspectjweaver的版本问题 改成1.6.10即可

浙公网安备 33010602011771号