利用注解指定Spring启动时加载的bean

在开发的过程中,一个接口往往有多个实现类。但根据需求,不一定会使用到所有的实现类。

以本人当前遇到的需求为例,一个系统不同的国家部署时,需要使用不同的实现类。在此给出基于注解的实现方法。

1.注解定义

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface Adapter {

    /** 环境value */
    AdapterEnv[] value();

    /** bean 名称 */
    String name();

    enum AdapterEnv{
        // 不同国家的枚举
        TH("th"), CN("cn"), ID("id");
        String value;
        AdapterEnv(String value) {
            this.value = value;
        }
        public static AdapterEnv parse(String value) {
            for (AdapterEnv adapterEnv : AdapterEnv.values()) {
                if (adapterEnv.value.equals(value)) {
                    return adapterEnv;
                }
            }
            throw new RuntimeException("error adapter env");
        }
    }
}

2. 注解实现

public class I18nAdapterBeanDefinitionRegistry implements ResourceLoaderAware, BeanFactoryPostProcessor {
    // 扫描路径
    private static final String DEFAULT_RESOURCE_PATTERN = "**/*.class";

    private ResourcePatternResolver resourcePatternResolver = new PathMatchingResourcePatternResolver();
    private MetadataReaderFactory metadataReaderFactory = new CachingMetadataReaderFactory(this.resourcePatternResolver);
    // 通过配置文件注入
    private String i18nAdapterValue;

