多个Bean自动注入成Map @Autowired @Service 策略模式

需求

将多个策略的具体实现自动注入到Map中

准备

一个接口,有doSomething()方法

多个具体实现策略,实现doSomething()方法

一个Controller,用于测试自动注入

源代码

java 复制代码
public interface DemoInterface
{
    void doSomething();
}

@Service
public class DemoService implements DemoInterface
{
    public void doSomething()
    {
        System.out.println("call me");
    }
}

@Service("my-own-name-2")
public class DemoService2 implements DemoInterface
{
    public void doSomething()
    {
        System.out.println("2 call me");
    }
}

@Component
public class DemoService3 implements DemoInterface
{
    public void doSomething()
    {
        System.out.println("3 call me");
    }
}

@RestController
public class DemoController
{
    @Autowired
    private Map<String,DemoInterface> demoServiceMap;
​
    @GetMapping("/test")
    public String test(){
        for(Map.Entry<String, DemoInterface> entry : demoServiceMap.entrySet()){
            System.out.println(entry.getKey());
            System.out.println(entry.getValue());
        }
        return "succ";
    }
}

测试结果

java 复制代码
demoService
com.example.testtwo.DemoService@75d2647f
my-own-name-2
com.example.testtwo.DemoService2@1a5055cf
demoService3
com.example.testtwo.DemoService3@fe6916c

策略模式实现

需求

文件上传功能,可以使用oss和minio两种方式

准备

策略接口,包含uploadFile()方法

java 复制代码
public interface UploadStrategy {
    String uploadFile(MultipartFile file, String path);
    String uploadFile(String fileName, InputStream inputStream, String path);
}

抽象实现,抽象出一些公共逻辑,留出不同策略区别的方法进一步具体实现(非必要)

java 复制代码
public abstract class AbstractUploadStrategyImpl implements UploadStrategy{
    @Override
    public String uploadFile(MultipartFile file, String path) {
        try {
            String md5 = FileUtil.getMd5(file.getInputStream());
            String extName = FileUtil.getExtName(file.getOriginalFilename());
            String fileName = md5 + extName;
            if (!exists(path + fileName)) {
                upload(path, fileName, file.getInputStream());
            }
            return getFileAccessUrl(path + fileName);
        } catch (Exception e) {
            e.printStackTrace();
            throw new BizException("文件上传失败");
        }
    }
    @Override
    public String uploadFile(String fileName, InputStream inputStream, String path) {
        try {
            upload(path, fileName, inputStream); // 具体上传策略
            return getFileAccessUrl(path + fileName); // 具体文件路径
        } catch (Exception e) {
            e.printStackTrace();
            throw new BizException("文件上传失败");
        }
    }
    public abstract Boolean exists(String filePath);
​
    public abstract void upload(String path, String fileName, InputStream inputStream) throws IOException;
​
    public abstract String getFileAccessUrl(String filePath);
}

具体实现

Oss

java 复制代码
@Service("ossUploadStrategyImpl")
public class OssUploadStrategyImpl extends AbstractUploadStrategyImpl {

    @Autowired
    private OssConfigProperties ossConfigProperties;

    @Override
    public Boolean exists(String filePath) {
        return getOssClient().doesObjectExist(ossConfigProperties.getBucketName(), filePath);
    }

    @Override
    public void upload(String path, String fileName, InputStream inputStream) {
        getOssClient().putObject(ossConfigProperties.getBucketName(), path + fileName, inputStream);
    }

    @Override
    public String getFileAccessUrl(String filePath) {
        return ossConfigProperties.getUrl() + filePath;
    }

    private OSS getOssClient() {
        return new OSSClientBuilder().build(ossConfigProperties.getEndpoint(), ossConfigProperties.getAccessKeyId(), ossConfigProperties.getAccessKeySecret());
    }

}

Minio

java 复制代码
@Service("minioUploadStrategyImpl")
public class MinioUploadStrategyImpl extends AbstractUploadStrategyImpl {

    @Autowired
    private MinioProperties minioProperties;

    @Override
    public Boolean exists(String filePath) {
        boolean exist = true;
        try {
            getMinioClient()
                    .statObject(StatObjectArgs.builder().bucket(minioProperties.getBucketName()).object(filePath).build());
        } catch (Exception e) {
            exist = false;
        }
        return exist;
    }

    @SneakyThrows
    @Override
    public void upload(String path, String fileName, InputStream inputStream) {
        getMinioClient().putObject(
                PutObjectArgs.builder().bucket(minioProperties.getBucketName()).object(path + fileName).stream(
                                inputStream, inputStream.available(), -1)
                        .build());
    }

    @Override
    public String getFileAccessUrl(String filePath) {
        return minioProperties.getUrl() + filePath;
    }

    private MinioClient getMinioClient() {
        return MinioClient.builder()
                .endpoint(minioProperties.getEndpoint())
                .credentials(minioProperties.getAccessKey(), minioProperties.getSecretKey())
                .build();
    }

}

枚举

java 复制代码
// 把复杂的方法名与实际技术名词对应
public enum UploadModeEnum {

    OSS("oss", "ossUploadStrategyImpl"),

    MINIO("minio", "minioUploadStrategyImpl");

    private final String mode;

    private final String strategy;

    public static String getStrategy(String mode) {
        for (UploadModeEnum value : UploadModeEnum.values()) {
            if (value.getMode().equals(mode)) {
                return value.getStrategy();
            }
        }
        return null;
    }

}

使用

java 复制代码
@Autowired
private Map<String, UploadStrategy> uploadStrategyMap; // 自动注入UploadStrategy接口的实现类

uploadStrategyMap.get(getStrategy("oss")).uploadFile(file, path); // 先根据技术名词获得策略具体实现方法名,再从map中拿到对象,调用对象方法

参考

源码:https://github.com/linhaojun857/aurora

原理:https://www.cnblogs.com/lifullmoon/p/14453011.html

相关推荐
意法半导体STM324 小时前
【官方原创】如何为STM32CubeMX2配置Visual Studio Code配置方案
vscode·stm32·单片机·嵌入式硬件·策略模式·stm32cubemx·嵌入式开发
山东点狮信息科技有限公司19 小时前
企业级 MES 制造执行系统架构设计与实践
spring cloud·性能优化·系统架构·策略模式·点狮
zzqssliu1 天前
基于策略模式与责任链的代购商品多源采集架构实战
架构·策略模式
mxpan2 天前
macOS 13+ 上使用 macFUSE + NTFS-3G 读写 NTFS 移动硬盘技术说明
macos·策略模式
折哥的程序人生 · 物流技术专研2 天前
Java 23 种设计模式:从踩坑到精通 | 番外:编排器+策略模式在多平台电子面单中的实战(含性能压测)
设计模式·策略模式·代码重构·java设计模式·编排器·电子面单·从踩坑到精通
忧云3 天前
2026年最新 Cursor 国内使用 DeepSeek API等各模型使用完整教程
ai编程·策略模式·cursor·byok·cursor使用国内大模型
AIex-YH3 天前
三域贯通11/12:生物制造的“死亡之谷“,CDMO 是桥还是船?
运维·制造·策略模式
回忆2012初秋4 天前
【Nginx】原理、配置与运维实战(2)
运维·nginx·策略模式
怎么没有名字注册了啊4 天前
macOS 基于 CSDN GitCode + Homebrew Tap 发布 Qt .app 二进制程序通用教程(homebrew 安装自己的软件)
策略模式·homebrew·formula·ruhy
坏小虎5 天前
macOS 安装 Ghostty 终端完整教程:环境、依赖与美化配置
macos·策略模式