版权声明:本文为博主原创文章,未经博主允许不得转载 https://blog.csdn.net/kzcming/article/details/84335432
代码:
<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);
}
}