Spring-AOP 复合切点切面

举报
小工匠 发表于 2021/09/11 01:17:08 2021/09/11
【摘要】 概述ComposablePointcut源码 ComposablePointcut的构造函数ComposablePointcut的3个交集运算的方法ComposablePointcu...

概述

通过上面几篇文章我们发现,实例中的定义的切面仅有一个切点,有的时候,一个切点可能难以描述目标连接点的信息。

上篇博文 Spring-AOP 流程切面的例子,如果我们希望由WaiterDelegate#service方法发起调用并且被调用的方法是Waiter#greetTo才织入增强,那么这个切点就是复合切点,因为它有两个单独的切点共同确定。

当然,我们可以只通过一个切点来描述同时满足上述两个匹配条件的连接点,但是更好的方式是使用Spring提供的ComposalbePointcut把两个切点组合起来,通过切点的符合运行算表示。 ComposalbePointcut可以将多个切点以并集或者交集的方式组合起来,提供切点之间复合运算的功能。


ComposablePointcut源码

ComposablePointcut本身也是一个切点,它实现了Pointcut接口,

ComposablePointcut的构造函数

这里写图片描述

  • public ComposablePointcut()

    构造一个匹配所有类所有方法的复合切点

  • public ComposablePointcut(Pointcut pointcut)

    构造出一个匹配特定切点的复合切点

  • public ComposablePointcut(ClassFilter classFilter)

    构造一个匹配特定类所有方法的复合切点

  • public ComposablePointcut(MethodMatcher methodMatcher)

    构造出一个匹配所有类特定方法的复合切点

  • public ComposablePointcut(ClassFilter classFilter, MethodMatcher methodMatcher)

    构造出一个匹配特定类特定方法的复合切点


ComposablePointcut的3个交集运算的方法

这里写图片描述

  • public ComposablePointcut intersection(ClassFilter other)
    将复合切点和一个ClassFilter对象进行交集运算,得到一个结果复合切点

  • public ComposablePointcut intersection(MethodMatcher other)
    将复合切点和一个MethodMatcher对象进行交集运算,得到一个结果复合切点

  • public ComposablePointcut intersection(Pointcut other)
    将复合切点和一个切点对象进行交集运算,得到一个结果复合切点


ComposablePointcut的3个并集运算的方法

这里写图片描述

  • public ComposablePointcut union(ClassFilter other)
    将复合切点和一个ClassFilter对象进行并集运算,得到一个结果复合切点

  • public ComposablePointcut union(MethodMatcher other)

    将复合切点和一个MethodMatcher对象进行并集运算,得到一个结果复合切点

  • public ComposablePointcut union(Pointcut other)
    将复合切点和一个切点对象进行并集运算,得到一个结果复合切点


多个切点之间的交集并集运算

ComposablePointcut没有提供直接对两个切点机型并集交集的运算的方法,如果需要对连个切点进行叫交集并集运算,可以使用Spring提供的 org.springframework.aop.support.Pointcuts工具类,改工具类提供两个非常友好的静态方法

这里写图片描述

  • public static Pointcut union(Pointcut pc1, Pointcut pc2)
    对两个切点进行交集运算,返回一个结果切点,该切点即ComposablePointcut对象的实例

  • public static Pointcut intersection(Pointcut pc1, Pointcut pc2)
    对两个切点进行并集运算,返回一个结果切点,该切点即ComposablePointcut对象的实例


实例

代码已托管到Github—> https://github.com/yangshangwei/SpringMaster

package com.xgj.aop.spring.advisor.ComposablePointcut;

public class Waiter {

    public void greetTo(String name) {
        System.out.println("Waiter Greet To " + name);
    }

    public void serverTo(String name) {
        System.out.println("Waiter Server To " + name);
    }
}
  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
package com.xgj.aop.spring.advisor.ComposablePointcut;

public class WaiterDelegate {

    private Waiter waiter;

    public void setWaiter(Waiter waiter) {
        this.waiter = waiter;
    }

    /**
     * 
     * 
     * @Title: service
     * 
     * @Description: waiter类中方法的调用,通过该方法发起
     * 
     * @param name
     * 
     * @return: void
     */
    public void service(String name) {
        waiter.greetTo(name);
        waiter.serverTo(name);
    }

}
  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27

前置增强

package com.xgj.aop.spring.advisor.ComposablePointcut;

import java.lang.reflect.Method;

import org.springframework.aop.MethodBeforeAdvice;

public class GreetingBeforeAdvice implements MethodBeforeAdvice {

