专栏首页赵俊的Java专栏Spring 动态注入依赖设计

Spring 动态注入依赖设计

前言

最近在开发一个在线网盘的功能, 支持多个存储策略. 启动时, 读取数据库, 获取当前启用的存储类型, 然后项目启动后, 还可以动态切换存储类型.

由于是基于 Spring 开发的, 所以一般是这么写的:

接口:

public interface FileService {

    /**
     * 接口中的方法, 以此为例.
     */
    void method1();

    /**
     * 获取当前的存储类型
     * @return  存储类型
     */
    String getStorageType();

}

腾讯云实现类:

@Service
public class TencentFileService implements FileService {
    
    @Override
    public void method1() {
        // do something...
    }

    @Override
    public String getStorageType() {
        return "腾讯云";
    }

}

然后在 Controller 层注入:

@Controller
public class FileController {
    
    @Resource
    private FileService fileService;

    @GetMapping("xxx")
    public void method1() {
        fileService.method1();
    }

}

但, 这样肯定会出错的, 因为 FileService 接口, 有两个实现类, 都标注了 @Service, 注入时, Spring 不知道到底注入哪个.

这办法不可行, 即使指定了注入哪个, 也没办法实现动态切换注入的类.

实现

那么换个思路, 不使用 @Resource 注入, 而是在项目启动完后, 获取 FileService 类型的所有类, 然后从数据库获取当前启用的存储类型, set 到 ControllerfileService 属性中. 具体看代码吧:

两个 Service 类的代码不变, 新增获取存储类型的工厂类:

@Component
public class StorageTypeFactory implements ApplicationContextAware {

    private static Map<String, FileService> storageTypeEnumFileServiceMap;

    private static ApplicationContext applicationContext;

     /**
     * 项目启动时执行
     */
    @Override
    public void setApplicationContext(ApplicationContext act) throws BeansException {
        applicationContext = act;
        
        // 获取 Spring 容器中所有 FileService 类型的类
        storageTypeEnumFileServiceMap = act.getBeansOfType(FileService.class);
    }

    /**
     * 获取指定存储类型 Service
     */
    public static FileService getStorageTypeService(String type) {
        FileService result = null;
        for (FileService fileService : storageTypeEnumFileServiceMap.values()) {
            if (fileService.getStorageType() == type) {
                result = fileService;
                break;
            }
        }

        if (result == null) {
            // 未知的存储类型
            throw new UnknownStorageTypeException(type.getDescription());
        }
        return result;
    }

    public static ApplicationContext getApplicationContext() {
        return applicationContext;
    }
}
@Controller
public class FileController {
    
	private FileService fileService;

    @GetMapping("xxx")
    public void method1() {
        fileService.method1();
    }

	/**
     * PostConstruct 注解, 表示该类初始化的时候, 自动调用该方法.
     */
    @PostConstruct
    @GetMapping("/updateStorageType")
    public void initStorageType(String storageType) {
		// 如果 storageType 为空, 则表示是启动时初始化, 有值则说明是 Web 接口动态更改的
		if (storageType == null) {
			// 伪代码, 读取数据库获取当前存储类型
			storageType = xxxService.getCurrentStorage();
		}

		// 设置 fileService 类为当前存储类型对应的 Service
		fileService = StorageTypeFactory.getStorageTypeService(storageType);
    }

}

大概就是这样, 主要就是不直接使用 @Resouce 注入, 而是在启动时, 先获取所有的 Service, 存储到 Map 中, 提供静态方法, 然后利用 @PostConstruct 启动时自动调用初始化方法, 动态注入 fileService.

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • DigitalOcean 挂载 volume 硬盘

    DigitalOcean 的默认硬盘容量只有 25G,但 DigitalOcean 已经在部分服务器区域增加了 volume 的特性,大大方便了用户的存储需求,...

    一份执着✘
  • Java 动态代理初探

    对于使用过 Spring 的朋友, 应该都使用过 AOP, 那么今天我们来对 AOP 的原理: 动态代理 来一探究竟.

    一份执着✘
  • 丑数II

    一份执着✘
  • Hive存储格式简单介绍

    Hive支持的存储格式有: textfile、sequencefile、orc和parquet这几种格式。Hive 的存储方式有列式存储和行式存储。 textf...

    用户7459214
  • 宏杉科技IPO终止审查,资本需对中国存储更多包容!

    近日,证券会公布了最新一期中止审查和终止审查企业名单,一共有7家中止审查和134家终止审查,杭州宏杉科技位列终止审查名单之中。一般而言,拟上市公司在被终止审查之...

    大数据在线
  • 从安全和成本来看企业混合云的演变

    爆炸性的数据让企业考虑混合云存储来满足容量需求。但云的成本和安全问题需要解决。 各种规模的企业都面临非结构化数据集前所未有的增长速度。 增长的速度和使用的容量主...

    静一
  • 轻松入门腾讯云存储系列二:对象存储COS应用类型介绍

    腾讯云对象存储 COS 提供多种类别的云端存储服务,用户可以根据不同的业务类型搭配使用,包括用于频繁访问数据的标准存储、用于不频繁访问数据的低频存储。

    云加社区
  • 存储创新思路思考

    image.png 头图是西雅图风光,站在山上可以眺望华盛顿湖和雷尼尔雪山。 下面这篇文章写的比较highlevel,初学者可能看不懂,欢迎资深人士一起探讨。 ...

    大数据和云计算技术
  • 存储过程

    为了保证数据的完整性、一致性,提高应用性能,常采用存储过程技术。 一个存储过程包括名字、参数列表、及许多SQL语句的语句集。

    cherishspring
  • 聊一聊分布式对象存储解决方案

    OSS(Object Storage Service)俗称对象存储,主要提供图片、文档、音频、视频等二进制文件的海量存储功能。目前除了公有云提供对象存储服务外,...

    大数据技术架构

扫码关注云+社区

领取腾讯云代金券