Empresas
Empregos
  • Sobre nós
  • Soluções
    • Publicação de vagas
      Publique sua vaga e receba candidatos qualificados em 48h.
    • Avaliações de candidatos
      Mais de 500 testes técnicos e psicológicos, mais anti-fraude.
    • Headhunting
      Busca executiva personalizada do início ao fim.
    • Folha de Pagamento + EOR
      Dispersão de folha e EOR em mais de 15 países da LATAM.
  • Preços
  • Empregos

0

212
Visualizações
Resorte de cableado automático basado en la disponibilidad del servicio

Tengo la necesidad de crear condicionalmente una de las tres implementaciones posibles de un servicio según el entorno detectado por una aplicación Spring en tiempo de ejecución. Si el Servicio A está disponible, quiero crear una clase de implementación concreta que use el Servicio A como una dependencia. Si el Servicio A no está disponible, quiero crear una implementación usando el Servicio B como una dependencia. Y así.

Las clases que dependen de la implementación conectarán automáticamente la interfaz y no les importará cuál fue el servicio subyacente que se seleccionó para el entorno particular.

Mi primer intento en esto fue implementar múltiples métodos @Bean que devuelven un bean o nulo, dependiendo de si el Servicio está disponible, y luego tener una clase @Configuration separada que @Autowire(required=false) los dos servicios posibles, creando condicionalmente la implementación dependiendo de cuál de los campos @Autowired no era nulo.

El problema aquí es que cuando required=false, a Spring no parece importarle si espera a que se construyan los candidatos; es decir, la clase que intenta elegir la implementación puede construirse antes de que se construya uno o ambos Beans required=false, lo que garantiza que uno o ambos siempre sean nulos, independientemente de si pueden inicializarse correctamente.

Parece que voy contra la corriente en este punto, así que estoy buscando consejos sobre la forma "correcta" de hacer este tipo de cosas, donde un conjunto completo de frijoles podría cambiarse según la disponibilidad. de algún servicio o entorno exterior.

Los perfiles no parecen la respuesta correcta, porque no lo sabré hasta después de que mis beans de servicio intenten inicializar qué implementación quiero elegir; Ciertamente no lo sabré en el momento en que cree el contexto.

@Order tampoco logra el objetivo. Tampoco @Conditional y testing sobre la existencia del bean (porque es posible que aún no se haya construido). El mismo problema con FactoryBean: no sirve de nada verificar la existencia de beans que podrían no haberse construido en el momento en que se le pide a FactoryBean que cree una instancia.

Lo que realmente necesito hacer es crear un Bean basado en la disponibilidad de otros beans, pero solo DESPUÉS de que esos beans hayan tenido al menos la oportunidad de intentar inicializarse.

about 4 years ago · Santiago Trujillo
2 Respostas
Responde à pergunta

0

Spring Profiles es tu amigo. Puede establecer el perfil actual mediante variables ambientales, argumentos de línea de comandos y otros métodos. Puede anotar un componente administrado por Spring para que se cree para un perfil determinado.

Perfiles de Spring de la documentación de Spring

about 4 years ago · Santiago Trujillo Relatório

0

Bueno, en este caso resultó ser un error tangencial que influyó en todo el comportamiento incorrecto.

Para dar algunos antecedentes, mi primer enfoque ingenuo (pero factible) se veía así:

 @Autowired(required=false) @Qualifier(RedisConfig.HISTORY) private RLocalCachedMap<String, History> redisHistoryMap; @Autowired(required=false) @Qualifier(HazelcastConfig.HISTORY) private IMap<String, History> hazelcastHistoryMap; // RequestHistory is an interface @Bean public RequestHistory requestHistory() { if (redisHistoryMap != null) { return new RedisClusteredHistory(redisHistoryMap); } else if (hazelcastHistoryMap != null) { return new HazelcastClusteredHistory(hazelcastHistoryMap); } else { return new LocalRequestHistory(); // dumb hashmap } }

En otras clases de @Configuration , si los beans que obtienen @Autowired aquí no están disponibles (debido a la falta de configuración, excepciones durante la inicialización, etc.), los métodos @Bean que los crean devuelven un valor nulo.

El comportamiento observado fue que este método @Bean se llamaba después de que se llamara al método RLocalCachedMap<> @Bean , pero antes de que Spring intentara crear el IMap<> llamando a su método @Bean . Había pensado incorrectamente que esto tenía algo que ver con required=false pero, de hecho, no tenía nada que ver con eso.

Lo que realmente sucedió fue que usé accidentalmente la misma constante para ambos nombres de @Bean (y, en consecuencia, @Qualifier ), por lo que presumiblemente Spring no pudo notar la diferencia cuando estaba calculando su gráfico de dependencia para esta clase de @Configuration ... porque los dos @Autowire d beans parecían ser lo mismo (porque tenían el mismo nombre).

(Hay una razón secundaria para usar @Qualifier en este caso, que no abordaré aquí, pero baste decir que es posible tener muchos mapas del mismo tipo).

Una vez que califiqué mejor los nombres, el código hizo exactamente lo que yo quería, aunque de una manera algo poco elegante/fea.

En algún momento regresaré y veré si se ve más elegante/menos feo y funciona igual de bien para usar @Conditional y @Primary en lugar de if/else foulness.

La lección aquí es que si nombra beans explícitamente, asegúrese absolutamente de que sus nombres sean únicos en su aplicación, incluso si planea intercambiar cosas como esta.

about 4 years ago · Santiago Trujillo Relatório
Responde à pergunta
Encontrar trabalhos remotos

Descubra a nova forma de encontrar um emprego!

melhores empregos
Principais categorias de trabalho
Empresas
Postar vaga Preços Comercial
Jurídico
Termos e Condições Política de privacidade
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomende algumas ofertas para mim
Preciso de ajuda