@Service
public class Animal {
public String name;
}
@Service
public class Dog extends Animal {
public String name;
}
@Service
public class Cat extends Animal {
public String name;
}
在spring boot项目中,我想使用spring框架提供的ApplicationContext获得一个特定的bean,这是我写来说明的一个简单示例:
@Component
public class AnimalLocator implements ApplicationContextAware {
private static ApplicationContext applicationContext;
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
if (PayServiceLocator.applicationContext == null) {
PayServiceLocator.applicationContext = applicationContext;
}
}
public <T extends Animal> T getService(String name) {
if("Cat".equals(name) {
applicationContext.getBean(name, Cat.class);
}
if("Dog".equals(name) {
applicationContext.getBean(name, Dog.class);
}
}
}
但是,编译器提示了异常:
马赛克部分应该是狗或猫。我认为它应该起作用,因为T已经扩展了Animal类,但是它没有,那么有人对此有任何想法吗?谢谢!
答案 0 :(得分:1)
由于您正在使用bean类访问bean实例,因此直接将类作为参数传递即可。
public <T extends Animal> T getPayService(String name, Class<T> payClass) {
return applicationContext.getBean(name, payClass);
}
答案 1 :(得分:1)
T
中的 getPayService
将扩展Animal
。这意味着用另一种类型调用它的代码将无法编译:
Fruit fruit = animalLocator.getPayService("Banana")
为说明您当前的问题,请查看以下内容:
Cat cat = animalLocator.getPayService("Dog");
T
在这种情况下为Cat
,但是您的代码将返回Dog
。
要避免编译器错误,可以添加类型强制转换:
return (T) applicationContext.getBean(...
但这仍然不安全,因为编译器仍无法保证实际返回类型将是运行时在调用方上下文中的T
,并且调用方将拥有一个类强制转换异常。
如果我们可以假设getBean
是安全的调用,那么您应该将方法更改为该实现:
public <T extends Animal> T getPayService(String name, Class<T> cls) {
return applicationContext.getBean(name, cls);
}
从调用者的角度来看,这并没有太大变化,而是取决于applicationContext.getBean(name, cls);
将返回T
类型的对象这一事实(或假设)。这意味着您的代码与getBean
一样具有类型安全性,但是编译器对此感到满意。
答案 2 :(得分:0)
您可以将所有Animal实例自动连接到Map中,而不用对if / else进行编码:
@Service("Animal")
public class Animal {
public String name;
}
@Service("Dog")
public class Dog extends Animal {
}
@Service("Cat")
public class Cat extends Animal {
}
在您的AnimalLocator中:
@Component
public class AnimalLocator {
@Autowired
private Map<String,Animal> animals;
public <T extends Animal> T getService(String name) {
return this.animals.get(name);
}
}