• Spring 框架的 AOP


    上边的结果中,CustomerService.java 中,全部的 method 方法全部被拦截了,下边我们将展示怎样利用 Pointcuts 只拦截 printName()。

    在 Spring AOP 中,有 3 个常用的概念,Advices、Pointcut、Advisor,解释如下:

    • Advices:表示一个 method 执行前或执行后的动作。
    • Pointcut:表示根据 method 的名字或者正则表达式去拦截一个 method。
    • Advisor:Advice 和 Pointcut 组成的独立的单元,并且能够传给 proxy factory 对象。

    我们可以用名字匹配法和正则表达式匹配法去匹配要拦截的 method。

    Pointcut - Name match example

    通过 pointcut 和 advisor 拦截 printName() 方法。创建一个 NameMatchMethodPointcut 的 bean,将你想拦截的方法的名字 printName 注入到属性 mappedName,如下:

    <bean id = "customerPointcut"
            class = "org.springframework.aop.support.NameMatchMethodPointcut">
            <property name = "mappedName" value = "printName" />
    </bean>
    

    创建一个 DefaultPointcutAdvisor 的 advisor bean,将 pointcut 和 advice 关联起来。

    <bean id = "customerAdvisor"
            class = "org.springframework.aop.support.DefaultPointcutAdvisor">
            <property name = "pointcut" ref = "customerPointcut" />
            <property name = "advice" ref = "hijackAroundMethodBean" />
    </bean>
    

    更改代理的 interceptorNames 值,将上边的 advisor(customerAdvisor)替代原来的 hijackAroundMethodBean。

    <bean id = "customerServiceProxy"
            class = "org.springframework.aop.framework.ProxyFactoryBean">
    
            <property name = "target" ref = "customerService" />
    
            <property name = "interceptorNames">
                <list>
                    <value>customerAdvisor</value>
                </list>
            </property>
    </bean>
    

    所有的配置文件如下:

    <beans xmlns = "http://www.springframework.org/schema/beans"
        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 = "customerService" class = "com.shiyanlou.spring.aop.advice.CustomerService">
            <property name = "name" value = "lanqiao" />
            <property name = "url" value = "lanqiao.cn" />
        </bean>
    
        <bean id = "hijackAroundMethodBean" class = "com.shiyanlou.spring.aop.advice.HijackAroundMethod" />
    
        <bean id = "customerServiceProxy" class = "org.springframework.aop.framework.ProxyFactoryBean">
            <property name = "target" ref = "customerService" />
            <property name = "interceptorNames">
                <list>
                    <value>customerAdvisor</value>
                </list>
            </property>
        </bean>
    
        <bean id = "customerPointcut" class = "org.springframework.aop.support.NameMatchMethodPointcut">
            <property name = "mappedName" value = "printName" />
        </bean>
    
        <bean id = "customerAdvisor" class = "org.springframework.aop.support.DefaultPointcutAdvisor">
            <property name = "pointcut" ref = "customerPointcut" />
            <property name = "advice" ref = "hijackAroundMethodBean" />
        </bean>
    
    </beans>
    

    再运行一下 App.java,输出结果如下:

    以上运行结果显示,只拦截了 printName() 方法。

    注意:以上配置中 pointcut 和 advisor 可以合并在一起配置,即不用单独配置 customerPointcut 和 customerAdvisor,只要配置 customerAdvisor 时 class 选择 NameMatchMethodPointcutAdvisor 如下:

    <bean id = "customerAdvisor" class = "org.springframework.aop.support.NameMatchMethodPointcutAdvisor">
            <property name = "mappedName" value = "printName" />
            <property name = "advice" ref = "hijackAroundMethodBean" />
    </bean>
    

    这样,整个配置文件如下:

    <?xml version = "1.0" encoding = "UTF-8"?>
    <beans xmlns = "http://www.springframework.org/schema/beans"
        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 = "customerService" class = "com.shiyanlou.spring.aop.advice.CustomerService">
            <property name = "name" value = "lanqiao" />
            <property name = "url" value = "lanqiao.cn" />
        </bean>
    
        <bean id = "hijackAroundMethodBean" class = "com.shiyanlou.spring.aop.advice.HijackAroundMethod" />
    
        <bean id = "customerServiceProxy" class = "org.springframework.aop.framework.ProxyFactoryBean">
            <property name = "target" ref = "customerService" />
            <property name = "interceptorNames">
                <list>
                    <value>customerAdvisor</value>
                </list>
            </property>
        </bean>
    
    
        <bean id = "customerAdvisor" class = "org.springframework.aop.support.NameMatchMethodPointcutAdvisor">
            <property name = "mappedName" value = "printName" />
            <property name = "advice" ref = "hijackAroundMethodBean" />
        </bean>
    
    </beans>
    

    实际上这种做法将 method 名字与具体的 advice 捆绑在一起,有悖于 Spring 松耦合理念,如果将 method 名字单独配置成 pointcut(切入点),advice 和 pointcut 的结合会更灵活,使一个 pointcut 可以和多个 advice 结合。

    Pointcut - Regular exxpression match example

    你可以配置用正则表达式匹配需要拦截的 method,如下配置:

    <bean id = "customerAdvisor" class = "org.springframework.aop.support.RegexpMethodPointcutAdvisor">
            <property name = "patterns">
                <list>
                    <value>.*URL.*</value>
                </list>
            </property>
            <property name = "advice" ref = "hijackAroundMethodBean" />
        </bean>
    

    配置文件详情如下:

    <?xml version = "1.0" encoding = "UTF-8"?>
    <beans xmlns = "http://www.springframework.org/schema/beans"
        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 = "customerService" class = "com.shiyanlou.spring.aop.advice.CustomerService">
            <property name = "name" value = "lanqiao" />
            <property name = "url" value = "lanqiao.cn" />
        </bean>
    
        <bean id = "hijackAroundMethodBean" class = "com.shiyanlou.spring.aop.advice.HijackAroundMethod" />
    
        <bean id = "customerServiceProxy" class = "org.springframework.aop.framework.ProxyFactoryBean">
            <property name = "target" ref = "customerService" />
            <property name = "interceptorNames">
                <list>
                    <value>customerAdvisor</value>
                </list>
            </property>
        </bean>
    
        <bean id = "customerAdvisor" class = "org.springframework.aop.support.RegexpMethodPointcutAdvisor">
            <property name = "patterns">
                <list>
                    <value>.*URL.*</value>
                </list>
            </property>
            <property name = "advice" ref = "hijackAroundMethodBean" />
        </bean>
    
    </beans>
    

    运行结果:

  • 相关阅读:
    设计模式--工厂模式
    docker
    学习的网址
    showslow小记
    .Net学习线路图
    《掌握软件测试九大技术》
    Apache和Tomcat
    Visual Studio 2017 更新到15.3后 提示错误:包含了重复的“Compile”项 的解决方法
    Asp.Net Core MVC项目实现多语言(Globalization/Localization)
    7月23日 会议纪要(项目有重要变动)
  • 原文地址:https://www.cnblogs.com/sakura579/p/13971493.html
Copyright © 2020-2023  润新知