欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Spring AOP之切面

程序员文章站 2022-05-24 09:49:23
...


静态普通方法名匹配切面

1.定义两个业务类  服务生和售货员

public class Waiter {

    public void greetTo(String name) {

        System.out.println("waiter greet to " + name + "...");
    }

    public void serveTo(String name) {

        System.out.println("waiter serving " + name + "...");
    }
}
public class Seller {

    public void greetTo(String name) {

        System.out.println("seller greet to " + name + "...");
    }


}
Seller和Waiter拥有一个相同名称的方法greetTo();

现在通过StaticMathodMatcherPointcutAdvisor定义一个切面,在Waiter类greetTo()方法调用前织入一个前置增强。

public class GreetingAdvisor extends StaticMethodMatcherPointcutAdvisor {


    //切点方法匹配  匹配greetTo()方法
    public boolean matches(Method method, Class<?> aClass) {

        return "greetTo".equals(method.getName());
    }

    //仅匹配Waiter类及其子类
    @Override
    public ClassFilter getClassFilter() {

        return new ClassFilter() {
            public boolean matches(Class<?> clazz) {

                return Waiter.class.isAssignableFrom(clazz);
            }
        };
    }
}
StaticMathodMatcherPointcutAdvisor抽象为唯一定义的方法为matches()方法。

默认情况该切面匹配所有类,这里通过覆盖getClassFilter()方法,让他仅匹配Waiter类及其子类。

定义一个前置增强

public class GreetingBeforeAdvice implements MethodBeforeAdvice {


    public void before(Method method, Object[] args, Object o) throws Throwable {

        System.out.println(o.getClass().getName() + "." + method.getName());

        String clientName = (String) args[0];

        System.out.println("How are you ! Mr " + clientName + " .");
    }
}

配置文件

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

    <!-- 代理对象 -->
    <bean id="waiterTarget" class="com.smart.advisor.Waiter"/>
    <bean id="sellerTarget" class="com.smart.advisor.Seller"/>

    <!-- 前置增强 -->
    <bean id="greetingBeforeAdvice" class="com.smart.advisor.GreetingBeforeAdvice"/>

    <!-- 配置切面 向切面注入一个前置增强 -->
    <bean id="greetingAdvisor" class="com.smart.advisor.GreetingAdvisor"
          p:advice-ref="greetingBeforeAdvice"/>

    <!-- 配置代理 -->
    <bean id="waiterProxy" class="org.springframework.aop.framework.ProxyFactoryBean"
          p:interceptorNames="greetingAdvisor"
          p:target-ref="waiterTarget"
          p:proxyTargetClass="true"/>

    <!-- 配置代理 -->
    <bean id="sellerProxy" class="org.springframework.aop.framework.ProxyFactoryBean"
          p:interceptorNames="greetingAdvisor"
          p:target-ref="sellerTarget"
          p:proxyTargetClass="true"/>
</beans>


测试:

public class AdvisorTest {

    public static void main(String[] args) {

        String configPath = "beans.xml";
        ApplicationContext applicationContext = new ClassPathXmlApplicationContext(configPath);
        Waiter waiterProxy = (Waiter) applicationContext.getBean("waiterProxy");
        Seller sellerProxy = (Seller) applicationContext.getBean("sellerProxy");
        waiterProxy.greetTo("john");
        System.out.println("---------------");
        waiterProxy.serveTo("john");
        System.out.println("---------------");
        sellerProxy.greetTo("messi");
    }
}


运行结果:

com.smart.advisor.Waiter.greetTo
How are you ! Mr john .
waiter greet to john...
---------------
waiter serving john...
---------------
seller greet to messi...

切面只织入了Waiter类的greetTo()方法之前,Waiter类的serveTo()和Seller类的greetTo()方法都没有织入切面。

静态正则表达式匹配切面

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

    <!-- 代理对象 -->
    <bean id="waiterTarget" class="com.smart.advisor.Waiter"/>
    <bean id="sellerTarget" class="com.smart.advisor.Seller"/>

    <!-- 前置增强 -->
    <bean id="greetingBeforeAdvice" class="com.smart.advisor.GreetingBeforeAdvice"/>

    <!-- 配置切面 向切面注入一个前置增强 -->
    <bean id="greetingAdvisor" class="com.smart.advisor.GreetingAdvisor"
          p:advice-ref="greetingBeforeAdvice"/>

    <!--通过正则表达式定义切面 -->
    <bean id="regexpAdvisor" class="org.springframework.aop.support.RegexpMethodPointcutAdvisor"
          p:advice-ref="greetingBeforeAdvice"
          p:patterns=".*greet.*"
    />

    <!-- 配置代理 -->
    <bean id="waiterProxy" class="org.springframework.aop.framework.ProxyFactoryBean"
          p:interceptorNames="regexpAdvisor"
          p:target-ref="waiterTarget"
          p:proxyTargetClass="true"
    />

    <bean id="waiterProxy1" class="org.springframework.aop.framework.ProxyFactoryBean"
          p:interceptorNames="greetingAdvisor"
          p:target-ref="waiterTarget"
          p:proxyTargetClass="true"/>

    <!-- 配置代理 -->
    <bean id="sellerProxy" class="org.springframework.aop.framework.ProxyFactoryBean"
          p:interceptorNames="greetingAdvisor"
          p:target-ref="sellerTarget"
          p:proxyTargetClass="true"/>
</beans>


结果与第一种方法相同


自动代理机制 让容器自动生成代理,Spring使用BeanPostProcessor自动完成