一个接口有多个实现类,@Autowired注入map方式初始化实现类并统一调用

使用原因和场景

在工作中经常会遇到一个接口有很多实现类,然后需要定义一个统一的入口去调用,如果每次都注入不同的实现类,不符合Java的对开放-关闭原则(Open-Closed Principle, OCP),且代码冗余不好看。

//使用了策略模式
@Autowired
private Map<String, OrderService> beanFactory = Maps.newConcurrentMap();

Spring 会在启动时,自动查找实现了该接口的 bean,放到这个Map中去。 key为bean的名字,value为 实现了该接口的所有的 bean。

注意:这里只有在map的key为string类型时才有效;

具体的代码实现

1、定义接口的调用工厂

初始化所有的OrderService实现类并通过OrderFactory 来调用具体的实现类
Map<String, OrderService> String参数 是定义的service的类名,可以使用@Component(“AA”) 重命名为AA

@Slf4j
@Service
public class OrderFactory {
    /**
    *策略模式
    *会在spring启动时把所有OrderService加载到map中
    *关键在于 @Autowired
    **/
    @Autowired
    private Map<String, OrderService> beanFactory = Maps.newConcurrentMap();

    public OrderService get(String key){
        OrderService orderService = beanFactory.get(key);
        if(orderService == null) {
            throw new RuntimeException("no OrderService defined!");
        }
        return beanFactory.get(key);
    }

    public void put(String key, OrderService service){
        beanFactory.put(key, service);
    }

}

2、定义接口类

定义一个接口,用于提供统一的调用方法

public interface OrderService{
    /**
     *处理订单
     * @params orderNo 订单号
     * @params orderType 订单类型
    * */
    String dealOrdering(String orderNo,String orderType );
}
3、定义接口抽象实现类

定义一个抽象类,实现OrderService接口,提供多个实现类的通用方法,并提供一个业务逻辑处理抽象方法,让具体实现类各自实现自己的业务逻辑。所有通用的逻辑都可以抽出来,放在这个类里面处理。

@Service
public abstract class OrderAbstractService implements OrderService{
   
	//提供统一的逻辑校验等方法
    public boolean checkRepay(String orderNo,String orderType ){
    	Boolean check=false;
		//可以进行防重复校验
		//日志记录
		//其他
        return check;
    }

	//重写接口方法,做一些通用的逻辑处理,比如防重等
    @Override
    public String dealOrdering(String orderNo,String orderType ){
        //1.防重校验,如果校验为true,则不需要走dealOrder方法,直接返回Success
        if( checkRepay(orderNo,orderType )){
            return "Success";
        }

         return dealOrder(orderNo,orderType );
    }

	//抽象方法,各自具体实现类的逻辑处理
    public abstract String dealOrder(String orderNo,String orderType);

}
4、定义接口的多个实际业务实现类

下方是三个具体的实现类,继续抽象类OrderAbstractService ,实现各自业务逻辑

@Slf4j
@Component("OrderBenchiCar")
public class OrderBenchiCarService extends OrderAbstractService {

	//实现抽象类的dealOrder,具体实现逻辑处理
    @Override
    public String dealOrder(String orderNo,String orderType) {
		String returnMsg="";
        //2.处理奔驰汽车订单的生产逻辑
      
        //3.调用结果
        return returnMsg;
    }
}

@Slf4j
@Component("OrderBaomaCar")
public class OrderBaomaCarService extends OrderAbstractService {

	//实现抽象类的dealOrder,具体实现逻辑处理
    @Override
    public String dealOrder(String orderNo,String orderType) {
		String returnMsg="";
        //2.处理宝马汽车订单的生产逻辑
      
        //3.调用结果
        return returnMsg;
    }
}

@Slf4j
@Component("OrderAodiCar")
public class OrderAodiCarService extends OrderAbstractService {

	//实现抽象类的dealOrder,具体实现逻辑处理
    @Override
    public String dealOrder(String orderNo,String orderType) {
		String returnMsg="";
        //2.处理奥迪汽车订单的生产逻辑
      
        //3.调用结果
        return returnMsg;
    }
}
5、实际业务调用类

该类为所有此类型业务处理的统一入口,用来接收不同业务类型,然后进行统一调用处理

@Slf4j
@Service
public class OrderControl {

	//统一入口方法,根据传入的ordertype来决定具体的实现类	
	//@Async代表异步处理,也可不用,看具体场景
 	@Async
    public void commit(String orderNo,String orderType)  {
    	String Msg="";//定义返回参数
    	//orderType 为实现类的别名 OrderAodiCar OrderBaomaCar OrderBenchiCar
    	//1.所有类型都直接调用即可
    	Msg= OrderFactory.get(orderType).dealOrdering(orderNo, orderType);
		//2.其他逻辑处理
		if("OrderBenchiCar".equals(orderType)){
			//其他逻辑
			if("Success".equals(Msg)){
			....
			}
		}else if("OrderBenchiCar".equals(orderType)){
		
		}else if("OrderBenchiCar".equals(orderType)){
			
		}
    	
	}
}
  • 15
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
可以使用 Spring 的 ApplicationContext 对象来获取所有的 Service,并将它们放到一个 Map 中,然后通过 key 值调用对应的 Service。 下面是一个简单的示例代码: ```java @Service public class ServiceManager { @Autowired private ApplicationContext context; private Map<String, Object> serviceMap = new HashMap<>(); @PostConstruct public void init() { Map<String, Object> serviceBeans = context.getBeansWithAnnotation(Service.class); for (Object service : serviceBeans.values()) { Class<?>[] interfaces = service.getClass().getInterfaces(); if (interfaces.length > 0) { Class<?> serviceInterface = interfaces[0]; String serviceName = serviceInterface.getSimpleName(); serviceMap.put(serviceName, service); } } } public Object getService(String serviceName) { return serviceMap.get(serviceName); } } ``` 在上面的代码中,我们创建了一个 ServiceManager ,使用 @Autowired 注解注入了 ApplicationContext 对象,然后在初始化方法 init 中,使用 ApplicationContext 对象获取所有被注解为 @Service 的 Service,并将它们放到一个 Map 中,key 值为对应 Service 实现接口名。 最后,我们提供了一个公共方法 getService,用于根据 key 值获取对应的 Service 对象。 使用该方法,我们可以方便地获取所有的 Service,并根据 key 值调用对应的 Service。例如,我们可以在 Controller 中使用以下代码来获取 UserService 并进行相关操作: ```java @RestController public class UserController { @Autowired private ServiceManager serviceManager; @GetMapping("/user/{id}") public User getUser(@PathVariable Long id) { UserService userService = (UserService) serviceManager.getService("UserService"); return userService.getUserById(id); } } ``` 这样,我们就可以通过 ServiceManager 来管理所有的 Service,并在需要时根据 key 值获取对应的 Service。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值