lunes, 21 de agosto de 2017

Spring AppContext Beans (Xml y Anotaciones)

Spring AppContext Beans (Xml y Anotaciones)


  Prototipo básico de Spring por AppContext beans Core por xml

https://github.com/jalbertomr/jalbertomr-springAppContextBeans/commit/167618cb7557c6970c3e86127ebe095e73ff1937


Se modifica la configuración de xml a Anotaciones.
   Se crea una clase con nombre AppConfig, que puede tener otro nombre ya que se referencia en la class main por
ApplicationContext appContext = new AnnotationConfigApplicationContext(AppConfig.class);

Se anota la Clase AppConfig con @Configuration

@Configuration
public class AppConfig {

    @Bean
    public ClaseParaBean cpb() {
        return new ClaseParaBean();
    }
   
    @Bean
    public Tierra tierra() {
        return new Tierra();
    }
   
    @Bean(name = "beanMarte")
    public Marte marte() {
        return new Marte();
    }
}


En la Clase Main

public static void main(String[] args) {
        System.out.println("Iniciado...");
       
       
        /* Metodo Beans */
        ApplicationContext appContext = 

        new AnnotationConfigApplicationContext(AppConfig.class);
        //ClaseParaBean cpb = (ClaseParaBean) appContext.getBean("claseBean");
        ClaseParaBean cpb = (ClaseParaBean)    appContext.getBean(ClaseParaBean.class);
        System.out.println("ClaseParaBean.getPropiedadDeClaseMensaje:" + cpb.getPropiedadDeClaseMensaje());
       
        Tierra tierra = (Tierra) appContext.getBean(Tierra.class);
        System.out.println("Tierra color:" + tierra.getColor() );
        System.out.println("Tierra diametro:" + tierra.getDiametro().toString());
       
        Marte marte = (Marte) appContext.getBean("beanMarte");
        System.out.println("Marte color:" + marte.getColor());
        System.out.println("Marte diametro:" + marte.getDiametro().toString());
       
        ((ConfigurableApplicationContext)appContext).close();
    }


  Se modifica la AppConfig por anotaciones para tener otra AppConfig2, y se modifica la clase main en la parte de AnnotationConfigApplicationContext(..)

AnnotationConfigApplicationContext appContext = new AnnotationConfigApplicationContext();
        appContext.register(AppConfig.class);
        appContext.register(AppConfig2.class);
        appContext.refresh();


La clase Tierra inicializa sus valores con la anotacion @Value en sus propiedades

public class Tierra {
    @Value("AZUL")
    private String Color;
    @Value("12742")
    private BigInteger diametro;

    public String getColor() {    return Color;     }
    public void setColor(String color) { Color = color;    }

    public BigInteger getDiametro() { return diametro; }
    public void setDiametro(BigInteger diametro) { this.diametro = diametro; }
}



 https://github.com/jalbertomr/jalbertomr-springAppContextBeans/commit/3202f72a3e757b986ad19fa953e0819056095bc0

Inyección por Constructor


   Creamos una clase Persona, y la declaramos en el beans.xml

Clase Persona
public class Persona {
    private int id;
    private String nombre;
    private String telefono;
   
    public Persona(int id, String nombre, String telefono) {
        this.id = id;
        this.nombre = nombre;
        this.telefono = telefono;
    }


    public Persona(int id) {
        this.id = id;
    }

    public Persona(String telefono) {
        this.telefono = telefono;
    }


En bean.xml declaramos el bean de Persona y las propiedades las inicializamos con constructor

beans.xml
...
<bean id="persona" class="com.bext.beans.Persona">
   <constructor-arg value="1"></constructor-arg>
   <constructor-arg value="Alberto"></constructor-arg>
   <constructor-arg value="4325235244"></constructor-arg>
</bean>

...

Al ejecutar la app tenemos
App.java
...
Persona per = (Persona) appContext.getBean("persona");
        System.out.println(per.getId() + " " + per.getNombre() +" "+per.getTelefono());

...

Iniciado...
1 Alberto 4325235244


Si solo inicializamos en el constructor con value="1" y ejecutamos la App tenemos

<bean id="persona" class="com.bext.beans.Persona">
   <constructor-arg value="1"></constructor-arg>
</bean>


Iniciado...
0 null 1


Observamos que con un solo valor en este caso "1" lo toma como String, o sea toma el constructor con un solo parametro de tipo String, pero este corresponde al Telefono. para que tome el int, hay que especificar el type="int" 

<bean id="persona" class="com.bext.beans.Persona">
   <constructor-arg type="int" value="1"></constructor-arg>
</bean>


Iniciado...
1 null null


Si especificamos el type="String" tomará el constructor con parámetro type String que corresponde al Telefono.

<bean id="persona" class="com.bext.beans.Persona">
   <constructor-arg type="String" value="1234567"></constructor-arg>
</bean>


Iniciado...
0 null 1234567


Podemos indicar la posición del parametro del constructor a inicializar

...
<bean id="persona" class="com.bext.beans.Persona">
   <constructor-arg index="2" value="1234567"></constructor-arg>
   <constructor-arg index="0" value="1"></constructor-arg>
   <constructor-arg index="1" value="Alberto"></constructor-arg>
</bean>

...

Iniciado...
1 Alberto 1234567


Inyección de Objectos

