AspectJ 切点指示器-01-args()和@args()

落花浮王杯 提交于 2020-02-27 22:22:38
args() 通过判断目标类方法运行运行时入参对象的类型定义指定连接点
@args() 通过判断目标方法运行时入参对象的类是否标注特定注解来指定连接点

各个类最终结构图如下:

1、Factory

package com.test.aspectj.expression;

/**
 * 工厂接口
 */
public interface Factory {

    // 制作产品
    void make();

    // 运输
    void delivery(String address);
}

2、PhoneFactory

package com.test.aspectj.expression;

import com.test.aspectj.expression.annotation.Log;
import org.springframework.stereotype.Component;

/**
 * 手机工厂
 */
@Component
public class PhoneFactory implements Factory {

    // 制作产品的方法
    @Override
    @Log
    public void make() {
        System.out.println("来自目标类PhoneFactory的消息:生产手机");
    }

    // 运输手机的方法
    @Override
    public void delivery(String address) {
        System.out.println("来自目标类PhoneFactory的消息:运输手机至 " + address);
    }

    // 测试@Within注解
    public void testWithin() {
    }
 }

3、FoodFactory

package com.test.aspectj.expression;

import com.test.aspectj.expression.args.FreshFoodFactory;
import com.test.aspectj.expression.args.FrozenFoodFactory;
import org.springframework.stereotype.Component;

/**
 * 食品工厂
 */
@Component
public class FoodFactory implements Factory {
    // 制作产品的方法
    @Override
    public void make() {
        System.out.println("来自目标类FoodFactory的消息:生产食品");
    }

    // 运输
    @Override
    public void delivery(String address) {
        System.out.println("来自目标类FoodFactory的消息:销售食品至 " + address);
    }

    // 能匹配到 @args(com.test.aspectj.expression.args.Listen) 切入点
    public void testArgsAnnotation(FreshFoodFactory freshFoodFactory) {
    }

    // 不能匹配到 @args(com.test.aspectj.expression.args.Listen) 切入点
    public void testFrozenArgsAnnotation(FrozenFoodFactory frozenFoodFactory) {
    }
}

4、自定义注解 Listen

package com.test.aspectj.expression.args;

import java.lang.annotation.*;

/**
 * 监听注解
 */
@Retention(RetentionPolicy.RUNTIME)
@Target({ ElementType.TYPE, ElementType.METHOD })
@Documented
public @interface Listen {
    String value() default "";
}

5、FreshFoodFactory,注意此类上有@Listen自定义注解,@args(com.test.aspectj.expression.args.Listen) 能匹配到方法入参有FreshFoodFactory的方法。

package com.test.aspectj.expression.args;

import com.test.aspectj.expression.FoodFactory;
import org.springframework.stereotype.Component;

/**
 * 新鲜食品工厂
 */
@Listen
@Component
public class FreshFoodFactory extends FoodFactory {

}

6、FrozenFoodFactory,此类继承FreshFoodFactory,虽然FreshFoodFactory类上有@Listen自定义注解,但是@args(com.test.aspectj.expression.args.Listen) 不能匹配到方法入参是FrozenFoodFactory的方法

package com.test.aspectj.expression.args;

import org.springframework.stereotype.Component;

/**
 * 冷冻食品工厂
 */
@Component
public class FrozenFoodFactory extends FreshFoodFactory {

}

7、切面类 ArgsAspect,args()和@args()代码示例

package com.test.aspectj.expression.args;

import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;

/**
 * args和@args切面逻辑
 */
@Aspect
public class ArgsAspect {

    // args(...)匹配方法入参是String的方法
    @Before("args(java.lang.String)")
    public void before() {
        System.out.println("来自切面里的消息:args匹配方法入参是String的方法");
    }

    // @args(...)匹配入参类上有Listen注解的方法
    @After("@args(com.test.aspectj.expression.args.Listen)")
    public void after() {
        System.out.println("来自切面里的消息:@args匹配到方法执行了");
    }
}

8、xml

<?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"
       xmlns:context="http://www.springframework.org/schema/context"
       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 
       http://www.springframework.org/schema/context 
       http://www.springframework.org/schema/context/spring-context.xsd">
    
    <context:component-scan base-package="com.test.aspectj.expression"/>
    <bean id="annotationAspect" class="com.test.aspectj.expression.args.ArgsAspect"/>
    <aop:aspectj-autoproxy proxy-target-class="true"/>
</beans>

9、测试代码

package com.test.aspectj.expression.args;

import com.test.aspectj.expression.Factory;
import com.test.aspectj.expression.FoodFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

/**
 * 测试 args() 和 @args()
 */
public class AspectJExpressionDemo {
    public static void main(String[] args) {
        System.out.println("=============== 测试 args() 开始 ===============");
        ApplicationContext context = new ClassPathXmlApplicationContext("classpath:spring-chapter3-aspectjargsexpression.xml");
        System.out.println("----- FoodFactory#delivery(String)会被args匹配 -----");
        FoodFactory foodFactory = (FoodFactory) context.getBean("foodFactory");
        foodFactory.delivery("上海");
        System.out.println("----- PhoneFactory#delivery(String)会被args匹配 -----");
        Factory phoneFactory = (Factory) context.getBean("phoneFactory");
        phoneFactory.delivery("北京");
        System.out.println("=============== 测试 args() 结束 ===============");
        System.out.println();
        System.out.println("=============== 测试 @args() 开始 ===============");
        System.out.println("----- FreshFoodFactory#testArgsAnnotation(FreshFoodFactory)会被@args匹配 -----");
        FreshFoodFactory freshFoodFactory = (FreshFoodFactory) context.getBean("freshFoodFactory");
        freshFoodFactory.testArgsAnnotation(freshFoodFactory);
        System.out.println("----- FrozenFoodFactory#testArgsAnnotation(FreshFoodFactory)会被@args匹配 -----");
        FrozenFoodFactory frozenFoodFactory = (FrozenFoodFactory) context.getBean("frozenFoodFactory");
        frozenFoodFactory.testArgsAnnotation(frozenFoodFactory);
        System.out.println("----- FrozenFoodFactory#testFrozenArgsAnnotation(FrozenFoodFactory)不会被@args匹配 -----");
        frozenFoodFactory.testFrozenArgsAnnotation(frozenFoodFactory);
        System.out.println("=============== 测试 @args() 结束 ===============");
    }
}

10、运行结果

=============== 测试 args() 开始 ===============
----- FoodFactory#delivery(String)会被args匹配 -----
来自切面里的消息:args匹配方法入参是String的方法
来自目标类FoodFactory的消息:销售食品至 上海
----- PhoneFactory#delivery(String)会被args匹配 -----
来自切面里的消息:args匹配方法入参是String的方法
来自目标类PhoneFactory的消息:运输手机至 北京
=============== 测试 args() 结束 ===============

=============== 测试 @args() 开始 ===============
----- FreshFoodFactory#testArgsAnnotation(FreshFoodFactory)会被@args匹配 -----
来自切面里的消息:@args匹配到方法执行了
----- FrozenFoodFactory#testArgsAnnotation(FreshFoodFactory)会被@args匹配 -----
来自切面里的消息:@args匹配到方法执行了
----- FrozenFoodFactory#testFrozenArgsAnnotation(FrozenFoodFactory)不会被@args匹配 -----
=============== 测试 @args() 结束 ===============

11、结论

args(java.lang.String)匹配方法入参是String的方法

@args(com.test.aspectj.expression.args.Listen)匹配入参类上有Listen注解的方法

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!