Spring 一个接口多个实现,如何根据外部条件来实时替换具体实现类

7 篇文章 0 订阅

代码:

<T> Map<String, T> getBeansOfType(Class<T> var1) throws BeansException;

作用:

1. 传入一个接口的Class 类型,获取这个class 的所有具体实现,不包括抽象类

2. 还可以将 applicationContext 单独设置一个值,写成一个工具类,结合ApplicationContext 类的其他方法,比如:

getBean(String var1)

需求:

定义了一个接口,来对外提供服务,这个接口下的方法不能随便改变,而接口有一系列实现,且实现还在不断添加,如何在传入外部不同的条件下,实现实时更换接口的实现类

之前的解决办法:

是在controller 中分别引入具体的实现,通过一个外部条件在controller 判断使用那个实现,

弊端:

1.每次增加新的接口,都需要在controller 中在@Autowired 一个依赖,都必须修改Controller 类的代码,

2.之前最多引入的实现类有9个,但是实现还在不断增加,如果继续引入更多类,spring 创建这个controller的时间大大增加,因为引入加载太多类,

修改的办法:

通过spring 的ApplicationContext(应用上下文)的getBeansOfType 方法传入接口类型,一次性获取所有实现类

问题:

1怎么获得实时的应用上下文对象 applicationContext

任何类 实现 ApplicationContextAware 接口,实现setApplicationContext 方法,就会在启动时,向实现类的实现方法注入applicationContext对象

例子:

package com.util;

import com.service.TestService;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.annotation.Configurable;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;

import java.util.HashMap;
import java.util.Map;

@Component
public class TestServiceFactory implements ApplicationContextAware {

    private static Map<TypeEnum, TestService> testServiceMap;

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        Map<String,TestService> map = applicationContext.getBeansOfType(TestService.class);
        testServiceMap = new HashMap<>();
        map.forEach((key,value) -> testServiceMap.put(value.getCode(),value));
    }

    public TestService getTestService(TypeEnum typeEnum) {
        return testServiceMap.get(typeEnum);
    }
}

2. 怎么根据外部条件实现获得对应的实现类?

可以在接口中加一个getCode方法,实现类实现这个方法,然后返回一个定义的枚举类型,然后将getBeansOfType获得map进行转换

例子:

package com.util;

public enum  TypeEnum {
    impl1,
    impl2
}

接口

package com.service;

import com.util.TypeEnum;
import org.springframework.stereotype.Service;

@Service
public interface TestService {

    public TypeEnum getCode();

    public String test();

}

实现类

package com.service.impl;

import com.service.TestService;
import com.util.TypeEnum;
import org.springframework.stereotype.Service;

@Service
public class TestServiceImpl1 implements TestService {
    @Override
    public TypeEnum getCode() {
        return TypeEnum.impl1;
    }

    @Override
    public String test() {
        return this.toString();
    }
}
package com.service.impl;

import com.service.TestService;
import com.util.TypeEnum;
import org.springframework.context.annotation.Primary;
import org.springframework.stereotype.Service;

@Service
public class TestServiceImpl2  implements TestService {
    @Override
    public TypeEnum getCode() {
        return TypeEnum.impl2;
    }

    @Override
    public String test() {
        return this.toString();
    }
}

controller类

package com.controller;

import com.util.TestServiceFactory;
import com.util.TypeEnum;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import com.service.TestService;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

@Controller
@RequestMapping("test")
public class TestController {

    @Autowired
    TestServiceFactory testServiceFactory;

    private TestService testService;

    @ResponseBody
    @RequestMapping("test")
        public String test(HttpServletRequest request, HttpServletResponse response){
        String type = request.getParameter("type");
        testService = getTestService(type);
        return testService.test();
    }

    public TestService getTestService(String type) {
        TypeEnum typeEnum = null;
        if(type.equals("1")) typeEnum = TypeEnum.impl1;
        if(type.equals("2")) typeEnum = TypeEnum.impl2;
        return testServiceFactory.getTestService(typeEnum);
    }

}

 

  • 4
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
高度耦合的代码会导致以下问题: 1. 难以维护:当一个对象发生变化时,其他依赖于它的对象也需要相应地修改。如果代码存在大量高度耦合的关系,当一个对象发生改变时,需要在多个地方进行修改,增加了维护的难度和风险。 2. 难以扩展:如果一个对象被多个其他对象依赖,那么对该对象进行扩展或修改可能会影响到其他依赖它的对象。这使得系统的扩展变得困难,新功能的添加可能会导致意想不到的副作用。 下面以一个Spring Boot代码的例子来说明高度耦合的问题。 假设我们有一个控制器 `UserController` 和一个服务 `UserService`: ```java @RestController public class UserController { private UserService userService; public UserController() { userService = new UserService(); } @GetMapping("/users/{id}") public String getUser(@PathVariable String id) { return userService.getUserById(id); } } public class UserService { public String getUserById(String id) { // 获取用户逻辑 return "User: " + id; } } ``` 在上述代码,`UserController` 直接创建了 `UserService` 的实例,并在 `getUser` 方法调用了 `userService.getUserById` 方法。这种紧密耦合的方式会导致以下问题: 1. 可维护性差:如果我们决定更改 `UserService` 的实现方式或者添加其他的依赖,那么我们需要修改 `UserController` 的代码。这种紧密耦合会导致修改的范围扩大,增加了代码的维护成本。 2. 难以进行单元测试:由于 `UserController` 直接依赖于 `UserService` 的具体实现,我们无法在单元测试轻松地模拟或替换 `UserService` 的行为。这使得单元测试变得困难,可能需要依赖于底层的数据库或其他外部资源。 为了解决这个问题,我们可以使用控制反转(IoC)和依赖注入(DI)来解耦代码。通过使用Spring Boot容器和相关注解,我们可以将对象的创建和管理交给容器处理,从而实现低耦合的代码。详细的示例请查看之前的回答。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值