Empresas
Empleos
  • Sobre nosotros
  • Soluciones
    • Publicación de vacantes
      Publica tu vacante y recibe candidatos calificados en 48h.
    • Evaluación de candidatos
      500+ pruebas técnicas y psicológicas, más anti-fraude.
    • Headhunting
      Búsqueda ejecutiva a la medida de principio a fin.
    • Nómina + EOR
      Dispersión de nómina y EOR en más de 15 países de LATAM.
  • Precios
  • Empleos

0

92
Vistas
Bean prototipo de Spring autoconectado parcialmente con argumentos de constructor determinados por el tiempo de ejecución

El javadoc a ConstructorResolver.autowireConstructor(...) dice

También se aplica si se especifican valores de argumento de constructor explícitos, haciendo coincidir todos los argumentos restantes con beans de la fábrica de beans.

pero no puedo hacer que funcione. Obtengo una BeanCreationException :

No se pudo resolver el constructor coincidente (sugerencia: especifique argumentos de índice/tipo/nombre para parámetros simples para evitar ambigüedades de tipo)

En este ejemplo, tengo un bean con un constructor que toma Spring beans así como un String y un int que solo se conocerá en tiempo de ejecución.

 @Component @Scope(BeanDefinition.SCOPE_PROTOTYPE) public class BeanWithRuntimeDependencies { public final DependencyA dependencyA; public final DependencyB dependencyB; public final String myString; public final int myInt; public BeanWithRuntimeDependencies( DependencyA dependencyA, DependencyB dependencyB, String myString, int myInt) { this.dependencyA = dependencyA; this.dependencyB = dependencyB; this.myString = myString; this.myInt = myInt; } } @Component public class DependencyA { /* ... */ } @Component public class DependencyB { /* ... */ }

y mi prueba:

 @RunWith(SpringRunner.class) @SpringBootTest public class PrototypeBeanConstructorsApplicationTests { @Autowired private ApplicationContext context; @Autowired private DependencyA dependencyA; @Autowired private DependencyB dependencyB; @Test public void getBeanFromContext() { BeanWithRuntimeDependencies bean = context.getBean(BeanWithRuntimeDependencies.class, "runtime string", 10); assertNotNull(bean); assertEquals(dependencyA, bean.dependencyA); assertEquals(dependencyB, bean.dependencyB); assertEquals("runtime string", bean.myString); assertEquals(10, bean.myInt); } }

El código fuente de ConstructorResolver.autowireConstructor(...) tiene un comentario:

 // Explicit arguments given -> arguments length must match exactly.

que parece contradecir su javadoc.

¿Es posible hacer esto? ¿Qué estoy haciendo mal?

about 4 years ago · Santiago Trujillo
1 Respuestas
Responde la pregunta

0

Parece que no es posible hacerlo de la manera que lo estás haciendo.

En realidad es una situación extraña. De acuerdo con el siguiente fragmento en ConstructorResolver.autowireConstructor(...) ( línea de código fuente #207 ), Spring no considerará a su constructor como candidato para la invocación:

 ... // Explicit arguments given -> arguments length must match exactly. if (paramTypes.length != explicitArgs.length) { continue; }

Y como notó correctamente, realmente contradice la declaración de javadoc:

... haciendo coincidir todos los argumentos restantes con frijoles de la fábrica de frijoles

Pero de todos modos, la implementación significa que, de forma predeterminada, Spring no puede resolver el constructor para crear instancias de dichos beans. Y tienes que crear el método de fábrica manualmente. Algo como:

 @Configuration public class Config{ @Bean @Scope(BeanDefinition.SCOPE_PROTOTYPE) public BeanWithRuntimeDependencies beanWithRuntimeDependencies(String myString, int myInt){ return new BeanWithRuntimeDependencies(dependencyA(), dependencyB(), myString, myInt); } @Bean public DependencyA dependencyA(){ return new dependencyA(); } @Bean public DependencyB dependencyB(){ return new dependencyB(); } }

Entonces puedes obtener bean del contexto como quieras hacer:

 BeanWithRuntimeDependencies bean = context.getBean(BeanWithRuntimeDependencies.class, "runtime string", 10);

Si no quiere tener un trato con la clase de configuración y el método de fábrica, simplemente puede pasar los beans necesarios al context.getBean() . Seguro que tienes que obtener estos frijoles del contexto:

 BeanWithRuntimeDependencies bean = context.getBean(BeanWithRuntimeDependencies.class, context.getBean(DependencyA.class), context.getBean(DependencyB.class), "runtime string", 10);
about 4 years ago · Santiago Trujillo Denunciar
Responde la pregunta
Encuentra empleos remotos

¡Descubre la nueva forma de encontrar empleo!

Top de empleos
Top categorías de empleo
Empresas
Publicar vacante Precios Comercial
Legal
Términos y condiciones Política de privacidad
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomiéndame algunas ofertas
Necesito ayuda