程序小屋

记录生活中的点滴,分享、学习、创新

文章内容 1623902340

基于Schema配置切面

1、一个简单切面的配置

基于Schema配置的切面示例:复制代码

<?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:aop="http://www.springframework.org/schema/aop"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
       http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
       http://www.springframework.org/schema/aop
       http://www.springframework.org/schema/aop/spring-aop-3.0.xsd">
    <aop:config proxy-target-class="true">
        <aop:aspect ref="adviceMethods">
            <aop:before pointcut="target(com.yyq.schema.NaiveWaiter) and execution(* greetTo(..))"
                        method="preGreeting"/>
        </aop:aspect>
    </aop:config>
    <bean id="adviceMethods" class="com.yyq.schema.AdviceMethods"/>
    <bean id="naiveWaiter" class="com.yyq.schema.NaiveWaiter"/>
    <bean id="naughtyWaiter" class="com.yyq.schema.NaughtyWaiter"/>
</beans>

复制代码

  使用一个<aop:aspect>元素标签定义切面,其内部可以定义多个增强。在<aop:config>元素中可以定义多个切面。通过<aop:before>声明了一个前置增强,并通过pointcut属性定义切点表达式,切点表达式的语法和@AspectJ中所用的语法完全相同,由于&&在XML中使用不便,所以一般用and操作符代替。通过method属性指定增强的方法,该方法应该是adviceMethods Bean中的方法。

 

增强方法所在的类:复制代码

package com.baobaotao.schema;
import org.aspectj.lang.ProceedingJoinPoint;

public class AdviceMethods {
    public void preGreeting(String name) {
        System.out.println("--how are you!--");
        System.out.println(name);
    }
    //后置增强对应方法
    public void afterReturning(int retVal){
       System.out.println("----afterReturning()----");
       System.out.println("returnValue:"+retVal);
       System.out.println("----afterReturning()----");
    }
    //环绕增强对应方法
    public void aroundMethod(ProceedingJoinPoint pjp){
       System.out.println("----aroundMethod()----");
       System.out.println("args[0]:"+pjp.getArgs()[0]);
       System.out.println("----aroundMethod()----");
    }
    //抛出异常增强
    public void afterThrowingMethod(IllegalArgumentException iae){
       System.out.println("----afterThrowingMethod()----");
       System.out.println("exception msg:"+iae.getMessage());
       System.out.println("----afterThrowingMethod()----");
    }
    //final增强
    public void afterMethod(){
       System.out.println("----afterMethod()----");
    }
        
      //------------绑定连接点参数----------//
    public void bindParams(int num,String name){
       System.out.println("----bindParams()----");
       System.out.println("name:"+name);
       System.out.println("num:"+num);
       System.out.println("----bindParams()----");
    }
}

复制代码

NaiveWaiter类:

复制代码

package com.yyq.schema;
public class NaiveWaiter implements Waiter {
    @Override
    public void greetTo(String name) {
        System.out.println("NaiveWaiter:greet to " + name + "...");
    }
    @Override
    public void serveTo(String name) {
        System.out.println("NaiveWaiter:serving to " + name + "...");
    }
    public void smile(String clientName,int times){
        System.out.println("NaiveWaiter:smile to  "+clientName+ times+"times...");
    }
}

复制代码

NaughtyWaiter类:

复制代码

package com.yyq.schema;
public class NaughtyWaiter implements Waiter {
    public void greetTo(String clientName) {
        System.out.println("NaughtyWaiter:greet to " + clientName + "...");
    }
    public void serveTo(String clientName) {
        System.out.println("NaughtyWaiter:serving " + clientName + "...");
    }
    public void joke(String clientName, int times) {
        System.out.println("NaughtyWaiter:play " + times + " jokes to " + clientName + "...");
    }
}

复制代码

测试方法:

复制代码

package com.yyq;
import com.yyq.schema.Waiter;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class SchemaTest {
    @Test
    public void schemaTest(){
        String configPath = "com\\yyq\\schema\\beans.xml";
        ApplicationContext ctx = new ClassPathXmlApplicationContext(configPath);
        Waiter naiveWaiter = (Waiter)ctx.getBean("naiveWaiter");
        Waiter naughtyWaiter = (Waiter)ctx.getBean("naughtyWaiter");
        naiveWaiter.greetTo("John");
        naughtyWaiter.greetTo("Tom");
    }
}

复制代码输出结果:

---How are you !---

John

NaiveWaiter:greet to John...

NaughtyWaiter:greet to Tom...

 

2、配置命名切点

    通过pointcut属性声明的切点时匿名切点,它不能被其他增强或其他切面引用。Spring提供了命名切点的配置方式。

命名切点配置:复制代码

  <aop:config proxy-target-class="true">
        <aop:aspect ref="adviceMethods">
            <aop:pointcut id="greetToPointcut" expression="target(com.yyq.schema.NaiveWaiter) and execution(* greetTo(..))"/>
            <aop:before method="preGreeting" pointcut-ref="greetToPointcut"/>
        </aop:aspect>
    </aop:config>

复制代码

  使用<aop:pointcut>定义了一个切点,并通过id属性进行命名,通过pointcut-ref引用这个命名的切点。和<aop:before>一样,除了引介增强外,其他任意增强类型都拥有pointcut、pointcut-ref和method这3个属性。

    如果想要让一个切点为所有增强访问,定义如下:

复制代码

 <aop:config proxy-target-class="true">
        <aop:pointcut id="greetToPointcut2" expression="target(com.yyq.schema.NaiveWaiter) and execution(* greetTo(..))"/>
        <aop:aspect ref="adviceMethods">
            <aop:before method="preGreeting" pointcut-ref="greetToPointcut2"/>
        </aop:aspect>
        <aop:aspect ref="adviceMethods">
            <aop:after method="postGreeting" pointcut-ref="greetToPointcut2"/>
        </aop:aspect>
    </aop:config>

复制代码

 

3、各种增强类型的配置

1)后置增强复制代码

<aop:config proxy-target-class="true">
        <aop:aspect ref="adviceMethods">
            <aop:after-returning method="afterReturning"
                                 pointcut="target(com.baobaotao.SmartSeller)" returning="retVal" />
        </aop:aspect>
    </aop:config>

复制代码

2)环绕增强

复制代码

 <aop:config proxy-target-class="true">
        <aop:aspect ref="adviceMethods">
            <aop:around method="aroundMethod"
                        pointcut="execution(* serveTo(..)) and within(com.baobaotao.Waiter)" />
        </aop:aspect>
    </aop:config>

复制代码

3)抛出异常增强

复制代码

<aop:config proxy-target-class="true">
        <aop:aspect ref="adviceMethods">
            <aop:after-throwing method="afterThrowingMethod"
                                pointcut="target(com.baobaotao.SmartSeller) and execution(* checkBill(..))"
                                throwing="iae" />
        </aop:aspect>
    </aop:config>

复制代码

4)Final增强

复制代码

 <aop:config proxy-target-class="true">
        <aop:aspect ref="adviceMethods">
            <aop:after method="afterMethod"
                       pointcut="execution(* com..*.Waiter.greetTo(..))" />
        </aop:aspect>
    </aop:config>

复制代码

5)引介增强

复制代码

<aop:config proxy-target-class="true">
        <aop:aspect ref="adviceMethods">
            <aop:declare-parents
                    implement-interface="com.baobaotao.Seller"
                    default-impl="com.baobaotao.SmartSeller"
                    type
*