Considering a project of many entities, I have a service that requires to know the entity's type to execute a method. I created;
interface Service<T> {
String myMethod(T entity)
Class<T> getResponsibility()
And for example;
class FooService<Foo> {
String myMethod(Foo entity) { return 'foo'; }
Class<Foo> getResponsibility() { return Foo.class }
I wanted to create a factory to return the correct Bean (I'm using Spring Boot) to use, which I defined:
class ServiceFactory {
List<Service<?>> services;
@Autowired
public ServiceFactory(List<Service<?>> services) {
this.services = services;
}
Service getFor(Object entity) {
// Simplified for comprehension purpose
return this.services.stream().filter(service -> service.getResponsibility().equals(entity.getClass()).get();
}
This works, but I have a (sonar) warning saying that I should not make 'raw' use of Service
as return type for my factory method. What is the correct way of achieving this? Using a wildcard is another warning.
The goal is to have a factory that returns the correct Bean. Is the initial design wrong?
Instead of passing an object, pass the class itself and capture it as a method type parameter:
<T> Service<T> getFor(Class<T> type) {
You'd still get a warning because the injected list uses a wildcard:
@SuppressWarnings("unchecked")
<T> Service<T> getFor(Class<T> type) {
// Simplified for comprehension purpose
return (Service<T>) this.services.stream()
.filter(service -> service.getResponsibility().equals(type))
.findFirst()
.get();
}
You might be better off using Spring's support for generics by injecting directly the specific service:
@Autowired
Service<Foo> fooService;
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.