Business
Jobs
  • About Us
  • Solutions
    • Job Postings
      Post your job and receive qualified candidates in 48h.
    • Candidate Assessments
      500+ technical and psychological tests, plus anti-fraud.
    • Headhunting
      Tailor-made executive search from start to finish.
    • Payroll + EOR
      Payroll dispersal and EOR across 15+ LATAM countries.
  • Pricing
  • Jobs

0

98
Views
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?

over 4 years ago · Santiago Trujillo
1 answers
Answer question

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);
over 4 years ago · Santiago Trujillo Report
Answer question
Find remote jobs

Discover the new way to find a job!

Top jobs
Top job categories
Business
Post vacancy Pricing Sales
Legal
Terms and conditions Privacy policy
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Show me some job opportunities
There's an error!