基于@Aspect 的 spring aop注解基础

1. 注解基础

  • @Before
    先看@Before源码
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface Before {

    /**
     * 指定切点的位置
     */
    String value(); 
    /**
     * 获取目标方法的参数和对应的值,比较难理解
     */
    String argNames() default "";
}

代码示例如下:

public interface Waiter {
    void serveTo(String clientName);
    void greetTo(String clientName);
    void greetTo(String a,String b);
}
public class NaiveWaiter implements Waiter {
    @Override
    public void serveTo(String clientName) {

        System.out.println("serveTo:"+clientName);
    }

    @Override
    public void greetTo(String clientName) {

        System.out.println("greetTo:"+clientName);
    }

    @Override
    public void greetTo(String a, String b) {

        System.out.println("NaiveWaiter.greetTo:"+a+" "+b);
    }
}
public class NaughtWaiter implements Waiter {
    @Override
    public void serveTo(String clientName) {
        System.out.println("NaughtWaiter.serveTo:"+clientName);
    }

    @NeedTest
    @Override
    public void greetTo(String clientName) {

        System.out.println("NaughtWaiter.greetTo:"+clientName);
    }

    @NeedTest
    @Override
    public void greetTo(String a,String b) {

        System.out.println("NaughtWaiter.greetTo:"+a+" "+b);
    }
}
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.FIELD,ElementType.METHOD})
public @interface NeedTest {
}
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;

@Aspect
public class TestAspect {

    @Before(value = "@annotation(com.ghq.cloud.anno.NeedTest) && args(a,b)",argNames="a,b")
    public void needTestFun(String a, String b){
        System.out.println("TestAspect.needTestFun:"+a+" "+b);
    }
}

说明:

  1. @Before(value = “@annotation(com.ghq.cloud.anno.NeedTest) && args(a,b)”,argNames=“a,b”)
  2. 这里的 @annotation(com.ghq.cloud.anno.NeedTest) 表示声明有@NeedTest注解
  3. 这里的 && 表示 并且 连接符
  4. 这里的 args(a,b) 表示方法有两个参数,
  5. argNames=“a,b”,表示参数名字为 a,b,顺序必须一直,切面里面的方法的参数名(这里为 TestAspect #needTestFun)必须为a 和 b
  6. 目标方法 的参数类型必须 和 切面里面的方法的参数类型保持一致,否则不能增强。参数名字不必和 切面里面的方法的参数名字保持一致。

main方法:

public class AnnoTest {

    public static void main(String[] args) {

        ApplicationContext context =
                new ClassPathXmlApplicationContext("classpath:anno.xml");

        Waiter naiveWaiter = (Waiter) context.getBean("naiveWaiter");
        Waiter naughtWaiter = (Waiter)  context.getBean("naughtWaiter");

        naiveWaiter.greetTo("snow","xxx");
        naughtWaiter.greetTo("aaaaaa","bbbbb");
    }
}

输出结果:只有NaughtWaiter #void greetTo(String a,String b)方法增强了

NaiveWaiter.greetTo:snow xxx
TestAspect.needTestFun:aaaaaa bbbbb
NaughtWaiter.greetTo:aaaaaa bbbbb
  • @AfterReturning
    源码:
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface AfterReturning {

    /**
     * 切点表达式:增强绑定的位置
     */
    String value() default "";

    /**
     * 切点表达式:增强绑定的位置 ,当指定了pointcut,将覆盖 
     */
    String pointcut() default "";

    /**
     * The name of the argument in the advice signature to bind the returned value to
     */
    String returning() default "";
    
    /**
     * 同@Before
     */
    String argNames() default "";

}

使用:

    @AfterReturning(pointcut = "@annotation(com.ghq.cloud.anno.NeedTest)",returning = "ret")
    public void testAfterReturning(Object ret){//Joinpoint joinpoint,
        System.out.println("bb");
        System.out.println(ret+" "+"bb");
    }

注意:目标方法抛出异常之后,增强不会执行。可以该表目标方法的返回引用的属性值。

  • @After
    /*@After(value = "@annotation(com.ghq.cloud.anno.NeedTest) && args(a,b) ",argNames="a,b")
    public void testAfterReturning(String a, String b){
        System.out.println("bb");
    }*/

    @After(value = "@annotation(com.ghq.cloud.anno.NeedTest)")
    public void testAfterReturning(){
        System.out.println("bb");
    }

注意:目标方法抛出异常之后,增强会执行。不可以改变目标方法的返回值。


  • @Around 略去
  • @AfterThrowing 略去
  • @DeclareParents 相当于引介增强,案例说明如何使用
    示例
public interface Waiter {
    void serveTo(String clientName);
    void greetTo(String clientName);
}
public class NaiveWaiter implements Waiter {
    @Override
    public void serveTo(String clientName) {

        System.out.println("serveTo:"+clientName);
    }

    @Override
    public void greetTo(String clientName) {

        System.out.println("greetTo:"+clientName);
    }
}

想法:希望 NaiveWaiter 也能充当售货员的角色,即通过切面技术为 NaiveWaiter 新增 Seller 接口的实现

/**
 * 想法:希望 NaiveWaiter 也能充当售货员的角色,
 * 即通过切面技术为 NaiveWaiter 新增 Seller 接口的实现
 */
@Aspect
public class EnableSellerAspect {

    /**
     * @DeclareParents:引介增强,相当于 IntroductionInterceptor
     * value : 该成员用于定义切点,它表示在哪个目标类上添加引介增强
     * defaultImpl:默认的接口实现类
     */
    @DeclareParents(value = "com.ghq.cloud.anno.NaiveWaiter",defaultImpl = SmartSeller.class)
    public Seller seller;//要实现的目标接口
}

xml配置:

    <aop:aspectj-autoproxy/>

    <bean id="naiveWaiter" class="com.ghq.cloud.anno.NaiveWaiter"/>
    <bean class="com.ghq.cloud.anno.EnableSellerAspect"/>

main方法:

public class AnnoTest {

    public static void main(String[] args) {

        ApplicationContext context =
                new ClassPathXmlApplicationContext("classpath:anno.xml");

        Waiter naiveWaiter = (Waiter) context.getBean("naiveWaiter");
        naiveWaiter.greetTo("snow");

        Seller seller = (Seller) naiveWaiter;
        seller.sell("apple");
    }
}

输出结果:

greetTo:snow
sell:apple

说明:Seller seller = (Seller) naiveWaiter; 转换成功,Waiter naiveWaiter 自动实现了Seller接口

完。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值