1

@AspectJ配置切面

编程方式实现

public class Waiter {
    public void check(String name){
        System.out.println("waiter说:结账?"+name);
    }
    public void serve(String name){
        System.out.println("waiter说:要点什么?"+name);
    }
}
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;

@Aspect
public class PreGreeting {
    @Before("execution(* serve(..))")
    public void beforeGreeting(){
        System.out.println("how are you!");
    }
}

@Before注解表示前置增强,后面的切点表达式表示在目标类的serve()方法织入增强,serve()方法可以带任意的传入参数和任意的返回值。
PreGreeting类通过注解,将切点,增强类型和增强的横切逻辑组合在一起。PreGreeting类相当于上一篇中的BeforeAdvice(增强),NameMatchMethodPointcut(切点)DefaultPointcutAdvisor(切面)三者联合表达的信息。

        Waiter waiter=new Waiter();
        AspectJProxyFactory factory=new AspectJProxyFactory();
        factory.setTarget(waiter);//设置目标类
        factory.addAspect(PreGreeting.class);//添加切面
        Waiter proxy=factory.getProxy();
        proxy.serve("TheViper");
        proxy.check("TheViper");
how are you!
waiter说:要点什么?TheViper
waiter说:结账?TheViper

通过配置使用

<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" 
    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 
    http://www.springframework.org/schema/aop 
    http://www.springframework.org/schema/aop/spring-aop.xsd">
    <aop:aspectj-autoproxy/>
    <bean id='waiter' class='aspectj.Waiter'/>
    <bean class='aspectj.PreGreeting'/>
</beans>
  • 引用aop命名空间

xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="...  
    http://www.springframework.org/schema/aop 
    http://www.springframework.org/schema/aop/spring-aop.xsd"
  • <aop:aspectj-autoproxy/>自动为spring容器中那些匹配@AspectJ切面的Bean创建代理,完成切面织入

        ApplicationContext ctx=new ClassPathXmlApplicationContext("beans.xml");
        Waiter waiter=(Waiter)ctx.getBean("waiter");
        waiter.serve("TheViper");
        waiter.check("TheViper");

使用的时候,直接获取bean操作就可以了,不用像前面还要创建AspectJProxyFactory,设置好代理才能用。

schema配置切面

配置命名切点

需要引入aspectjweaver

public class GreetBefore {
    public void say(String name){
        System.out.println("hallo!"+name);
    }
}

增强不用像上一篇中那样,需要继承特定类或实现特定接口。

<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" 
    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 
    http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd">
    <bean id='waiterTarget' class='com.Waiter'/>
    <bean id='greetBefore' class='schema.GreetBefore'/>
    <aop:config>
        <aop:pointcut expression="target(com.Waiter) and execution(* check(..)) and args(name,..)" 
        id="servePointcut"/>
        <aop:aspect ref="greetBefore">
            <aop:before method="say" pointcut-ref="servePointcut"/>
        </aop:aspect>
    </aop:config>
</beans>  

匹配Waiter类中的check()方法。

  • 需要引入aop命名空间

xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="... http://www.springframework.org/schema/aop 
http://www.springframework.org/schema/aop/spring-aop.xsd"
  • <aop:aspect>定义切面,其内部可以定义多个增强,ref属性指定引用的具体增强

  • <aop:before>声明了一个前置增强,通过pointcut-ref属性引用切点,method属性指定增强中哪个方法用于具体的增强行为

  • <aop:pointcut>定义切点,expression属性设置切点表达式,其语法和@AspectJ中的语法完全相同。

public class Waiter {
    public void check(String name){
        System.out.println("waiter说:结账?"+name);
    }
    public void serve(String name){
        System.out.println("waiter说:要点什么?"+name);
    }
}
        ApplicationContext ctx=new ClassPathXmlApplicationContext("applicationContext.xml");
        Waiter waiter=(Waiter)ctx.getBean("waiterTarget");
        waiter.serve("TheViper");
        waiter.check("TheViper");
waiter说:要点什么?TheViper
hallo!TheViper
waiter说:结账?TheViper

配置顺序问题

命名切点只能被当前<aop:aspect>内定义的元素访问到,<aop:config>中的配置顺序必须是<aop:pointcut>=><aop:advisor>=><aop:aspect>

各种增强类型

后置增强

<aop:config>
    ...
    <aop:aspect ref="greetBefore">
        <aop:after-returning method="sayEnjoy" pointcut='target(com.Waiter) and execution(* serve(..))'/>
    </aop:aspect>
</aop:config>

环绕增强

<aop:config>
    ...
    <aop:aspect ref="greetBefore">
        <aop:around method="aroundMethod" pointcut='execution(* serve(..)) and within(com.Waiter))'/>
    </aop:aspect>
</aop:config>
    public void aroundMethod(ProceedingJoinPoint pjp){
    //pjp可以访问到环绕增强的连接点信息
        ...
    }

抛出异常增强

<aop:config>
    ...
    <aop:aspect ref="greetBefore">
        <aop:after-throwing method="afterThrowingMethod" pointcut='target(com.Waiter) and 
        execution(* serve(..))' throwing='exception'/>
    </aop:aspect>
</aop:config>
public void afterThrowingMethod(Exception exception){
    ...
}

throwing属性声明需要绑定的异常对象,指定的异常名必须和增强方法对应的传入参数一致

final增强

<aop:config>
    ...
    <aop:aspect ref="greetBefore">
        <aop:after method="afterMethod" pointcut='execution(*com.Waiter. serve(..))'/>
    </aop:aspect>
</aop:config>

引介增强


TheViper
465 声望16 粉丝