[英]How to inject bean via generic variable in spring
I have problem with injecting bean with generic types. 我在用泛型类型注入bean时遇到问题。 Look at the example.
看例子。 I will inject to the service a repository which types takes from App class.
我将向服务注入类型从App类获取的存储库。 Now i have exception:
现在我有例外:
No qualifying bean of type 'asd.IRepository' available: expected single matching bean but found 2: a,b 没有可用的类型为'asd.IRepository'的合格Bean:预期为单个匹配的Bean,但找到了2:a,b
asd here is package, just for tests. asd是软件包,仅供测试。
What can I do in this situation? 在这种情况下我该怎么办? Is any way to makes it?
有什么办法吗?
public interface IRepository<T, V> {
void print();
}
@Component
public class A implements IRepository<String,String> {
@Override
public void print() {
System.out.println("A");
}
}
@Component
public class B implements IRepository<Double,String> {
@Override
public void print() {
System.out.println("A");
}
}
@Service
public class ServiceABC<V, T> {
@Autowired
private IRepository<V,T> repo;
public void print(){
repo.print();
}
}
@Controller
public class App {
@Autowired
private ServiceABC<String, String> serviceABC;
public static void main(String[] args) {
ApplicationContext ctx =
new AnnotationConfigApplicationContext("asd");
App app = ctx.getBean(App.class);
app.serviceABC.print();
}
You have to name your components and autowire by name: 您必须命名组件并按名称自动接线:
@Component("A")
public class A implements IRepository<String,String> {...}
@Component("B")
public class B implements IRepository<Double,String> {...}
[...]
@Autowired
@Qualifier("B")
private IRepository repo;
It looks like you don't know in advance which implementation of your IRepository
interface you will need. 看来您事先并不知道将需要
IRepository
接口的哪种实现。 And you will know that at runtime. 您将在运行时知道这一点。 In this case it is a typical case for Factory pattern where you will have a
IRepositoryFactory
that will have a method thhat retrieves specific implementation by type (for example IRepositoryFactory.getInstance(String type);
So in your ServiceABC
you may use the IRepository
to get specific bean at runtime. So Factory pattern may be an answer to your question. I also wrote an article that deals with this type of problem and proposes the idea of self-populating Factory (using Open source library that provides such utility). Here is the link to the article: Non-intrusive access to "Orphaned" Beans in Spring framework 在这种情况下,这是Factory模式的典型情况,在这种情况下,您将拥有一个
IRepositoryFactory
,该方法将具有按类型检索特定实现的方法(例如IRepositoryFactory.getInstance(String type);
因此,在ServiceABC
您可以使用IRepository
来获取运行时使用特定的bean。因此,Factory模式可能是您问题的答案。我还写了一篇文章来处理此类问题,并提出了自我填充Factory的想法(使用提供此类实用程序的开源库)。文章链接: 在Spring框架中非侵入式访问“孤立” Bean
Something like that? 这样的东西?
@Controller
public class RepositoryFactory {
@Autowired
private IRepository<String, String> a;
@Autowired
private IRepository<Double, String> b;
public IRepository getRepository(String className) {
if(className.equalsIgnoreCase("a")) {
return a;
} else if(className.equalsIgnoreCase("b")) {
return b;
}
return null;
}
}
@Service
public class ServiceABC {
@Autowired
private RepositoryFactory repositoryFactory;
public void print(String className){
repositoryFactory.getRepository(className).print();
}
}
@Controller
public class App {
@Autowired
private ServiceABC serviceABC;
public static void main(String[] args) {
ApplicationContext ctx =
new AnnotationConfigApplicationContext("asd");
App app = ctx.getBean(App.class);
app.serviceABC.print(A.class.getSimpleName());
}
}s
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.