    // bean初始化处理
    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory configurableListableBeanFactory) throws BeansException {
        if (configurableListableBeanFactory instanceof BeanDefinitionRegistry) {
            postProcessBeanDefinitionRegistry((BeanDefinitionRegistry) configurableListableBeanFactory);
        }
    }

    public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry beanDefinitionRegistry) throws BeansException {

        // bean定义map
        Map<String, AdapterBeanDefinitionInfo> definitionMap = new LinkedHashMap<String, AdapterBeanDefinitionInfo>();
        // 注解中的值不符合当前环境的bean定义map
        Map<String, AdapterBeanDefinitionInfo> nullDefinitionMap = new LinkedHashMap<String, AdapterBeanDefinitionInfo>();

        // 扫描指定包
        String basePackage = "com.xx.service.adapter";
        Set<Class<?>> classes = scannerPackages(basePackage);

        Adapter.AdapterEnv i18nAdapterEnv = Adapter.AdapterEnv.parse(i18nAdapterValue);
        for (Class<?> adapterClass : classes) {
            // 检查注解
            Adapter annotation = adapterClass.getAnnotation(Adapter.class);
            if (annotation == null) {
                continue;
            }

            // bean 名称
            String beanName = annotation.name();
            // bean 环境
            Adapter.AdapterEnv[] values = annotation.value();
            // bean 实现的接口
            Class<?>[] interfaces = adapterClass.getInterfaces();

            if (StringUtils.isBlank(beanName) || ArrayUtils.isEmpty(values) || ArrayUtils.isEmpty(interfaces)) {
                continue;
            }
            //判断是否是当前环境需要加载的bean
            // 校验bean 接口
            AdapterBeanDefinitionInfo definitionInfo;
            if (ArrayUtils.contains(values, i18nAdapterEnv)) {
                if (definitionMap.containsKey(beanName)) {
                    definitionInfo = definitionMap.get(beanName);
                } else {
                    definitionInfo = new AdapterBeanDefinitionInfo(beanName);
                    definitionMap.put(beanName, definitionInfo);
                }
                definitionInfo.setInterface(interfaces);
                RootBeanDefinition beanDefinition = new RootBeanDefinition(adapterClass);
                beanDefinition.setAutowireMode(AUTOWIRE_BY_NAME);
                definitionInfo.setAdapterClass(adapterClass);
                definitionInfo.setBeanDefinition(beanDefinition);
            }else {
                if (nullDefinitionMap.containsKey(beanName)) {
                    definitionInfo = nullDefinitionMap.get(beanName);
                } else {
                    definitionInfo = new AdapterBeanDefinitionInfo(beanName);
                    nullDefinitionMap.put(beanName, definitionInfo);
                }
                definitionInfo.setAdapterClass(adapterClass);
                definitionInfo.setInterface(interfaces);
            }
        }
        Map<String, AdapterBeanDefinitionInfo> checkNullDefinitionMap = new LinkedHashMap<String, AdapterBeanDefinitionInfo>();

        if(MapUtils.isNotEmpty(nullDefinitionMap)) {
            // 循环判断,不符合当前环境的bean是否已经在定义map中
            // 如果对应的名称已有bean,则忽略
        	for (Entry<String, AdapterBeanDefinitionInfo>  adapterBeanDefinitionEntry : nullDefinitionMap.entrySet()) {
        		// 生成定义
        		String beanNameTemp=adapterBeanDefinitionEntry.getKey();
        		//已有实例 不需要在做空的 bean
        		if(!definitionMap.containsKey(beanNameTemp)) {
        			AdapterBeanDefinitionInfo adapterBeanDefinition =adapterBeanDefinitionEntry.getValue();
        			BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(adapterBeanDefinition.getAdapterClass());
        			GenericBeanDefinition definition = (GenericBeanDefinition) builder.getRawBeanDefinition();
        			
        			definition.getConstructorArgumentValues().addGenericArgumentValue(adapterBeanDefinition.getAdapterClass());
        			definition.setBeanClass(I18nNullAdapterFactoryBean.class);
        			definition.setAutowireMode(AUTOWIRE_BY_NAME);
        			adapterBeanDefinition.setBeanDefinition(definition);
        			checkNullDefinitionMap.put(beanNameTemp, adapterBeanDefinition);
        		}
			}
        }
        definitionMap.putAll(checkNullDefinitionMap);

        // 注册bean
        for (AdapterBeanDefinitionInfo definitionInfo : definitionMap.values()) {
            beanDefinitionRegistry.registerBeanDefinition(definitionInfo.getBeanName(), definitionInfo.getBeanDefinition());
        }
    }

    // 扫描包class
    private Set<Class<?>> scannerPackages(String basePackage) {
        Set<Class<?>> set = new LinkedHashSet<Class<?>>();
        String packageSearchPath = ResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX +
                resolveBasePackage(basePackage) + '/' + DEFAULT_RESOURCE_PATTERN;
        try {
            Resource[] resources = this.resourcePatternResolver.getResources(packageSearchPath);
            for (Resource resource : resources) {
                if (resource.isReadable()) {
                    MetadataReader metadataReader = this.metadataReaderFactory.getMetadataReader(resource);
                    String className = metadataReader.getClassMetadata().getClassName();
                    Class<?> clazz;
                    try {
                        clazz = Class.forName(className);
                        set.add(clazz);
                    } catch (ClassNotFoundException e) {
                        e.printStackTrace();
                    }
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        return set;
    }

    private String resolveBasePackage(String basePackage) {
        return ClassUtils.convertClassNameToResourcePath(SystemPropertyUtils.resolvePlaceholders(basePackage));
    }

    public void setResourceLoader(ResourceLoader resourceLoader) {
        this.resourcePatternResolver = ResourcePatternUtils.getResourcePatternResolver(resourceLoader);
        this.metadataReaderFactory = new CachingMetadataReaderFactory(resourceLoader);
    }

    public String getI18nAdapterValue() {
        return i18nAdapterValue;
    }

    public void setI18nAdapterValue(String i18nAdapterValue) {
        this.i18nAdapterValue = i18nAdapterValue;
    }
}

3.配置文件

    <bean class="com.xx.adapter.I18nAdapterBeanDefinitionRegistry">
        <property name="i18nAdapterValue" value="cn"/>
    </bean>

4.使用

@Adapter(name = "adminAdapterService", value = Adapter.AdapterEnv.CN)
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值