如何重构Spring+Java8环境下的多实例POJO保存方法?
嘿,这场景我太熟悉了!当你要处理十几个实体对应各自服务的保存逻辑时,一堆if-else或者switch case不仅写起来烦,后续新增实体还要改核心代码,完全是维护噩梦——尤其是你这还13个服务呢!我给你几个靠谱的重构方案,按需选:
方案1:策略模式(最推荐,符合开闭原则)
这种方式把每个实体的保存逻辑封装成独立策略,新增实体只需要加策略类,不用动原有代码,完美解决扩展性问题。
首先定义一个通用的保存策略接口:
public interface EntitySaveStrategy<T> { // 返回当前策略支持的实体类型 Class<T> getEntityClass(); // 执行保存操作 void save(T entity); }
然后为每个实体写对应的策略实现类(比如Activite的):
@Component public class ActiviteSaveStrategy implements EntitySaveStrategy<Activite> { private final ActiviteService activiteService; // 构造注入(比@Autowired更优雅) public ActiviteSaveStrategy(ActiviteService activiteService) { this.activiteService = activiteService; } @Override public Class<Activite> getEntityClass() { return Activite.class; } @Override public void save(Activite entity) { activiteService.create(entity); } }
接下来写一个策略管理器,把所有策略注入并维护类型到策略的映射:
@Component public class EntitySaveManager { private final Map<Class<?>, EntitySaveStrategy<?>> strategyMap; // 注入所有实现了EntitySaveStrategy的Bean public EntitySaveManager(List<EntitySaveStrategy<?>> strategies) { this.strategyMap = strategies.stream() .collect(Collectors.toMap( EntitySaveStrategy::getEntityClass, Function.identity() )); } @SuppressWarnings("unchecked") public <T> void save(T entity) { EntitySaveStrategy<T> strategy = (EntitySaveStrategy<T>) strategyMap.get(entity.getClass()); if (strategy == null) { throw new IllegalArgumentException("找不到对应实体的保存策略:" + entity.getClass().getName()); } strategy.save(entity); } }
最后你的业务方法就可以简化成一行:
@Autowired private EntitySaveManager saveManager; public void handleEntitySave(Object entity) { saveManager.save(entity); }
以后新增实体?只需要写个对应的XxxSaveStrategy类就行,完全不用碰核心的保存逻辑,太省心了!
方案2:Spring Bean名称映射(简洁但依赖命名规范)
如果你的服务命名严格遵循「实体名首字母小写 + Service」的规则(比如Activite对应activiteService),可以直接利用Spring的上下文来动态获取服务Bean,代码量更少。
首先给所有服务定义一个通用父接口:
public interface BaseService<T> { void create(T entity); } // 让你的所有服务都继承它,比如: public interface ActiviteService extends BaseService<Activite> { // 原有方法... }
然后写一个统一的保存服务:
@Component public class EntitySaveService { private final ApplicationContext applicationContext; public EntitySaveService(ApplicationContext applicationContext) { this.applicationContext = applicationContext; } @SuppressWarnings("unchecked") public <T> void save(T entity) { String entitySimpleName = entity.getClass().getSimpleName(); // 生成对应的服务Bean名称(首字母小写) String serviceBeanName = Character.toLowerCase(entitySimpleName.charAt(0)) + entitySimpleName.substring(1) + "Service"; BaseService<T> service = (BaseService<T>) applicationContext.getBean(serviceBeanName); service.create(entity); } }
这种方式的好处是代码极简,但缺点是依赖命名规范——如果某个服务的Bean名称不符合规则,就得特殊处理,灵活性稍差。
方案3:枚举映射(适合实体数量固定的场景)
如果13个实体短期内不会新增太多,用枚举来维护实体和服务的映射也可以,比一堆if-else好看多了。
先定义枚举:
public enum EntityServiceMapping { ACTIVITE(Activite.class, ActiviteService.class), ADRESSE_MS_SANTE(AdresseMsSante.class, AdresseMsSanteService.class), // 把剩下11个实体的映射都加上... ; private final Class<?> entityClass; private final Class<? extends BaseService<?>> serviceClass; EntityServiceMapping(Class<?> entityClass, Class<? extends BaseService<?>> serviceClass) { this.entityClass = entityClass; this.serviceClass = serviceClass; } public static EntityServiceMapping getByEntityClass(Class<?> entityClass) { for (EntityServiceMapping mapping : values()) { if (mapping.entityClass.equals(entityClass)) { return mapping; } } throw new IllegalArgumentException("找不到实体对应的服务映射:" + entityClass.getName()); } public Class<? extends BaseService<?>> getServiceClass() { return serviceClass; } }
然后在保存方法里用:
@Autowired private ApplicationContext applicationContext; public <T> void save(T entity) { EntityServiceMapping mapping = EntityServiceMapping.getByEntityClass(entity.getClass()); BaseService<T> service = (BaseService<T>) applicationContext.getBean(mapping.getServiceClass()); service.create(entity); }
这种方式比if-else整洁,但新增实体需要修改枚举,还是违反开闭原则,适合实体数量稳定的场景。
内容的提问来源于stack exchange,提问作者DALDOUL
相关产品推荐
相关产品推荐

