spring自定义注解使用

注解的定义

@Target

代表注解作用的位置(注解生效位置可设置多个)

可用值 作用位置
ElemenetType.FIELD 类成员
ElemenetType.METHOD 方法
ElemenetType.TYPE 类/接口/枚举
ElemenetType.CONSTRUCTOR 构造器声明

@Retention

代表注解生效的阶段(生命周期)

RetentionPolicy.SOURCE:注解只保留在源文件,当Java文件编译成class文件的时候,注解被遗弃
RetentionPolicy.CLASS:注解被保留到class文件,但jvm加载class文件时候被遗弃,这是默认的生命周期;
RetentionPolicy.RUNTIME:注解不仅被保存到class文件中,jvm加载class文件之后,仍然存在;

@Target(value={ElementType.TYPE,ElementType.FIELD})
@Retention(value = RetentionPolicy.RUNTIME)
public @interface MyAnnotation {

    String value() default "hello";
}

作用于方法的注解

  1. 定义注解
  2. 定义Aspect切面类,设置切点(@PointCut)和拦截逻辑
  3. 将切面类注入到Spring上下文
@Component
@Aspect
public class MyAspect {

    @Pointcut("@annotation(com.qianshan.demo.annotation.MyAnnotation)")
    public void pointCut() {

    }

    @Around("pointCut()&&@annotation(myAnnotation)")
    public Object handle(ProceedingJoinPoint joinPoint, MyAnnotation myAnnotation) throws Throwable {
        System.out.println("注解作用的方法名: " + joinPoint.getSignature().getName());
        System.out.println("所在类的简单类名: " + joinPoint.getSignature().getDeclaringType().getSimpleName());
        System.out.println("所在类的完整类名: " + joinPoint.getSignature().getDeclaringType());
        System.out.println("目标方法的声明类型: " + Modifier.toString(joinPoint.getSignature().getModifiers()));
        //获取注解值
        String value = myAnnotation.value();
        //获取方法参数
        Object args[] = joinPoint.getArgs();
        return joinPoint.proceed();
    }
}

作用于类的注解

使用场景:通常在spring启动时扫描有注解的Bean进行初始化等逻辑,在此以策略模式的实现为例。

1.注解定义

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface Channel {
    //渠道名
    String value() ;
}

2.注解使用

public interface ChannelApi {
    Result refund(RefundRequest refundRequest);
}
@Channel("wechat")
public class WeChatChannel implements ChannelApi {
    @Override
    public Result refund(RefundRequest refundRequest) {
        System.out.println("触发微信退款逻辑");
        return null;
    }
}
@Channel("alipay")
public class AlipayChannel implements ChannelApi {

    @Override
    public Result refund(RefundRequest refundRequest) {
        System.out.println("触发支付宝退款逻辑");
        return null;
    }
}
/**
 * @Author :千山
 * @Date :2019/07/28
 */
@Component
public class PayChannelManager implements ApplicationListener<ContextRefreshedEvent> {
  
    //策略路由
    private Map<String, ChannelApi> channelMap;

    @Override
    public void onApplicationEvent(ContextRefreshedEvent event) {
        ApplicationContext context = event.getApplicationContext();

        Map<String, Object> channelBeanMap = context.getBeansWithAnnotation(Channel.class);

        channelBeanMap.forEach((key, value) -> {
            Object channelInstance = value.getClass();
            String name = channelInstance.getClass().getAnnotation(Channel.class).name();
            channelMap.put(name, (ChannelApi) channelInstance);
        });
    }

    public ChannelApi getChannelInstance(String channelName) {
        return channelMap.get(channelName);
    }
}