Spring Context. es Necesario Cargar todas las instancias al inicio?

Hola amigos, necesito su ayuda, apenas comence a hacer uso de la Inyeccion Basica de Dependencias con Spring, pero ahora quiero inyectarlas desde un Context (Xml)

Veran tengo el siguiente ejemplo:
Clase A:

class A{
     Private B ObjB;
         SetDependenciaB(B ObjB){
             this.B=ObjB;
         }
         
         OtroMedoto(){
                B.Correr();
         }

}

Main:

FileSystemXmlApplicationContext FSXObj = new FileSystemXmlApplicationContext("Archivo.xml");

A ObjA = (A)FSXObj.getBean("ClaseA");
B ObjB = (B)FSXObj.getBean("ClaseB");

A.setDependenciaB(ObjB);

siendo mi xml el siguiente:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN 2.0//EN"
    "http://www.springframework.org/dtd/spring-beans-2.0.dtd">

<beans>
        <bean id="ClaseA" class="A"></bean>
        <bean id="ClaseB" class="B"></bean>
</beans>

Esto creo que esta bien. pero si yo tuviera una aplicacion con Muchisisisismas Clases entonces
¿en la Clase Main tendria que inyectar todas las dependencias de una vez al iniciar la aplicacion ?
¿no puedo inyectar las dependencias como valla utilizando las Clases sin crear un acoplamiento con la clase Main?

No se si realmente estoy implementando de manera correcta la inyeccion de dependencias, pero cualquier comentario o critica sera bien resibida
Muchas Gracias por su atencion.

Opciones de visualización de comentarios

Seleccione la forma que prefiera para mostrar los comentarios y haga clic en «Guardar las opciones» para activar los cambios.
Imagen de ezamudio

usa Spring

Ya tienes un ApplicationContext. Ahora USALO! Lo mejor de Spring es que puedes conectar tus componentes, para que no tengas que hacer nada de eso por código:

<bean id="claseA" class="A">
  <property name="dependenciaB" ref=claseB" />
</bean>
<bean id="
claseB" class="B" />

Así se definen las referencias entre componentes. Lee bien la documentación de Spring, eso es de lo más básico que hacen los BeanFactories y ApplicationContexts.

Tu clase principal debería ser un bean normalito, yo recomiendo que implemente Runnable, y lo defines como bean en el application context igual que cualquier otro. Y de ese modo, lo único que tienes que hacer para iniciar tu aplicación es esto (y es código bastante genérico):

public static void main(String[] args) {
  ApplicationContext ctxt = blabla; //como quieras inicializarlo, yo uso ClassPathXmlApplicationContext, tu usas FileSystemXmlApplicationContext
  Runnable main = (Runnable)ctxt.getBean("main");
  main.run();
}

Y en tu application context defines un bean llamado main y listo. Si para alguna prueba quieres cambiar el componente principal, lo único que tienes que hacer es renombrar los beans en tu contexto para que haya otro main en vez del de siempre, y listo.

Y cuando llegues a tener un application context con muchísimos componentes, puedes aprovechar otras facilidades de Spring, como la configuración basada en anotaciones. Por ejemplo si tienes un paquete a.b.c con 30 componentes y otras 20 clases que no son componentes que quieras meter como beans de Spring, puedes anotar esos 30 componentes con @Componente o @Service, y usar las facilidades del application context para detectar los componentes anotados en ese paquete, de modo que ya no tienes ni siquiera que definirlos. Y para cada componente que quieras conectar con otro, puedes usar @Resource (anotación estándar de Java), @Autowired o @Required (anotaciones de Spring).

Por ejemplo otra opción para tu ejemplo, es que no modifiques el contexto, sino el bean A:

public class A {
  @Resource
  private B claseB;

  void otroMetodo() {
    claseB.correr;
  }
}

Y el application context lo defines así (usando esquemas en vez del DTD):

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

<context:annotation-config" title="http://www.springframework.org/schema/context/spring-context-3.0.xsd">

<context:annotation-config">http://www.springframework.org/schema/context/spring-context-3.0.xsd">

...</a> />

<beans>
  <bean id="claseA" class="A" />
  <bean id="claseB" class="B" />
</beans>

El <context:annotation-config/> causa que el application context procese los beans que tiene definidos, buscando anotaciones como @Autowired, @Resource, @Required, etc. Para los casos de @Resource sin modificadores y @Autowired, lo que hace es buscar que haya un solo componente definido de la clase de la propiedad anotada (si te fijas, ya ni puse un setter para esa propiedad, porque no es necesario, Spring lo puede fijar de todas formas, dejémoslo por ahora en que lo hace automágicamente). Si llegaras a tener varios beans de la misma clase, o si por ejemplo tienes varios beans de distintas clases pero que implementan una interfaz común y tienes una propiedad del tipo de la interfaz, entonces puedes usar @Resource(name="nombre del bean que necesitas") para especificar cuál debe conectar Spring. @Required se debe usar en setters y es muy útil cuando solamente quieres forzar a que se pongan valores en las propiedades que los requieren (o Spring arroja excepción). Por ejemplo si tu bean B tuviera una propiedad nombre de tipo String:

public class B {
  private String nombre;
  @Required
  public void setNombre(String value) {
    nombre = value;
  }
}

Si no cambias la definición de tus beans en el contexto en XML, Spring arroja una excepción porque el bean claseB necesita tener un valor definido para la propiedad nombre. Se corregiría así:

<bean id="claseB" class="B">
  <property name="nombre" value="una cadena" />
</bean>

Todo esto viene super bien documentado, Spring es de los frameworks mejor documentados, es una de las razones por las que se ha vuelto tan popular.

Imagen de cyberserver

Gracias.

Muchas Gracias. :) me sirvio mucho tu respuesta.
De hecho ya sabia que podias crear property en el Xml,
pero en los ejemplos que vi solo inyectaban los valos a atributos de un tipo X
no a variables de instancia. y con esta linea tu lo haces

<property name="dependenciaB" ref=claseB" />

Tambien nunca havia escuchado de las anotaciones. ni del metodo run(); :)

Muchas Gracias

Imagen de ezamudio

run()

El método run() lo define la interfaz Runnable. Si no habías visto eso nunca, te recomiendo que primero estudies más acerca de Java y luego te metas a Spring.

Imagen de cyberserver

Chale ya me atore.

Caramba ya me volvi a atorar. :S esto es lo que llevo (De hecho no es nada pero no puedo Cargar el xml con ApplicationContext sin resivir este mega error)

8/02/2011 09:45:49 PM org.springframework.context.support.AbstractApplicationContext prepareRefresh
INFO: Refreshing org.springframework.context.support.FileSystemXmlApplicationContext@c1b531: display name [org.springframework.context.support.FileSystemXmlApplicationContext@c1b531]; startup date [Tue Feb 08 21:45:49 CST 2011]; root of context hierarchy
8/02/2011 09:45:49 PM org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions
INFO: Loading XML bean definitions from file [C:\Users\Abel\Documents\NetBeansProjects\EjemploDeSpringYContext\src\Archivo.xml]
8/02/2011 09:45:49 PM org.springframework.context.support.AbstractApplicationContext obtainFreshBeanFactory
INFO: Bean factory for application context [org.springframework.context.support.FileSystemXmlApplicationContext@c1b531]: org.springframework.beans.factory.support.DefaultListableBeanFactory@161f10f
8/02/2011 09:45:49 PM org.springframework.beans.factory.support.DefaultListableBeanFactory preInstantiateSingletons
INFO: Pre-instantiating singletons in org.springframework.beans.factory.support.DefaultListableBeanFactory@161f10f: defining beans [Clase1,Clase2]; root of factory hierarchy
8/02/2011 09:45:49 PM org.springframework.beans.factory.support.DefaultSingletonBeanRegistry destroySingletons
INFO: Destroying singletons in org.springframework.beans.factory.support.DefaultListableBeanFactory@161f10f: defining beans [Clase1,Clase2]; root of factory hierarchy
Exception in thread "main" org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'Clase1' defined in file [C:\Users\Abel\Documents\NetBeansProjects\EjemploDeSpringYContext\src\Archivo.xml]: Error setting property values; nested exception is org.springframework.beans.NotWritablePropertyException: Invalid property 'VariableIndependienteB' of bean class [Independiente]: Bean property 'VariableIndependienteB' is not writable or has an invalid setter method. Did you mean 'variableIndependienteB'?
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyPropertyValues(AbstractAutowireCapableBeanFactory.java:1279)
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1010)
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:472)
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory$1.run(AbstractAutowireCapableBeanFactory.java:409)
        at java.security.AccessController.doPrivileged(Native Method)
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:380)
        at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:264)
        at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:222)
        at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:261)
        at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:185)
        at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:164)
        at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:429)
        at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:728)
        at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:380)
        at org.springframework.context.support.FileSystemXmlApplicationContext.<init>(FileSystemXmlApplicationContext.java:140)
        at org.springframework.context.support.FileSystemXmlApplicationContext.<init>(FileSystemXmlApplicationContext.java:84)
        at Dependiente.main(Dependiente.java:8)
Caused by: org.springframework.beans.NotWritablePropertyException: Invalid property 'VariableIndependienteB' of bean class [Independiente]: Bean property 'VariableIndependienteB' is not writable or has an invalid setter method. Did you mean 'variableIndependienteB'?
        at org.springframework.beans.BeanWrapperImpl.setPropertyValue(BeanWrapperImpl.java:801)
        at org.springframework.beans.BeanWrapperImpl.setPropertyValue(BeanWrapperImpl.java:651)
        at org.springframework.beans.AbstractPropertyAccessor.setPropertyValues(AbstractPropertyAccessor.java:78)
        at org.springframework.beans.AbstractPropertyAccessor.setPropertyValues(AbstractPropertyAccessor.java:59)
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyPropertyValues(AbstractAutowireCapableBeanFactory.java:1276)
        ... 16 more
Java Result: 1

Siendo mis Clases las siguientes :
Clase Dependiente (Si se dan cuenta, no utilizo ningun Bean, pero aun asi me manda el error)

import javax.swing.*;

import org.springframework.context.support.FileSystemXmlApplicationContext;

public class Dependiente {

    public static void main (String[] args) {
        FileSystemXmlApplicationContext FSXObj = new FileSystemXmlApplicationContext("C:\\Users\\Abel\\Documents\\NetBeansProjects\\EjemploDeSpringYContext\\src\\Archivo.xml");
        //InterfaceRelacion Obj = (InterfaceRelacion)FSXObj.getBean("Clase1");
        //JOptionPane.showMessageDialog(null,"Uno" + Obj.GetNombreUsuario());
    }
   
   
}

Clase Independiente

public class Independiente implements InterfaceRelacion {
    public IndependienteB VariableIndependienteB;
       
    public void setVariableIndependienteB(IndependienteB VariableIndependienteB){
        this.VariableIndependienteB=VariableIndependienteB;
    }
       
    public String GetNombreUsuario() {
        return VariableIndependienteB.GetNombreUsuario();
    }
   
}

Clase IndependienteB

public class IndependienteB implements InterfaceRelacion {
    public String GetNombreUsuario() {
        return "Abel";
    }
   
}

Interface InterfaceRelacion

public interface InterfaceRelacion {
    public String GetNombreUsuario();
}
   

Archivo.xml

<?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
       <a href="
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">

" title="http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">

">http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">

</a>    <bean id="Clase1" class="Independiente">
                <property name="VariableIndependienteB" ref="Clase2"/>
        </bean>
        <bean id="Clase2" class="IndependienteB"></bean>
       
</beans>

El error traducito es :

Error al crear el frijol con el nombre de "Clase1" se define en el archivo
[C: \ Users \ Abel \ Documents \ NetBeansProjects \ EjemploDeSpringYContext
\ src \ Archivo.xml]:
 Error al establecer el valor de la propiedad;
 excepción anidada es org.springframework.beans.NotWritablePropertyException:
 la propiedad no válido 'VariableIndependienteB' de frijol clase [Independiente]:
 Construcción Bean 'VariableIndependienteB "No se puede escribir o tiene un
 método setter válido.
  ¿Te refieres a '
variableIndependienteB?

Pero no entiendo. por que me dice eso si tengo en la Clase Independiente una variable de instancia con todo y su metodo setter ?

public IndependienteB VariableIndependienteB;
       
    public void setVariableIndependienteB(IndependienteB VariableIndependienteB){
        this.VariableIndependienteB=VariableIndependienteB;
    }

Cualquier ayuda de verdad muchas gracias!

Imagen de cyberserver

Que Raro?

jjajajaj que raro....

lo raro de esto es si cambio la forma de inyeccion de Setter a inyectarlo por el Constructor.........

Archivo.xml

<?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
       <a href="
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">

" title="http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">

">http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">

</a>    <bean id="Clase1" class="Independiente">
        <constructor-arg ref="Clase2"/>
        </bean>
        <bean id="Clase2" class="IndependienteB"></bean>
       
</beans>

Clase Independiente

public class Independiente implements InterfaceRelacion {
    public IndependienteB VariableIndependienteB;

    public Independiente(IndependienteB VariableIndependienteB){
        this.VariableIndependienteB=VariableIndependienteB;
    }
       
    public String GetNombreUsuario() {
        return VariableIndependienteB.GetNombreUsuario();
    }
   
}

Si funciona :) ? ¿?¿?

Que Raro.......
Pero si alguien sabe por que no funciona con Setter se los agradeceria :)

Imagen de ezamudio

RTFS

Si tuviste el tiempo de copiar y pegar el megaerror, deberías tener tiempo de leerlo.

Error setting property values; nested exception is org.springframework.beans.NotWritablePropertyException: Invalid property 'VariableIndependienteB' of bean class [Independiente]: Bean property 'VariableIndependienteB' is not writable or has an invalid setter method. Did you mean 'variableIndependienteB'?

Para usar Spring, sí hay que respetar la convención de que las propiedades comienzan con minúscula. Tienes el método setVariableblabla() así que tu propiedad debe ser variableblabla. Solamente cuando usas anotaciones como @Resource o @Autowired se pueden conectar los componentes sin necesidad de un setter. Si vas a definir el setter, entonces lo que importa es el nombre público de la propiedad, no el nombre de la variable privada. Ejemplo:

private int Entero;
public void setEntero(int x) { Entero = x; }
public int getEntero() { return Entero; }

El nombre de la propiedad es entero, no Entero, aunque este último sea el nombre de la variable privada.