Spring-AOP 流程切面

举报
小工匠 发表于 2021/09/10 23:36:30 2021/09/10
【摘要】 概述实例总结 概述 Spring的流程切面由DefaultPointcutAdvisor和ControlFlowPointcut实现。 流程切点代表由某个方法直接或者间接发...

概述

Spring的流程切面由DefaultPointcutAdvisorControlFlowPointcut实现。 流程切点代表由某个方法直接或者间接发起调用的其他方法。


实例

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

这里写图片描述

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

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
  • 13

我们通过一个WaiterDelegate类调用Waiter中的所有方法

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

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
  • 28

我们希望所有由WaiterDelegate .service方法发起调用的其他方法都织入GreetingBeforeAdvice前置增强,就必须使用流程切面来完成了。

编写增强

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

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

下面使用DefaultPointcutAdvisor配置一个流程切面来完成这一需求

<?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.ControlFlowAdvisor.Waiter"/>

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

    <!-- 流程切点   指定流程切点的类 和 流程切点的方法-->
    <bean id="controlFlowPointcut" class="org.springframework.aop.support.ControlFlowPointcut">
        <constructor-arg type="java.lang.Class"  value="com.xgj.aop.spring.advisor.ControlFlowAdvisor.WaiterDelegate"/>
        <constructor-arg type="java.lang.String" value="service"/> 
    </bean>

    <!-- 切面 -->
    <bean id="controlFlowAdvisor" class="org.springframework.aop.support.DefaultPointcutAdvisor"
        p:pointcut-ref="controlFlowPointcut"
        p:advice-ref="greetingBeforeAdvice"/>


    <!-- 代理类 -->
    <bean id="waiter" class="org.springframework.aop.framework.ProxyFactoryBean"
        p:interceptorNames="controlFlowAdvisor"
        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
  • 28
  • 29
  • 30
  • 31
  • 32

我们来看下ControlFlowPointcut

这里写图片描述

两个构造函数:

  • ControlFlowPointcut(Class<?> clazz) 指定一个类作为流程切点

  • ControlFlowPointcut(Class<?> clazz, String methodName) 指定一个类和某一个方法作为流程切点

我们这里指定com.xgj.aop.spring.advisor.ControlFlowAdvisor.WaiterDelegate中的service()方法作为流程切点,表示所有通过该方法直接或者间接发起的调用匹配切点。

编写测试类

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

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

public class ControlFlowAdvisorTest {

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

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

        System.out.println("\n");

        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
  • 25
  • 26
  • 27

运行结果:

2017-08-20 03:36:49,907  INFO [main] (AbstractApplicationContext.java:583) - Refreshing org.springframework.context.support.ClassPathXmlApplicationContext@76566fb: startup date [Sun Aug 20 03:36:49 BOT 2017]; root of context hierarchy
2017-08-20 03:36:50,020  INFO [main] (XmlBeanDefinitionReader.java:317) - Loading XML bean definitions from class path resource [com/xgj/aop/spring/advisor/ControlFlowAdvisor/conf-controlFlowAdvisor.xml]
Waiter Greet To XiaoGongJiang
Waiter Server To XiaoGongJiang


Pointcut:com.xgj.aop.spring.advisor.ControlFlowAdvisor.Waiter.greetTo
How are you XiaoGongJiang ?
Waiter Greet To XiaoGongJiang
Pointcut:com.xgj.aop.spring.advisor.ControlFlowAdvisor.Waiter.serverTo
How are you XiaoGongJiang ?
Waiter Server To XiaoGongJiang

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

我们在测试类中直接调用了greetTo和serverTo,此时增强并没有起作用,
我们通过WaiterDelegate的service调用Waiter中的greetTo和serverTo,,可以看到Waiter的两个方法都织入了增强


总结

流程切面和动态切面从某种城都说说可以算是一类切面,因为二者都需要在运行期判断动态的环境。 对于流程切面来讲,代理对象那个在每次调用目标类方法时,都需要判断方法调用堆栈中是否有满足流程切点要求的方法,和动态切面一样,对性能的影响很大.

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

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

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

评论(0

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

全部回复

上滑加载中

设置昵称

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

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

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