Bootstrap

springboot学习(六十) springboot中使用ImportSelector


前言

ImportSelector接口是spring中导入外部配置的核心接口,在SpringBoot的自动化配置和@EnableXXX(功能性注解)都有它的存在。

一、ImportSelector是什么?

当在@Configuration标注的配置类上添加@Import引入一个ImportSelector的实现后,会将selectImports函数返回值中按Class名称注册到Spring中。
另外还有一个接口DeferredImportSelector继承自ImportSelector,会在所有@Configuration执行完后再装载DeferredImportSelector引入的Bean。

二、使用步骤

下面以一个缓存配置的例子来说明ImportSelector的使用,实现内存缓存与Redis缓存的切换。

1.准备缓存接口和实现

(1)缓存接口

只是测试,所有只定义了一个测试接口

package com.iscas.springboot.samples.importselector;

/**
 *
 * @author zhuquanwen
 * @vesion 1.0
 * @date 2021/10/24 12:36
 * @since jdk1.8
 */
public interface ICache {
    String test();
}

(2)内存实现

package com.iscas.springboot.samples.importselector;

/**
 *
 * @author zhuquanwen
 * @vesion 1.0
 * @date 2021/10/24 12:37
 * @since jdk1.8
 */
public class MemoryCache implements ICache {
    @Override
    public String test() {
        return "=====测试内存缓存====";
    }
}

(3)Redis实现

package com.iscas.springboot.samples.importselector;

/**
 *
 * @author zhuquanwen
 * @vesion 1.0
 * @date 2021/10/24 12:37
 * @since jdk1.8
 */
public class RedisCache implements ICache {
    @Override
    public String test(){
        return "=====测试Redis缓存====";
    }
}

2.定义ImportSelector实现类

以下代码中根据EnableCachex注解中的不同值来切换缓存的实现类再spring中的注册。

package com.iscas.springboot.samples.importselector;

import org.springframework.cache.Cache;
import org.springframework.context.annotation.ImportSelector;
import org.springframework.core.type.AnnotationMetadata;

import java.text.MessageFormat;
import java.util.Map;

/**
 *
 * @author zhuquanwen
 * @vesion 1.0
 * @date 2021/10/24 12:38
 * @since jdk1.8
 */
public class CacheSelector implements ImportSelector {
    @Override
    public String[] selectImports(AnnotationMetadata importingClassMetadata) {
        Map<String, Object> annotationAttributes = importingClassMetadata.getAnnotationAttributes(EnableCachex.class.getName());
        CacheType type = (CacheType) annotationAttributes.get("type");
        switch (type) {
            case MEMORY: {
                return new String[]{MemoryCache.class.getName()};
            }
            case REDIS: {
                return new String[]{RedisCache.class.getName()};
            }
            default: {
                throw new RuntimeException(MessageFormat.format("unsupport cache type {0}", type.toString()));
            }
        }
    }
}

3.定义注解

package com.iscas.springboot.samples.importselector;

/**
 *
 * @author zhuquanwen
 * @vesion 1.0
 * @date 2021/10/24 12:44
 * @since jdk1.8
 */
public enum CacheType {
    MEMORY, REDIS;
}

package com.iscas.springboot.samples.importselector;

import org.springframework.context.annotation.Import;

import java.lang.annotation.*;

/**
 *
 * @author zhuquanwen
 * @vesion 1.0
 * @date 2021/10/24 12:34
 * @since jdk1.8
 */
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import(CacheSelector.class)
public @interface EnableCachex {
    CacheType type() default CacheType.MEMORY;
}

4.测试

package com.iscas.springboot.samples.importselector;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

/**
 *
 * @author zhuquanwen
 * @vesion 1.0
 * @date 2021/10/24 12:49
 * @since jdk1.8
 */
@RestController
@RequestMapping("/test/cache")
public class CacheTestController {
    @Autowired
    private ICache cache;

    @GetMapping
    public String test() {
        return cache.test();
    }
}

(1)主类上使用Memory
在这里插入图片描述
测试结果:
在这里插入图片描述
(2)主类上使用Redis
在这里插入图片描述
测试结果:
在这里插入图片描述

;