2010-10-18 8 views
16

En mi aplicación que estoy utilizando ContextLoaderListener para cargar archivos de contexto de muchos frascos usando:referencias de frijol de primavera opcionales

<context-param> 
    <param-name>contextConfigLocation</param-name> 
    <param-value>classpath*:META-INF/contextBeans.xml</param-value> 
</context-param> 

Esto significa que puedo hacer referencia a los granos de otros frascos sin hacer importación.

En la aplicación hay varias opciones de implementación y en algunas implementaciones se pueden excluir los archivos jar. Para apoyarlo, me gustaría que algunas referencias de frijoles sean opcionales. Por ejemplo:

<bean id="mainAppBean" class="com.someapp.MyApplication"> 
    <constructor-arg index="0" ref="localBean"/> 
    <constructor-arg index="1" ref="optionalBeanReference1"/> 
    <constructor-arg index="2" ref="optionalBeanReference2"/> 
</bean> 

En el ejemplo anterior me gustaría tener optionalBeanReference1 igual nulo si no se ha encontrado la referencia (opcional marcarlo de alguna manera)

se puede hacer esto en la primavera? ¿o qué método recomienda para manejar referencias dinámicas?

Respuesta

9

qué método me recomiendan para el manejo de referencias dinámicas?

Creo que @ cristian's @Autowired answer es una buena respuesta. Eso llamará a los métodos setter si los beans de ese tipo están disponibles. Sin embargo, si tiene varios beans del mismo tipo, creo que Spring arroja una excepción. Si no puede utilizar @Autowired para esta o alguna otra razón, veo un par de soluciones:

  1. Se podría hacer que su clase ApplicationContextAware y la búsqueda de los granos en el contexto mismo:

    public void setApplicationContext(ApplicationContext applicationContext) { 
        if (applicationContext.containsBean("optionalBeanReference1")) { 
         setOptionalBeanReference1(
          (OptionalBeanReference1)applicationContext.bean(
           "optionalBeanReference1"); 
        } 
        ... 
    } 
    
  2. Podrías invertir la dependencia. Cada una de las clases opcionales podría establecer ellos mismos en el MainAppBean. Utilizo esto en ciertas situaciones cuando una dependencia directa causaría bucles u otros problemas.

    <bean id="optionalBeanReference1" class="com.someapp.SomeClass"> 
        <constructor-arg index="0" ref="mainAppBean"/> 
    </bean> 
    

    Luego, en el SomeClass:

    public SomeClass(com.someapp.MyApplication mainAppBean) { 
        mainAppBean.setOptionalBeanReference1(this); 
    } 
    
  3. Se podía quedarse con su dependencia directa y luego o importar un archivo con los granos definidos o importar otro archivo en el que se definen los granos que tienen valores nulos mediante el uso de un frijol de fábrica. Vea esto factory code.

Buena suerte.

+0

Usé algo similar a la primera opción, donde después de cargar el frijol, verifico si existen otros frijoles también. Esta parece ser la mejor manera sin anotaciones – mbdev

23

Mi mejor conjetura es utilizar autowire -ing con falsa requerida. No sabe cómo se puede expresar esto en XML, pero utilizando la configuración de anotación este sería el resultado:

@Autowired(required=false) 
+1

Oh, sí, y la inyección del colocador es probablemente mejor para este tipo de situaciones. –

+0

Esto suena bien, pero por el momento no puedo usar las anotaciones Spring en el proyecto. – mbdev

5

No hay un mecanismo incorporado para esto.Sin embargo, se podría escribir una muy trivial FactoryBean aplicación para hacer esto para usted, algo como esto:

public class OptionalFactoryBean extends AbstractFactoryBean<Object> implements BeanNameAware { 

    private String beanName; 

    @Override 
    public void setBeanName(String beanName) { 
     this.beanName = BeanFactoryUtils.originalBeanName(beanName); 

    } 

    @Override 
    protected Object createInstance() throws Exception { 
     if (getBeanFactory().containsBean(beanName)) { 
      return getBeanFactory().getBean(beanName); 
     } else { 
      return null; 
     } 
    } 

    @Override 
    public Class<?> getObjectType() { 
     return null; 
    } 
} 

A continuación, puede utilizar de esta manera:

<bean id="mainAppBean" class="com.someapp.MyApplication"> 
    <constructor-arg index="0" ref="localBean"/>  
    <constructor-arg index="1"> 
     <bean name="optionalBeanReference1" class="com.someapp.OptionalBeanFactory"/> 
    </constructor-arg> 
    <constructor-arg index="2"> 
     <bean name="optionalBeanReference2" class="com.someapp.OptionalBeanFactory"/> 
    </constructor-arg> 
</bean> 
4

Teniendo en cuenta que las referencias de frijol en el código XML config se definen a través de lenguaje de expresión (eL) se puede hacer lo siguiente:

<property name="cache" value="#{getObject('optionalCache')}" /> 

que hace uso de el método BeanExpressionContext.getObject(). Vea here para más detalles.

7

Con las versiones recientes de Spring (probadas con el muelle 4.1) y Java Configuration y Java 8, puede usar Optional en los parámetros, y solo están auto conectadas si están disponibles.

@Autowired 
public MyApplication(Optional<YourOptionalObject> maybeObject) { 
    // do something with the optional autowired 
} 
+1

Vea el ticket de mejora de Spring aquí: https://jira.spring.io/browse/SPR-11833 y un ejemplo real aquí: https://stackoverflow.com/questions/19485878/can -inject-be-made-optional-in-jsr-330-like-autowirerequired-false –

+0

¡esta es la mejor solución! ¡Funciona! ¡Gracias! – Torsten

Cuestiones relacionadas