    @Override
    public void before(Method method, Object[] args, Object target)
            throws Throwable {
        // 输出切点
        System.out.println("Pointcut:" + target.getClass().getName() + "."
                + method.getName());
        String clientName = (String) args[0];
        System.out.println("How are you " + clientName + " ?");
    }

}

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20

通过ComposablePointcut创建一个流程切点和方法名切点的相交切点

package com.xgj.aop.spring.advisor.ComposablePointcut;

import org.springframework.aop.Pointcut;
import org.springframework.aop.support.ComposablePointcut;
import org.springframework.aop.support.ControlFlowPointcut;
import org.springframework.aop.support.NameMatchMethodPointcut;

public class GreetingComposablePointcut {

    public Pointcut getIntersectionPointcut() {
        // 创建一个复合切点
        ComposablePointcut composablePointcut = new ComposablePointcut();

        // 创建一个流程切点
        Pointcut controlFlowPointcut = new ControlFlowPointcut(
                WaiterDelegate.class, "service");
        // 创建一个方法名切点
        NameMatchMethodPointcut nameMatchMethodPointcut = new NameMatchMethodPointcut();
        nameMatchMethodPointcut.addMethodName("greetTo");

        // 将两个切点进行交集操作
        return composablePointcut.intersection(controlFlowPointcut)
                .intersection((Pointcut) nameMatchMethodPointcut);

    }
}

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27

通过GreetingComposablePointcut#intersectionPointcut方法即可得到一个相交的复合切点,配置复合切点的切面和配置其他切点一样,如下所示

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:p="http://www.springframework.org/schema/p"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">

    <!-- 目标类 -->
    <bean id="waiterTarget" class="com.xgj.aop.spring.advisor.ComposablePointcut.Waiter"/>

    <bean id="greetingComposablePointcut" class="com.xgj.aop.spring.advisor.ComposablePointcut.GreetingComposablePointcut"/>

    <!-- 增强 -->
    <bean id="greetingBeforeAdvice" class="com.xgj.aop.spring.advisor.ComposablePointcut.GreetingBeforeAdvice"/>

    <!-- 切面点   p:pointcut引用getIntersectionPointcut返回的复合切点  
           注意写法 #{greetingComposablePointcut.intersectionPointcut}-->
    <bean id="composableAdvisor" class="org.springframework.aop.support.DefaultPointcutAdvisor"
        p:pointcut="#{greetingComposablePointcut.intersectionPointcut}"
        p:advice-ref="greetingBeforeAdvice"/>

    <!-- 代理类 -->    
    <bean id="waiter" class="org.springframework.aop.framework.ProxyFactoryBean"
        p:interceptorNames="composableAdvisor"
        p:target-ref="waiterTarget"
        p:proxyTargetClass="true"/>
</beans>

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27

测试类

package com.xgj.aop.spring.advisor.ComposablePointcut;

import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class IntroductionAdvisorTest {

    @Test
    public void test() {
        ApplicationContext ctx = new ClassPathXmlApplicationContext(
                "classpath:com/xgj/aop/spring/advisor/ComposablePointcut/conf-composablePointcut.xml");

        Waiter waiter = ctx.getBean("waiter", Waiter.class);
        waiter.greetTo("XiaoGongJiang");
        waiter.serverTo("XiaoGongJiang");

        WaiterDelegate waiterDelegate = new WaiterDelegate();
        waiterDelegate.setWaiter(waiter);
        waiterDelegate.service("XiaoGongJiang");
    }

}

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24

运行结果

2017-08-20 18:24:14,593  INFO [main] (AbstractApplicationContext.java:583) - Refreshing org.springframework.context.support.ClassPathXmlApplicationContext@eb6dcf9: startup date [Sun Aug 20 18:24:14 BOT 2017]; root of context hierarchy
2017-08-20 18:24:14,694  INFO [main] (XmlBeanDefinitionReader.java:317) - Loading XML bean definitions from class path resource [com/xgj/aop/spring/advisor/ComposablePointcut/conf-composablePointcut.xml]
Waiter Greet To XiaoGongJiang
Waiter Server To XiaoGongJiang
Pointcut:com.xgj.aop.spring.advisor.ComposablePointcut.Waiter.greetTo
How are you XiaoGongJiang ?
Waiter Greet To XiaoGongJiang
Waiter Server To XiaoGongJiang
  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

通过输出信息可以看出,只有通过WaiterDelegate#service方法调用的Waiter#greetTo才织入了增强,这正是复合交集切点所描述的连接点

文章来源: artisan.blog.csdn.net,作者:小小工匠,版权归原作者所有,如需转载,请联系作者。

原文链接:artisan.blog.csdn.net/article/details/77429625

【版权声明】本文为华为云社区用户转载文章,如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。