  A la Clase Persona le agregamos la Clase Pais.

Pais.java
public class Pais {
    private String nombre;

    public String getNombre() {
        return nombre;
    }

    public void setNombre(String nombre) {
        this.nombre = nombre;
    }
}


 
Persona.java
public class Persona {
    private int id;
    private String nombre;
    private String telefono;
    private Pais pais;
   
    public int getId() { return id; }
    public void setId(int id) {    this.id = id; }

    public String getNombre() {    return nombre;}
    public void setNombre(String nombre) { this.nombre = nombre;}

    public String getTelefono() { return telefono; }
    public void setTelefono(String telefono) { this.telefono = telefono; }

    public Pais getPais() {    return pais;}
    public void setPais(Pais pais) {this.pais = pais;}
}

App.java
public class App {

    public static void main(String[] args) {
        System.out.println("Iniciado...");
       
        /* Metodo Beans */
        ApplicationContext appContext = new ClassPathXmlApplicationContext("com/bext/xml/beans.xml");
        //AnnotationConfigApplicationContext appContext = new AnnotationConfigApplicationContext();
        //appContext.register(AppConfig.class);
        //appContext.register(AppConfig2.class);
        //appContext.refresh();
       
        Persona per = (Persona) appContext.getBean("persona");
        System.out.println(per.getId() + " " + per.getNombre() +" "+per.getTelefono() + " "+ per.getPais().getNombre());
       
        ((ConfigurableApplicationContext)appContext).close();
    }
}



beans.xml
...
<bean id="persona" class="com.bext.beans.Persona">
   <property name="pais" ref="pais"></property>
   <property name="id" value="1"></property>
   <property name="nombre" value="Alberto"></property>
   <property name="telefono" value="1234567"></property>
</bean>

<bean id="pais" class="com.bext.beans.Pais">
    <property name="nombre" value="Mexico"></property>
</bean>
...


Ejecución

Iniciado...
1 Alberto 1234567 Mexico


Inyección de sub-Objeto


Ahora agregamos otra clase a la de Pais, será Ciudad.

Ciudad.java
public class Ciudad {
    private String nombre;

    public String getNombre() {    return nombre;}
    public void setNombre(String nombre) {this.nombre = nombre;}
}


Pais.java
public class Pais {
    private String nombre;
    private Ciudad ciudad;

    public String getNombre() {    return nombre;    }
    public void setNombre(String nombre) {    this.nombre = nombre;    }

    public Ciudad getCiudad() {    return ciudad;    }
    public void setCiudad(Ciudad ciudad) {    this.ciudad = ciudad;}
}


beans.xml
...
<bean id="persona" class="com.bext.beans.Persona">
   <property name="pais" ref="pais"></property>
   <property name="id" value="1"></property>
   <property name="nombre" value="Alberto"></property>
   <property name="telefono" value="1234567"></property>
</bean>

<bean id="pais" class="com.bext.beans.Pais">
    <property name="nombre" value="Mexico"></property>
    <property name="ciudad" ref="ciudad"></property>
</bean>

<bean id="ciudad" class="com.bext.beans.Ciudad">
    <property name="nombre" value="CDMX"></property>
</bean>

...

App.java
...
        Persona per = (Persona) appContext.getBean("persona");
        System.out.println(per.getId() + " " + per.getNombre() +" "+per.getTelefono() + " "+ per.getPais().getNombre() + " "+per.getPais().getCiudad().getNombre());
...

Ejecución
Iniciado...
1 Alberto 1234567 Mexico CDMX


https://github.com/jalbertomr/jalbertomr-springAppContextBeans/commit/aa26774b29d7c021faf11faa7fdc67eaa47813de

Anidando Beans

Integramos Ciudad dentro de Pais
    <bean id="persona" class="com.bext.beans.Persona">
        <property name="pais" ref="pais"></property>
        <property name="id" value="1"></property>
        <property name="nombre" value="Alberto"></property>
        <property name="telefono" value="1234567"></property>
    </bean>

    <bean id="pais" class="com.bext.beans.Pais">
        <property name="nombre" value="Mexico"></property>
        <property name="ciudad">
            <bean id="ciudad" class="com.bext.beans.Ciudad">
                <property name="nombre" value="CDMX"></property>
            </bean>
        </property>
    </bean>


Ahora Integramos Ciudad dentro de Persona

    <bean id="persona" class="com.bext.beans.Persona">
        <property name="pais">
            <bean id="pais" class="com.bext.beans.Pais">
                <property name="nombre" value="Mexico"></property>
                <property name="ciudad">
                    <bean id="ciudad" class="com.bext.beans.Ciudad">
                        <property name="nombre" value="CDMX"></property>
                    </bean>
                </property>
            </bean>
        </property>
        <property name="id" value="1"></property>
        <property name="nombre" value="Alberto"></property>
        <property name="telefono" value="1234567"></property>
    </bean>


https://github.com/jalbertomr/jalbertomr-springAppContextBeans/commit/2817c32acb881ab56797c8cae565cee9e5317970


Referenciando Beans (Alias)


Creamos un alias en beans.xml para Persona

<alias name="persona" alias="personaAlias"></alias>

Y se llama este alias desde App.java

Persona per = (Persona) appContext.getBean("personaAlias");

Tambien podemos poner el nombre de alias en la definición del bean de Persona con nombre="personaAlias2"

<bean id="persona" class="com.bext.beans.Persona" name="personaAlias2">
        <property name="pais" ref="pais"></property>
        <property name="id" value="1"></property>
        <property name="nombre" value="Alberto"></property>
        <property name="telefono" value="1234567"></property>

</bean>

https://github.com/jalbertomr/jalbertomr-springAppContextBeans/commit/3dfbd46fb0850f4ba00a228dd72ac700682ab9ba


Colecciones (Lista) Beans

  Vamos a definir valores para las ciudades del pais por medio de inicialización por xml.

beans.xml
...
    <bean id="persona" class="com.bext.beans.Persona" name="personaAlias2">
        <property name="pais" ref="pais"></property>
        <property name="id" value="1"></property>
        <property name="nombre" value="Alberto"></property>
        <property name="telefono" value="1234567"></property>
    </bean>

    <bean id="pais" class="com.bext.beans.Pais">
        <property name="nombre" value="Mexico"></property>
        <property name="ciudades">
            <list>
               <ref bean="ciudad1"></ref>
               <ref bean="ciudad2"></ref>
               <ref bean="ciudad3"></ref>
            </list>

        </property>
    </bean>

    <bean id="ciudad1" class="com.bext.beans.Ciudad">
        <property name="nombre" value="CDMX"></property>
    </bean>
    <bean id="ciudad2" class="com.bext.beans.Ciudad">
        <property name="nombre" value="Tepatitlan"></property>
    </bean>
    <bean id="ciudad3" class="com.bext.beans.Ciudad">
        <property name="nombre" value="Guadalajara"></property>
    </bean>

...

La App.java la modificamos para que podamos desplegar la lista
...
Persona per = (Persona) appContext.getBean("personaAlias2");
        System.out.println(per.getId() + " " + per.getNombre() +" "+per.getTelefono() + " "+ per.getPais().getNombre());

        for (Ciudad ciudad:  per.getPais().getCiudades()) {
            System.out.println(ciudad.getNombre());
        }

...

Ejecución

Iniciado...
1 Alberto 1234567 Mexico
CDMX
Tepatitlan
Guadalajara


https://github.com/jalbertomr/jalbertomr-springAppContextBeans/commit/ff559934528cd433081c8d3caf9347f897e9364b


AutoWire

   Modificamos a Pais para que no tenga la propiedad Ciudad, se traslada esta propiedad a Persona.

  En beans.xml borramos las propiedades que asignaban a Pais y Ciudad, estos valores se tomaran con autowire la cual las asociará por nombre. 

beans.xml
...
<bean id="persona" class="com.bext.beans.Persona" autowire="byName">
        <property name="id" value="1"></property>
        <property name="nombre" value="Alberto"></property>
        <property name="telefono" value="1234567"></property>
    </bean>

    <bean id="pais" class="com.bext.beans.Pais">
        <property name="nombre" value="Mexico"></property>
    </bean>

    <bean id="ciudad" class="com.bext.beans.Ciudad">
        <property name="nombre" value="CDMX"></property>
    </bean>

...

Persona.java

public class Persona {
    private int id;
    private String nombre;
    private String telefono;
    private Pais pais;
    private Ciudad ciudad;

...

Ejecutando

Iniciado...
1 Alberto 1234567 Mexico CDMX


   El autowire puede hacerse tambien por type "byType", así asignará las propiedades de personas comparadas por tipo, pero si hay dos o más tipos no  sabrá a que bean asignar la propiedad. Tambien esta autowire por constructor.

Scope (Singleton, Prototype)

Prototype genera instancias diferentes por bean

...
<bean id="persona" class="com.bext.beans.Persona" autowire="byName" scope="prototype">
        <property name="id" value="1"></property>
        <property name="nombre" value="Alberto"></property>
        <property name="telefono" value="1234567"></property>
</bean>

...

Ejecución
Iniciado...
1 Alberto 1234567 Mexico CDMX
com.bext.beans.Persona@6fc6f14e
com.bext.beans.Persona@56235b8e


Singleton genera una sola instancia por cada bean que se cree.

...<bean id="persona" class="com.bext.beans.Persona" autowire="byName" scope="singleton">
        <property name="id" value="1"></property>
        <property name="nombre" value="Alberto"></property>
        <property name="telefono" value="1234567"></property>
    </bean>

...

Ejecución
Iniciado...
1 Alberto 1234567 Mexico CDMX
com.bext.beans.Persona@6fc6f14e
com.bext.beans.Persona@6fc6f14e


https://github.com/jalbertomr/jalbertomr-springAppContextBeans/commit/21d6eb30019cf7785188e7af715203808d58b6c0

eot

No hay comentarios:

Publicar un comentario