Spring学习之AOP的切点表达式详解

1.背景知识

在Sping中使用AOP的主要工作是配置织入关系,使用标签代表这一段是织入关系的配置
首先,用标签声明一个切面,这里要引用我们之前编写好的切面类极其在配置文件中注册的id(myAspect)
然后,通过标签对各种类型的增强进行配置,前置增强用before,后置增强用after
切面=增强+切点,所以在对应的增强类型中我们还要指定具体的增强方法和切点,配置切点就需要切点表达式


    <aop:config>
        
        <aop:aspect ref="myAspect">
            
            <aop:before method="beforeEnhance" pointcut="execution(public void com.lxl.aop.Target.service())"/>
            <aop:after method="afterEnhance" pointcut="execution(public void com.lxl.aop.Target.service())"/>
        aop:aspect>
    aop:config>

2.切点表达式的写法

切点表达式的语法:execution([修饰符] 返回值类型 包名.类名.方法名(参数)),其中

  • 修饰符可以省略
  • 返回值类型、包名、类名、方法名可以用*代替
  • 包名与类名之前一个点.代表当前包写的类,两个点…代表当前包极其子包下的所有类
  • 参数列表可以用两个点…代表任意类型、任意个数的参数

1.最明确也是范围最小的一种声明:所有的地方都不省略,但是这样只能声明一个方法,不方便
excecution(public void com.lxl.aop.Target.service())

2.代表Target类下的所有方法都要声明成切点,不过返回值必须都是void
excecution( void com.lxl.aop.Target.*(..))

3.这种声明方法最常用,代表aop当前包下的所有类的任何方法都声明成切点,需要被增强
excecution( * com.lxl.aop.*.*(..))

4.拓展了上面的方法,把aop包极其子包下的所有类也声明成了切点
excecution( * com.lxl.aop..*.*(..))

3.切点表达式的抽取

首先,我们在applicationContext.xml中有一个织入的配置,但是发现所有的增强都是用的同一个切点表达式:


    <aop:config>
        
        <aop:aspect ref="myAspect">
            
            <aop:before method="beforeEnhance" pointcut="execution( * com.lxl.aop.Target.*(..))"/>
            <aop:after-returning method="afterReturningEnhance" pointcut="execution( * com.lxl.aop.Target.*(..))"/>
            <aop:after method="afterEnhance" pointcut="execution( * com.lxl.aop.Target.*(..))"/>
            <aop:around method="aroundEnhance" pointcut="execution( * com.lxl.aop.Target.*(..))"/>
            <aop:after-throwing method="throwingEnhance" pointcut="execution( * com.lxl.aop.Target.*(..))"/>
        aop:aspect>
    aop:config>

抽点表达式都是相同的,但是重复去写很麻烦,而且也不利于后期的维护,所有可以把他们抽取出来:

所以原先的织入配置就可以改为:

  
  <aop:config>
      
      <aop:aspect ref="myAspect">
          
          
          <aop:pointcut id="myPointcut" expression="execution( * com.lxl.aop.Target.*(..))"/>
          <aop:before method="beforeEnhance" pointcut-ref="myPointcut"/>
          <aop:after-returning method="afterReturningEnhance" pointcut-ref="myPointcut"/>
          <aop:after method="afterEnhance" pointcut-ref="myPointcut"/>
          <aop:around method="aroundEnhance" pointcut-ref="myPointcut"/>
          <aop:after-throwing method="throwingEnhance" pointcut-ref="myPointcut"/>
      aop:aspect>
  aop:config>

补充:注解配置中切点表达式的抽取方法
在切面类中自定义一个方法,然后在方法上加上 @Pointcut(“excecution(…)”)注解,在增强方法中使用时直接进行引用即可:

@Component("myAspect")
@Aspect // 告知Spring容器当前MyAspect类是一个切面类
public class MyAspect {

    @Pointcut("execution(* com.lxl.aopAnnotation.Target.*(..))")
    public void myPoint(){}

    @Before("MyAspect.myPoint()")
    public void beforeEnhance(){
        System.out.println("前置增强,在切点的前面执行.......");
    }
}

你可能感兴趣的:(Spring,Framework,spring,java,后端,aop,切点表达式)