Spring IoC: ¿construyendo beans dependientes del contexto?

Considere el siguiente código:

@Service
class UserSpecificService {
    @Autowired ServiceA serviceA;
    @Autowired ServiceB serviceB;
    @Autowired User user;

    public void doUserSpecificThings() {
        // consume serviceA, serviceB and user here
    }
}

@Service class ServiceA {}
@Service class ServiceB {}

@Service
class Facade {
    public void doThingsForUser(Long userId) {
        User user = userService.getById(userId);
        UserSpecificService userSpecificService = ...; // !!!
        userSpecificService.doUserSpecificThings();
    } 
}

La pregunta es sobre la línea marcada con // !!!. ¿Hay alguna forma en que pueda construir UserSpecificService sin implementando mi propia fábrica que es consciente de ServiceA y ServiceB, y solo requiere una instancia de User para instanciar un UserSpecificService?

Si importa, voy a usar el Facade con Spring MVC, aunque me gustaría no depender de esto.

¡Gracias!

preguntado el 03 de mayo de 12 a las 20:05

2 Respuestas

He aquí una sugerencia:

  • hacer que todos los servicios que son elegibles para ser userSpecificService (Supongo que estos son ServiceA y serviceB) tienen una interfaz común
  • deje que esa interfaz tenga dos métodos: doUserSpecificThing() y isEligibleFor(user)
  • utilizado @Autowired List<YourInterface> list
  • en tu doThingsForUser() iterar la lista de todas las instancias de la interfaz dada, y para cada una de ellas verificar si es elegible para el usuario dado. Si es así, invoque el método.

contestado el 03 de mayo de 12 a las 21:05

Si está preguntando si puede crear un UserSpecificService dinámicamente sin tener que configurar manualmente los servicios, intente esto:

@Configurable
class UserSpecificService {
    @Autowired private ServiceA serviceA;
    @Autowired private ServiceB serviceB;
    private User user;

    public UserSpecificService(User user){
        this.user = user;
    }

    public void doUserSpecificThings() {
        // consume serviceA, serviceB and user here
    }
}

@Service class ServiceA {}
@Service class ServiceB {}

@Service
class Facade {
    public void doThingsForUser(Long userId) {
        User user = userService.getById(userId);
        UserSpecificService userSpecificService = new UserSpecificService(user);
        userSpecificService.doUserSpecificThings();
    } 
}

Solo tenga en cuenta que deberá configurar su contexto de primavera para buscar @Configurable. Para hacer esto todo lo que tienes que hacer es agregar <context:spring-configured/> al archivo de contexto de su aplicación. Otro enfoque sería:

@Service
class UserSpecificService {
    @Autowired private ServiceA serviceA;
    @Autowired private ServiceB serviceB;

    public void doUserSpecificThings(User user) {
        // consume serviceA, serviceB and user here
    }
}

@Service class ServiceA {}
@Service class ServiceB {}

@Service
class Facade {
    public void doThingsForUser(Long userId) {
        User user = userService.getById(userId);
        userSpecificService.doUserSpecificThings(user);
    } 
}

Ese enfoque puede ser mejor dependiendo de su aplicación específica.

contestado el 03 de mayo de 12 a las 21:05

No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas or haz tu propia pregunta.