Spring中在Bean实例上加入自定义注解 避免硬编码大量的@Qualifier

admin 2021-09-08 PM 116℃ 0条

在Spring日常开发中, 一个比较常见的场景是, 对于一个Service接口, 我们有多个实现, 举个例子, 定义如下接口

interface Say {
    void sayhello();
}

然后对于此接口, 我们有多个实现

@Service
public class CatSay implements Say {
    @Override
    public void sayhello() {
        System.out.println("Cat Say");
    }
}

@Service
public class DogSay implements Say {
    @Override
    public void sayhello() {
        System.out.println("Dog Say");
    }
}

在使用的时候, 很大概率我们必须根据Bean的名称注入两个service示例出来, 这样就出现了大量的意大利面条式的代码, 非常不美观。

我们可以通过 自定义注解 + 自定义Enum 来实现一个 该Service的注册器, 在使用的时候只需要根据业务自动生成枚举, 然后根据枚举中 注册器中拿到这个Service即可。 操作步骤如下

实现一个枚举

该枚举的目标是用来区分不同的业务类型

public enum BizEnums {
    BIZ_CAT,
    BIZ_DOG
}

实现一个自定义注解

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface BizConfig {
    BizEnums bizType();
}

实现一个注册器 扫描Service实现

@Service
public class SayRegisty implements ApplicationListener<ContextRefreshedEvent> {
      private Map<BizEnums , Say > assembleMap;
      
      @Override
    public void onApplicationEvent(ContextRefreshedEvent event) {
        Map<String, Object> beansMap = event.getApplicationContext().getBeansWithAnnotation(BizConfig.class);
        Map<BackArchEnums, Say> _tmpMap = new HashMap<>();

        for(Object object : beansMap.values()) {
            if(object instanceof Say) {
                Say assembler = (Say ) object;
                BackArch annotation = assembler.getClass().getAnnotation(BizConfig .class);
                _tmpMap.put(annotation.bizType(), assembler);
            }
        }
        assembleMap = _tmpMap;
     
    }

    public Say get(BizEnums evt) {
        return assembleMap.getOrDefault(evt, null);
    }

}

使用Registry

//先注入SayRegisty 
sayRegsty.get(BizEnums.BIZ_DOG).sayHello();
sayRegsty.get(BizEnums.BIZ_CAT).sayHello();
标签: none

非特殊说明,本博所有文章均为博主原创。

评论啦~