2012-05-15 6 views
7

Digamos que tengo una clase con un constructor que toma uno o más argumentos. Digamos también que se espera que los argumentos sean un tipo de entrada del usuario. Es decir, el argumento no puede conocerse en tiempo de compilación o tiempo de configuración, solo en tiempo de ejecución. ¿Debo definir mi clase como un prototipo de bean de primavera o debería simplemente crearlo con "nuevo".Constructor que toma argumentos - ¿Definir como objeto ordinario o bean de primavera?

Si debería definirlo como un bean, ¿cómo puedo pasar los argumentos?

Respuesta

7

Esto es problemático en primavera. Si su clase no tiene dependencias en otros beans, simplemente créelo con new. Si tiene una clase que depende de otros beans Spring pero aún desea pasar algunos argumentos en tiempo de ejecución, actualmente Spring no la admite. Sin embargo, eche un vistazo a SPR-7431 y my article about passing custom argument to <lookup-methods/>. Si todo va bien, esta característica debería ser parte de Spring 3.2 y debería coincidir con sus requisitos. Básicamente, permite crear prototype-beans cocidos mientras se sigue pasando algún argumento de constructor.

+0

Información muy buena y agradable. Gracias –

+0

Actualización: Esta característica NO es parte de la primavera todavía. – javadeveloper

+0

¿esto es compatible con Spring 4 ahora? –

5

A menos que su clase también tenga dependencias de otros granos en su contexto, entonces no, no debe convertirla en un frijol; no tiene sentido. Simplemente use new.

La única razón de peso para convertirlo en un frijol es si hace depende de otros frijoles, en cuyo caso se justifica un frijol con un tamaño de prototipo. Sin embargo, si la clase requiere esos valores de tiempo de ejecución en su constructor, entonces no puede hacer eso, salvo cambiar la clase para inyectarlos a través de algún método en lugar de usar el constructor.

+0

Bueno .. el objeto que quiero crear es en realidad supone que devolver las habas de primavera en una de sus métodos por lo que _does_ dependen de ellos. Pero si no se puede hacer, entonces no se puede hacer ... –

+0

@LudwigMagnusson: Sugiero refactorizar la clase, entonces, para que los valores de tiempo de ejecución se pasen al método que luego devuelve el bean apropiado, en lugar de pasarlos al constructor. – skaffman

+0

Eso no es posible. La clase implementa una interfaz que define el método y no puede tomar argumentos porque se supone que las clases de implementación pueden crear los beans a partir de diferentes tipos de entrada. Pero tal vez si pienso más profundamente sobre esto, puedo refactorizarlo de tal manera ... –

0

la función de primavera de los argumentos de paso a constructor de utilizar el trabajo de búsqueda método no funciona en la primavera 3.2.11, pero está trabajando en la versión 4.1.1 de primavera

aquí el código que utiliza para comprobar que:

esta es la fábrica de interfaz ...

package prueba; 

public interface Factory { 

    Person createPersonWithDependencies(String name); 
} 

este es el frijol queremos ser gestionado por la primavera, la inyección de HelloWorldService ...

package prueba; 

public class Person { 

    private HelloWorldService helloWorldService; 

    public final void setHelloWorldService(HelloWorldService extraService) { 
     this.helloWorldService = extraService; 
    } 

    public Person() { 
     super(); 
    } 

    public Person(String name) { 
     super(); 
     this.name = name; 
    } 

    private String name; 

    public final String sayHello() { 
     return helloWorldService.getGreeting()+" I am "+name; 
    } 
} 

este es el famoso servicio de holamundo:

package prueba; 

public class HelloWorldService { 

    public String getGreeting(){ 
     return "hello world"; 
    } 
} 

este es un servicio de ejemplo que utiliza la fábrica

package prueba; 

public class Service { 

    private Factory factory; 

    public final void setFactory(Factory factory) { 
     this.factory = factory; 
    } 


    public void doSomeThing(){ 
     Person bean1= factory.createPersonWithDependencies("Jhon"); 

     System.out.println(bean1.sayHello()); 

     Person bean2= factory.createPersonWithDependencies("Maria"); 

     System.out.println(bean2.sayHello()); 
     System.out.println(bean1.sayHello()); 

    } 
} 

esta es la clase principal que pone a prueba toda

package prueba; 

import org.springframework.context.ApplicationContext; 
import org.springframework.context.support.ClassPathXmlApplicationContext; 

public class TestLookupMethodWithArguments { 
    /** 
    * Main method. 
    */ 
    public static void main(String[] args) { 

     ApplicationContext applicationContext = new ClassPathXmlApplicationContext("/applicationContext.xml"); 

     Service service=applicationContext.getBean("service",Service.class); 

     service.doSomeThing(); 
    } 

} 

y finalmente el archivo de configuración de primavera:

<?xml version="1.0" encoding="UTF-8"?> 
<beans xmlns="http://www.springframework.org/schema/beans" 
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"> 

    <bean id="helloWorldService" class="prueba.HelloWorldService" /> 

    <bean id="Person" class="prueba.Person" scope="prototype"> 
     <property name="helloWorldService" ref="helloWorldService" /> 
    </bean> 

    <bean id="myFactory" class="prueba.Factory"> 
     <lookup-method name="createPersonWithDependencies" bean="Person" /> 
    </bean> 

    <bean id="service" class="prueba.Service"> 
     <property name="factory" ref="myFactory" /> 
    </bean> 
</beans> 

la salida usando la primavera 4.1.1

hello world I am Jhon 
hello world I am Maria 
hello world I am Jhon 
Cuestiones relacionadas