API-Server构建指南(2)-使用注解作为功能开关

2019-12-06  本文已影响0人  东阿

Filter 写好了,那么就需要配置上去,我们需要的 优雅的 功能开关,毕竟不是每个项目都要默认启用此FIlter。
听起来最简单的是,读取配置,根据配置项来决定是否注入 某Filter。
遗憾的是,我看到了一个 更装逼,更优雅的方式。
注解。

@UrlParamCheck // 只需要增加这个注解,就可以启用 UrlParamFilter。反之,不启用
public class App  {

    public static void main(String[] args) {
        SpringApplication.run(App.class, args);
    }

}

现在开始动手实现。

第一步 肯定是 定义注解

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)  // 此注解作用于类 上
@Documented
@Import(UrlParamCheckConfigRegistrar.class)
public @interface UrlParamCheck {
    int order() default Ordered.LOWEST_PRECEDENCE;
}


第二步 编写一个工具类,用于 将一个filter 转换为 一份 Bean声明,并注册到 spring bean 声明的注册中心去。

@UtilityClass
@Slf4j
public class BeanDefinitionUtils {

    /**
     * 注册一个 filter
     * @param registry  注册中心 ,待传入
     * @param order  Filter的挂载顺序
     * @param name  spring bean 的名称,全局唯一
     * @param urlPatterns  url过滤规则
     * @param filter  待注册的filter
     */
    public static void registerFilter(BeanDefinitionRegistry registry, int order, String name, Collection<String> urlPatterns, Object filter) {
        if (registry.containsBeanDefinition(name)) {
            log.warn("duplicate beanName, the bean exist in spring IOC,will skip :" + name);
            return;
        }
        BeanDefinition annotationProcessor = BeanDefinitionBuilder
            .genericBeanDefinition(FilterRegistrationBean.class)
            .addPropertyValue("urlPatterns", urlPatterns)
            .addPropertyValue("name", name)
            .addPropertyValue("order", order)
            .addPropertyValue("filter", filter)
            .getBeanDefinition();
        registry.registerBeanDefinition(name, annotationProcessor);
    }
}

第三步,也是最重要的一步 编写 一个bean 声明 注册器

public class UrlParamCheckConfigRegistrar implements ImportBeanDefinitionRegistrar {

    @Override
    public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
        AnnotationAttributes attributes = AnnotationAttributes   //固定写法,用于后续获取 此注解使用时所 定义的属性的值
            .fromMap(importingClassMetadata
            .getAnnotationAttributes(UrlParamCheck.class.getName()));
        int order = attributes.getNumber("order"); // 通过attributes 可以获取注解所定义的属性的值
        // 使用钢材声明的工具类,将 UrlParamCheckFilter 注册进spring
        BeanDefinitionUtils.registerFilter(registry, order, "urlParamCheckFilter", Collections.singleton("/*"), new UrlParamCheckFilter());
    }
}

实现完毕,最核心的就是 通过 注解上的 @Import(UrlParamCheckConfigRegistrar.class) 来引导spring 导入新的注册器,再通过注册器,注册一份新的 bean 声明,此处声明的是一个filter bean。其他的bean可以同样处理。

上一篇下一篇

猜你喜欢

热点阅读