前言
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
测试结果: