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>

运行结果:

原文地址:https://www.cnblogs.com/sakura579/p/13971493.html