AOP(面向切面)
①通知(advice):在什么时机调用该方法;spring提供了5种通知
②切点(pointcut):标注需要使用到该通知的方法的位置
③切面(Aspect):是通知与切点的结合
Spring提供了4种各具特色的AOP支持:
①基于代理的经典aop
②@AspectJ注解驱动的切面
③纯POJO切面
④注入式AspectJ切面(适合spring的各版本)
Spring的切面由包裹了目标对象的代理类实现,代理类处理方法的调用执行额外的切面逻辑。并调用目标方法
调用者--------》代理(调用额外的切面逻辑)----------》目标bean
Spring借助AspectJ的切点表达式语言来定义spring的切面
execution:用于匹配是连接点的方法
spring可以加多个指示器,用&&来连接
spring的bean()指示器
execute(* com.tanghaibin.spring.Person.play(..)) && bean(xxx):表示在调用com.tanghaibin.spring包下的person类中play方法时调用该通知,并且bean的id要为xxx才可以
使用xml配置aop:
<aop:config>//配置aop切面都需要在此标签下
<aop:aspect ref="">//声明一个aop切面
<aop:before pointcut="execute()" method=""></aop:before>//声明一个通知与切点,调用那个方法
</aop:aspect>
</aop:config>
如果一个切面中有多个通知,且切点来自同一个类,那么就会出现切点相同,就会重复写,很麻烦;解决之道:定义一个可以在所有通知中都可以使用的命名切点:
<aop:pointcut id="xxx" expression="execution(切点)"/>
其他的通知都可以通过id引用该切点表达式:<aop:before pointcut-ref="xxx" method=""/>
环绕通知:
需要在做什么事情之前与做什么事情之后进行数据的通信,就如吃饭一样,如果要计算你吃饭吃了多长时间,就需要在吃饭之前进行计时,当饭吃完后,计算花费了多少时间;这样就需要环绕通知:
环绕通知的方法需要一个形参:ProceedingJoinPoint类型的;这个对象很重要,因为它能让我们在通知里调用被通知的方法,通知方法可以完成任何它所需要做的事情,做完后,可以调用ProceedingJoinPoint中的proceed()方法,
将控制转给被通知的方法,如果没有调用该方法,通知就会阻止调用被通知的方法
声明环绕通知:使用<aop:around/>标签 <aop:around pointcut="execute()" method=""/>
当调用者调用被通知者的时候,我们可以获取其向被通知者传递的参数,需要在申明通知的时候加上参数:
<aop:config>
<aop:pointcut id="personBefore" expression="execution(* com.tanghaibin.aop.Person.eating(..)) and args(xxx))"/>
<aop:aspect ref="personAspect">
<aop:before pointcut-ref="personBefore" method="before" arg-names="xxx"/>
</aop:aspect>
</aop:config>
通过@AspectJ注解来定义切面:
@Aspect
@Component
public class AspectDemo {
@Pointcut("execution(* com.tanghaibin.aop.Person.eat(..))")//定义在此切面中都可以引用的切点,该切点的id是方法是 方法名()
public void pointcut(){}
@Before("pointcut()")//通知注解,引用上面定义的切点
public void before(){
System.out.println("吃饭之前先洗手");
}
}
在xml文件配置:<aop:aspectj-autoproxy/>
①通知(advice):在什么时机调用该方法;spring提供了5种通知
②切点(pointcut):标注需要使用到该通知的方法的位置
③切面(Aspect):是通知与切点的结合
Spring提供了4种各具特色的AOP支持:
①基于代理的经典aop
②@AspectJ注解驱动的切面
③纯POJO切面
④注入式AspectJ切面(适合spring的各版本)
Spring的切面由包裹了目标对象的代理类实现,代理类处理方法的调用执行额外的切面逻辑。并调用目标方法
调用者--------》代理(调用额外的切面逻辑)----------》目标bean
Spring借助AspectJ的切点表达式语言来定义spring的切面
execution:用于匹配是连接点的方法
spring可以加多个指示器,用&&来连接
spring的bean()指示器
execute(* com.tanghaibin.spring.Person.play(..)) && bean(xxx):表示在调用com.tanghaibin.spring包下的person类中play方法时调用该通知,并且bean的id要为xxx才可以
使用xml配置aop:
<aop:config>//配置aop切面都需要在此标签下
<aop:aspect ref="">//声明一个aop切面
<aop:before pointcut="execute()" method=""></aop:before>//声明一个通知与切点,调用那个方法
</aop:aspect>
</aop:config>
如果一个切面中有多个通知,且切点来自同一个类,那么就会出现切点相同,就会重复写,很麻烦;解决之道:定义一个可以在所有通知中都可以使用的命名切点:
<aop:pointcut id="xxx" expression="execution(切点)"/>
其他的通知都可以通过id引用该切点表达式:<aop:before pointcut-ref="xxx" method=""/>
环绕通知:
需要在做什么事情之前与做什么事情之后进行数据的通信,就如吃饭一样,如果要计算你吃饭吃了多长时间,就需要在吃饭之前进行计时,当饭吃完后,计算花费了多少时间;这样就需要环绕通知:
环绕通知的方法需要一个形参:ProceedingJoinPoint类型的;这个对象很重要,因为它能让我们在通知里调用被通知的方法,通知方法可以完成任何它所需要做的事情,做完后,可以调用ProceedingJoinPoint中的proceed()方法,
将控制转给被通知的方法,如果没有调用该方法,通知就会阻止调用被通知的方法
声明环绕通知:使用<aop:around/>标签 <aop:around pointcut="execute()" method=""/>
当调用者调用被通知者的时候,我们可以获取其向被通知者传递的参数,需要在申明通知的时候加上参数:
<aop:config>
<aop:pointcut id="personBefore" expression="execution(* com.tanghaibin.aop.Person.eating(..)) and args(xxx))"/>
<aop:aspect ref="personAspect">
<aop:before pointcut-ref="personBefore" method="before" arg-names="xxx"/>
</aop:aspect>
</aop:config>
通过@AspectJ注解来定义切面:
@Aspect
@Component
public class AspectDemo {
@Pointcut("execution(* com.tanghaibin.aop.Person.eat(..))")//定义在此切面中都可以引用的切点,该切点的id是方法是 方法名()
public void pointcut(){}
@Before("pointcut()")//通知注解,引用上面定义的切点
public void before(){
System.out.println("吃饭之前先洗手");
}
}
在xml文件配置:<aop:aspectj-autoproxy/>