[Primavera desde la entrada al tutorial de combate real] Capítulo 2 Bean de configuración de primavera

2. Configuración de Spring Bean

    Los objetos administrados por el contenedor Spring IoC se denominan beans, y los beans se crean en función de la información del archivo de configuración de Spring. El llamado bean de configuración es para decirle al contenedor IOC de Spring el objeto a administrar.

2.1 Formas de configurar beans

2.1.1 Método de configuración XML tradicional

Persona.java:

public class Person {
    private String name;
    private int age;
    private double money;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public double getMoney() {
        return money;
    }

    public void setMoney(double money) {
        this.money = money;
    }

    @Override
    public String toString() {
        return "Person{" +
                "name='" + name + '\'' +
                ", age=" + age +
                ", money=" + money +
                '}';
    }
}

contexto de aplicación.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
    http://www.springframework.org/schema/beans/spring-beans.xsd">
    <!--
    bean标签:让spring创建一个对象并放置在IOC容器内,一个bean标签就对应某个类的一个对象
    属性:
        id: 该bean对象的唯一标识符,bean的名称,不能重复的
        class: 需要创建对象的类型的全限定名,Spring通过反射机制创建该类的对象(要求:该类必须拥有无参构造方法)
    -->
    <bean id="person1" class="com.newcapec.bean.Person"/>
    <bean id="person2" class="com.newcapec.bean.Person">
</beans>

Resolución de atributos:

  • id: el nombre del bean debe ser único en el contenedor IOC. No importa si el archivo de configuración se divide o si se usan anotaciones más adelante, la identificación no debe repetirse; si no se especifica la identificación, Spring usará automáticamente la identificación completa. nombre de clase de la clase como el nombre del frijol;

  • class : el nombre completo de la clase java;

BeanTest.java:

public class BeanTest {

    @Test
    public void testBeanXML(){
        ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");

        Person p1 = (Person) ac.getBean("person1");
        System.out.println(p1);

        Person p2 = (Person) ac.getBean("person2");
        System.out.println(p2);

        //测试p1和p2是不是指向同一个地址
        System.out.println(p1 == p2);//false,验证一个Bean对应一个对象

        Person p3 = (Person) ac.getBean("person1");
        System.out.println(p1 == p3);//true
    }
}

2.1.2 Configuración basada en anotaciones Java

    Por favor, preste atención a los siguientes capítulos.

2.1.3 Configuración de Java basada en clases

    Por favor, preste atención a los siguientes capítulos.

2.2 Maneras de instanciar beans

2.2.1 Instanciar Bean a través del constructor

    El contenedor Spring IoC puede usar el constructor vacío predeterminado o el constructor parametrizado para instanciar el objeto Bean a través del mecanismo de reflexión.

2.2.2 Instanciar beans a través de fábricas

    Por favor, preste atención a los siguientes capítulos.

2.2.3 Bean de creación de instancias FactoryBean

    Por favor, preste atención a los siguientes capítulos.

2.3 Contenedor de resorte

    La idea de IoC se implementa en base al contenedor IoC, y la capa inferior del contenedor IoC es en realidad una fábrica de frijoles. Spring Framework nos proporciona dos tipos diferentes de contenedores IoC, que son BeanFactory y ApplicationContext.

2.3.1 Fábrica de Frijoles

    BeanFactory es la implementación básica del contenedor IoC y también el contenedor IoC más simple proporcionado por Spring. Proporciona las funciones más básicas del contenedor IoC y está definido por la interfaz org.springframework.beans.factory.BeanFactory.

    BeanFactory adopta un mecanismo de carga diferida: cuando el contenedor carga el archivo de configuración, el objeto Java no se creará inmediatamente, sino que solo se creará cuando el objeto se adquiera (utilice) en el programa.
    
    Nota: BeanFactory es una interfaz interna utilizada por Spring y, por lo general, no se proporciona para que los desarrolladores la utilicen. 

2.3.2 Contexto de aplicación

    ApplicationContext es una subinterfaz de la interfaz BeanFactory, que es una extensión de BeanFactory. ApplicationContext agrega muchas funciones de nivel empresarial sobre la base de BeanFactory, como AOP (programación orientada a aspectos), internacionalización, soporte de transacciones, etc.

2.3.3 Principales clases de implementación de ApplicationContext

  • ClassPathXmlApplicationContext: cargar archivos de configuración desde la ruta de clases;

  • FileSystemXmlApplicationContext: cargar archivos de configuración desde el sistema de archivos;

  • WebApplicationContext: especialmente preparado para aplicaciones WEB, permite la inicialización desde una ruta relativa al directorio raíz WEB;

2.3.4 Obtener el Bean del contenedor

  • El método getBean(String name) obtiene el objeto Bean del contenedor a través del id Bean;

  • El método getBean(Class requiredType) obtiene el objeto Bean del contenedor a través del tipo Class del Bean;

  • El método getBean(String name, Class requiredType) obtiene el objeto Bean del contenedor a través del id y el tipo de clase del Bean;

Nota: Cuando hay varios objetos de este tipo almacenados en el contenedor IOC, el objeto Bean no se puede obtener a través del tipo Clase.

BeanTest.java

public class BeanTest {
    @Test
    public void testGetBean() {
        ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");
        //1.参数为字符串类型
        Person p1 = (Person) ac.getBean("person1");
        System.out.println(p1);

        //2.参数为Class类型,缺点:当IOC容器中存在多个此类型对象时,抛出异常
        Person person = ac.getBean(Person.class);
        System.out.println(person);

        //3.参数为字符串类型+Class类型
        Person p2 = ac.getBean("person2", Person.class);
        System.out.println(p2);
    }
}

2.4 Inyección de dependencia

2.4.1 Inyección basada en la propiedad

    Podemos inyectar el valor del atributo en la propiedad del Bean a través del método setter del Bean.
    
    En el proceso de creación de instancias de beans en Spring, el contenedor IoC primero llamará al constructor predeterminado (constructor sin argumentos) para crear una instancia del Bean (objeto Java), y luego llamará al método setXxx() del bean a través del mecanismo de reflexión de Java para establecer el valor de propiedad Inyectar en el bean.
    
    Use la inyección de setter para la inyección de propiedades, los pasos generales son los siguientes:
        1. Proporcione un constructor predeterminado sin argumentos en el Bean (se puede omitir si no hay otros constructores de parámetros) y proporcione todas las propiedades que se deben inyectar. Un método setXxx();
        2. En el archivo de configuración Spring XML, use <beans> y su elemento secundario <bean> para definir el bean;
        3. Use el elemento <property> en el elemento <bean> para asignar valores para cada propiedad, use el atributo de nombre para especificar el nombre de la propiedad del Bean, y el atributo de valor o la subetiqueta <value> para especificar el valor de la propiedad.
        
    La inyección de propiedades es el método de inyección más utilizado en aplicaciones prácticas.

contexto de aplicación.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
    http://www.springframework.org/schema/beans/spring-beans.xsd">

    <!-- 通过setter方法注入属性值 -->
    <bean id="person" class="com.newcapec.bean.Person">
        <!--
        property标签:表示通过属性的set方法为属性赋值,也叫做依赖注入
        属性:
        	name: 对象中的属性名称
        	value: 属性值
        -->
        <property name="name" value="张三"/>
        <property name="age" value="20"/>
        <property name="money">
            <value>3600.5</value>
        </property>
    </bean>
</beans>
public class DiTest {

    @Test
    public void testSet() {
        ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");

        Person person = ac.getBean("person", Person.class);

        System.out.println(person);
    }
}

2.4.2 Inyección de métodos basados ​​en constructores

    Podemos implementar la inyección de propiedades del Bean a través del constructor parametrizado del Bean.
    
    Los pasos generales para implementar la inyección de atributos usando constructores son los siguientes:
        1. Agregue un constructor parametrizado al Bean, y cada parámetro en el constructor representa un atributo que necesita ser inyectado 2.
        
        En el archivo de configuración Spring XML, pase <beans > Y su elemento hijo <bean> define el Bean;

        3. Use el elemento <constructor-arg> en el elemento <bean> para asignar valores a los atributos en el constructor. Tantos parámetros como haya en el constructor Bean, necesita usar tantos <constructor-arg> elementos.

Coche.java:

public class Car {
    private String name;
    private String type;
    private double price;
    private int doors;

    public Car(String name, String type, double price, int doors) {
        this.name = name;
        this.type = type;
        this.price = price;
        this.doors = doors;
    }

    public Car(String name, String type, int doors) {
        this.name = name;
        this.type = type;
        this.doors = doors;
    }

    public Car(String name, String type, double price) {
        this.name = name;
        this.type = type;
        this.price = price;
    }

    public Car(String n, String t) {
        this.name = n;
        this.type = t;
    }

    @Override
    public String toString() {
        return "Car{" +
                "name='" + name + '\'' +
                ", type='" + type + '\'' +
                ", price=" + price +
                ", doors=" + doors +
                '}';
    }
}

contexto de aplicación.xml:

Nota: si hay varios métodos de construcción en esta clase, seleccione el método de construcción precisamente por índice, tipo o nombre.

<?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="car1" class="com.newcapec.bean.Car">
        <!--
        constructor-arg : 表示创建该类型的对象时,使用的构造方法的参数
        属性:
            value : 构造方法的参数值
            index : 构造方法参数的索引
            type : 构造方法参数的类型
            name : 构造方法参数的名称
        -->
        <constructor-arg value="宝马"/>
        <constructor-arg value="轿车"/>
        <constructor-arg value="360000"/>
        <constructor-arg value="4"/>
    </bean>
</beans>
  • Hacer coincidir los parámetros del constructor por índice

<bean id="car2" class="com.newcapec.bean.Car">
    <constructor-arg value="越野" index="1"/>
    <constructor-arg value="奔驰" index="0"/>
    <constructor-arg value="4" index="3"/>
    <constructor-arg value="560000" index="2"/>
</bean>
  • Hacer coincidir los parámetros del constructor por tipo

<bean id="car3" class="com.newcapec.bean.Car">
    <constructor-arg value="大众" type="java.lang.String"/>
    <constructor-arg value="商务车" type="java.lang.String"/>
    <constructor-arg value="290000" type="double"/>
</bean>
  • Hacer coincidir los parámetros del constructor por nombre de parámetro

<bean id="car4" class="com.newcapec.bean.Car">
    <constructor-arg value="电动车" name="t"/>
    <constructor-arg value="特斯拉" name="n"/>
</bean>

prueba:

public class DiTest {
    @Test
    public void testConstructor() {
        ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");

        Car car1 = ac.getBean("car1", Car.class);
        System.out.println(car1);

        Car car2 = ac.getBean("car2", Car.class);
        System.out.println(car2);

        Car car3 = ac.getBean("car3", Car.class);
        System.out.println(car3);

        Car car4 = ac.getBean("car4", Car.class);
        System.out.println(car4);
    }
}

2.5 Inyectar valores de atributo

2.5.1 Valores literales

  • Un valor que se puede representar mediante una cadena se puede <value>inyectar a través de la etiqueta o el atributo de valor;

  • La inyección de valor literal se puede utilizar para tipos de datos básicos, tipos de contenedores, cadenas y otros tipos. Spring convertirá automáticamente la cadena al tipo de datos correspondiente;

  • Si el valor literal contiene caracteres especiales, puede usar <![CDATA[]]>para ajustar el valor literal;

Persona.java:

public class Person {
    private String name;
    private int age;
    private double money;
    private Date birthday;
    private boolean gender;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public double getMoney() {
        return money;
    }

    public void setMoney(double money) {
        this.money = money;
    }

    public Date getBirthday() {
        return birthday;
    }

    public void setBirthday(Date birthday) {
        this.birthday = birthday;
    }

    public boolean isGender() {
        return gender;
    }

    public void setGender(boolean gender) {
        this.gender = gender;
    }

    @Override
    public String toString() {
        return "Person{" +
                "name='" + name + '\'' +
                ", age=" + age +
                ", money=" + money +
                ", birthday=" + birthday +
                ", gender=" + gender +
                '}';
    }
}

contexto de aplicación.xml:

<!--注入属性值:字面值-->
<bean id="per" class="com.newcapec.bean.Person">
    <property name="name" value="李四"/>
    <!--特殊值写法-->
    <!--<property name="name">
            <value><![CDATA[1<2]]></value>
        </property>-->
    <property name="age" value="20"/>
    <property name="money" value="3000.8"/>
    <!--对于日期值,如果写其他格式,不识别-->
    <property name="birthday" value="1998/05/12"/>
    <property name="gender" value="true"/>
</bean>

prueba:

@Test
public void testValue() {
    ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");

    Person per = ac.getBean("per", Person.class);

    System.out.println(per);
}

2.5.2 Referencias a otros beans

    Los beans que componen una aplicación a menudo necesitan cooperar entre sí para completar las funciones de la aplicación. Para permitir que los beans se accedan entre sí, debe especificar una referencia al bean en el archivo de configuración del bean.

Cliente.java:

public class Customer {
    private String username;
    private String password;

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    @Override
    public String toString() {
        return "Customer{" +
                "username='" + username + '\'' +
                ", password='" + password + '\'' +
                '}';
    }
}

Orden.java:

public class Order {
    private String orderNum;
    private double price;
    /**
     * 自定义类型的属性
     */
    private Customer customer;

    public Order() {
    }

    public Order(String orderNum, double price, Customer customer) {
        this.orderNum = orderNum;
        this.price = price;
        this.customer = customer;
    }

    public String getOrderNum() {
        return orderNum;
    }

    public void setOrderNum(String orderNum) {
        this.orderNum = orderNum;
    }

    public double getPrice() {
        return price;
    }

    public void setPrice(double price) {
        this.price = price;
    }

    public Customer getCustomer() {
        return customer;
    }

    public void setCustomer(Customer customer) {
        this.customer = customer;
    }

    @Override
    public String toString() {
        return "Order{" +
                "orderNum='" + orderNum + '\'' +
                ", price=" + price +
                ", customer=" + customer +
                '}';
    }
}
  • 2.5.2.1 Método del frijol interno

    Definiremos un bean dentro de un elemento <property> o <constructor-arg> de un elemento <bean> como un "bean interno".

1. El método setter inyecta beans internos:

    Podemos inyectar frijoles internos a través de setters. En este punto, solo necesitamos usar el elemento <bean> nuevamente para definir el bean interno en el elemento <property> debajo de la etiqueta <bean>, el formato es el siguiente.

<?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-3.0.xsd">

    <bean id="outerBean" class="……">
        <property name="……" >
            <!-- 定义内部 Bean -->
            <bean class="……">
                <property name="……" value="……" ></property>
                ……
            </bean>
        </property>
    </bean>
</beans>

    Nota: los beans internos son todos anónimos, no es necesario especificar la identificación y el nombre. Incluso si se especifica, el contenedor IoC no lo usará como un identificador para distinguir el Bean, sino que ignorará la etiqueta Scope del Bean. Por lo tanto, los beans internos casi siempre son anónimos y siempre se crean junto con los beans externos. Un bean interno no se puede inyectar en ningún otro bean que no sea el bean en el que reside.

<bean id="order1" class="com.newcapec.bean.Order">
    <property name="orderNum" value="20220413001"/>
    <property name="price" value="998"/>
    <!--setter 方式注入内部 Bean-->
    <property name="customer">
        <bean class="com.newcapec.bean.Customer">
            <property name="username" value="tom"/>
            <property name="password" value="123456"/>
        </bean>
    </property>
</bean>

2. Forma del constructor de inyectar Bean interno:

    Podemos inyectar el bean interno a través del constructor. En este punto, solo necesitamos usar el elemento <bean> nuevamente para definir el bean interno en el elemento <constructor-arg> debajo de la etiqueta <bean>, y el formato es el siguiente.

<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-3.0.xsd">

    <bean id="……" class="……">
        <constructor-arg name="……">
            <!--内部 Bean-->
            <bean class="……">
                <constructor-arg name="……" value="……"></constructor-arg>
                ……
            </bean>
        </constructor-arg>
    </bean>
</beans>

contexto de aplicación.xml:

<bean id="order2" class="com.newcapec.bean.Order">
    <constructor-arg name="orderNum" value="20220413002"/>
    <constructor-arg name="price" value="799"/>
    <!--构造函数方式注入内部 Bean-->
    <constructor-arg name="customer">
        <bean class="com.newcapec.bean.Customer">
            <property name="username" value="jack"/>
            <property name="password" value="123456"/>
        </bean>
    </constructor-arg>
</bean>
  • 2.5.2.2 método de referencia de atributo ref

    El atributo ref buscará el bean especificado del contenedor IOC de acuerdo con el nombre y luego asignará el valor por referencia.

1. <property>El atributo ref en la etiqueta:

<bean id="customer3" class="com.newcapec.bean.Customer">
    <property name="username" value="jerry"/>
    <property name="password" value="123456"/>
</bean>
<bean id="order3" class="com.newcapec.bean.Order">
    <property name="orderNum" value="20220413003"/>
    <property name="price" value="1299"/>
    <!-- 通过ref属性来注入属性值:其中ref属性的值为其他bean的id-->
    <property name="customer" ref="customer3"/>
</bean>

2. Sub-etiquetas <property>en etiquetas :<ref>

<bean id="customer4" class="com.newcapec.bean.Customer">
    <property name="username" value="Spike"/>
    <property name="password" value="123456"/>
</bean>
<bean id="order4" class="com.newcapec.bean.Order">
    <property name="orderNum" value="20220413004"/>
    <property name="price" value="698"/>
    <!-- 通过ref子标签来注入其他的bean对象-->
    <property name="customer">
        <ref bean="customer4"/>
    </property>
</bean>

prueba:

@Test
public void testRef() {
    ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");

    Order order1 = ac.getBean("order1", Order.class);
    System.out.println(order1);

    Order order2 = ac.getBean("order2", Order.class);
    System.out.println(order2);

    Order order3 = ac.getBean("order3", Order.class);
    System.out.println(order3);

    Order order4 = ac.getBean("order4", Order.class);
    System.out.println(order4);
}

2.5.3 Propiedades de la colección

    También podemos usar los siguientes elementos en el elemento <property> debajo de la etiqueta Bean para configurar las propiedades y los parámetros de los tipos de colección de Java, como Lista, Conjunto, Mapa y Propiedades.

Etiqueta ilustrar
<list> Se utiliza para inyectar valores de tipo lista, permitiendo la repetición.
<set> Se utiliza para inyectar el valor de tipo set, no se permite la duplicación.
<map> Se utiliza para inyectar la colección clave-valor, donde tanto la clave como el valor pueden ser de cualquier tipo.
<props> Se utiliza para inyectar colecciones de clave-valor, donde tanto la clave como el valor son tipos de cadena.

    Nota: Para valores de tipos comunes en la colección, se pueden inyectar directamente a través de la subetiqueta de valor o el atributo de valor. Para valores de tipos personalizados en la colección, se deben inyectar a través de etiquetas ref o beans internos.

Curso.java:

public class Course {
    private int id;
    private String cname;

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getCname() {
        return cname;
    }

    public void setCname(String cname) {
        this.cname = cname;
    }

    @Override
    public String toString() {
        return "Course{" +
                "id=" + id +
                ", cname='" + cname + '\'' +
                '}';
    }
}

Estudiante.java:

public class Student {
    private int id;
    private String name;
    private List<Course> courseList;
    private Integer[] ids;
    private Set<String> stringSet;
    private Map<String, Course> courseMap;
    private Properties props;

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public List<Course> getCourseList() {
        return courseList;
    }

    public void setCourseList(List<Course> courseList) {
        this.courseList = courseList;
    }

    public Integer[] getIds() {
        return ids;
    }

    public void setIds(Integer[] ids) {
        this.ids = ids;
    }

    public Set<String> getStringSet() {
        return stringSet;
    }

    public void setStringSet(Set<String> stringSet) {
        this.stringSet = stringSet;
    }

    public Map<String, Course> getCourseMap() {
        return courseMap;
    }

    public void setCourseMap(Map<String, Course> courseMap) {
        this.courseMap = courseMap;
    }

    public Properties getProps() {
        return props;
    }

    public void setProps(Properties props) {
        this.props = props;
    }

    @Override
    public String toString() {
        return "Student{" +
                "id=" + id +
                ", name='" + name + '\'' +
                ", courseList=" + courseList +
                ", ids=" + Arrays.toString(ids) +
                ", stringSet=" + stringSet +
                ", courseMap=" + courseMap +
                ", props=" + props +
                '}';
    }
}
  • 2.5.3.1 Colección de listas

    Para configurar propiedades del tipo java.util.List, debe especificar la etiqueta <list>, que contiene algunos elementos. Estas etiquetas pueden especificar valores constantes simples a través de <value> y referencias a otros beans a través de <ref>.

<bean id="course1" class="com.newcapec.bean.Course">
    <property name="id" value="10"/>
    <property name="cname" value="Java语言"/>
</bean>
<bean id="course2" class="com.newcapec.bean.Course">
    <property name="id" value="20"/>
    <property name="cname" value="Oracle数据库"/>
</bean>
<bean id="course3" class="com.newcapec.bean.Course">
    <property name="id" value="30"/>
    <property name="cname" value="Spring框架"/>
</bean>

<bean id="student" class="com.newcapec.bean.Student">
    <property name="id" value="1001"/>
    <property name="name" value="小明"/>
    <property name="courseList">
        <list>
            <ref bean="course1"/>
            <ref bean="course2"/>
            <ref bean="course3"/>
            <!--内部bean-->
            <bean class="com.newcapec.bean.Course">
                <property name="id" value="40"/>
                <property name="cname" value="Mybatis框架"/>
            </bean>
        </list>
    </property>
</bean>
@Test
public void testCollection() {
    ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");

    Student student = ac.getBean("student", Student.class);
    System.out.println(student);
}
  • 2.5.3.2 Objeto[] matriz

    Para configurar las propiedades de un tipo de matriz, utilice la etiqueta `<matriz>`.

<bean id="student" class="com.newcapec.bean.Student">
    <property name="id" value="1001"/>
    <property name="name" value="小明"/>
    <!-- 数组:array子标签-->
    <property name="ids">
        <array>
            <value>10</value>
            <value>20</value>
            <value>30</value>
            <value>40</value>
        </array>
    </property>
</bean>
  • 2.5.3.3 Colección de conjuntos

    Para configurar propiedades de tipo java.util.Set, use la etiqueta `<set>`.

<bean id="student" class="com.newcapec.bean.Student">
    <property name="id" value="1001"/>
    <property name="name" value="小明"/>
    <!-- set集合:set子标签-->
    <property name="stringSet">
        <set>
            <value>hello</value>
            <value>goodbye</value>
            <value>how are you</value>
        </set>
    </property>
</bean>
  • 2.5.3.4 Colección de mapas

    java.util.Map se define mediante la etiqueta `<map>`, y se pueden usar múltiples `<entry>` como subetiquetas en la etiqueta `<map>`. Cada `<entrada>` contiene una clave y un valor. Los tipos simples se definen mediante atributos de clave y valor, y las referencias de Bean se definen mediante los atributos key-ref y value-ref.

<bean id="student" class="com.newcapec.bean.Student">
    <property name="id" value="1001"/>
    <property name="name" value="小明"/>
    <!-- map集合:map子标签-->
    <property name="courseMap">
        <map>
            <!--
            entry标签:表示Map集合中的一组键值对
            key: 表示Map集合中的键为字面值
            key-ref: 表示Map集合中的键为自定义类型
            value: 表示Map集合中的值为字面值
            value-ref: 表示Map集合中的值为自定义类型
            -->
            <entry key="one" value-ref="course3"/>
            <entry key="two" value-ref="course1"/>
        </map>
    </property>
</bean>
  • 2.5.3.5 Propiedades

    Utilice `<props>` para definir java.util.Properties. Esta etiqueta utiliza múltiples `<prop>` como subetiquetas. Cada etiqueta `<prop>` debe definir el atributo clave.

<bean id="student" class="com.newcapec.bean.Student">
    <property name="id" value="1001"/>
    <property name="name" value="小明"/>
    <!-- Properties类型的属性 -->
    <property name="props">
        <props>
            <!-- prop标签,表示Properties集合中的一个键值对,key属性对应的键,prop开始标签与结束标签之后的区域填写值-->
            <prop key="hello">你好</prop>
            <prop key="goodbye">再见</prop>
        </props>
    </property>
</bean>
  • 2.5.3.6 Colecciones Singleton

    Colección Singleton: utilizada por varios beans. Use la etiqueta `<util>` para definir la colección fuera del bean.

    Nota: Requiere importar el espacio de nombres de utilidad y la especificación de etiqueta.

xmlns:util="http://www.springframework.org/schema/util"

http://www.springframework.org/schema/util
http://www.springframework.org/schema/util/spring-util.xsd
<bean id="student" class="com.newcapec.bean.Student">
    <property name="id" value="1001"/>
    <property name="name" value="小明"/>
    <!-- 引入单例集合 -->
    <property name="courseList" ref="myList"></property>
</bean>

<!-- 外部集合:多个集合属性可同时引用 -->
<util:list id="myList">
    <ref bean="course1"/>
    <ref bean="course2"/>
    <ref bean="course3"/>
    <bean class="com.newcapec.bean.Course">
        <property name="id" value="40"/>
        <property name="cname" value="MySQL数据库"/>
    </bean>
</util:list>

2.5.4 Inyección de espacios de nombres cortos

    Cuando realizamos la inyección de propiedades a través del método constructor o setter, generalmente lo implementamos anidando los elementos <property> y <constructor-arg> en el elemento <bean>. Aunque este método tiene una estructura clara, es más engorroso de escribir.

    Spring Framework proporciona dos espacios de nombres cortos, que pueden simplificar la configuración XML de Spring, como se muestra en la siguiente tabla.

espacio de nombres corto Configuración XML simplificada ilustrar
p espacio de nombres <bean><property>elementos anidados dentro de elementos Es una implementación abreviada de la inyección de propiedades de setter.
c espacio de nombres <bean><constructor>elementos anidados dentro de elementos Es una implementación abreviada de la inyección de propiedades del constructor.

Departamento java:

public class Dept {
    private int deptno;
    private String dname;
    private String loc;

    public Dept() {
    }

    public Dept(int deptno, String dname, String loc) {
        this.deptno = deptno;
        this.dname = dname;
        this.loc = loc;
    }

    public int getDeptno() {
        return deptno;
    }

    public void setDeptno(int deptno) {
        this.deptno = deptno;
    }

    public String getDname() {
        return dname;
    }

    public void setDname(String dname) {
        this.dname = dname;
    }

    public String getLoc() {
        return loc;
    }

    public void setLoc(String loc) {
        this.loc = loc;
    }

    @Override
    public String toString() {
        return "Dept{" +
                "deptno=" + deptno +
                ", dname='" + dname + '\'' +
                ", loc='" + loc + '\'' +
                '}';
    }
}

Emp.java:

public class Emp {
    private int empno;
    private String ename;
    /**
     * 关系属性
     */
    private Dept dept;

    public Emp() {
    }

    public Emp(int empno, String ename, Dept dept) {
        this.empno = empno;
        this.ename = ename;
        this.dept = dept;
    }

    public int getEmpno() {
        return empno;
    }

    public void setEmpno(int empno) {
        this.empno = empno;
    }

    public String getEname() {
        return ename;
    }

    public void setEname(String ename) {
        this.ename = ename;
    }

    public Dept getDept() {
        return dept;
    }

    public void setDept(Dept dept) {
        this.dept = dept;
    }

    @Override
    public String toString() {
        return "Emp{" +
                "empno=" + empno +
                ", ename='" + ename + '\'' +
                ", dept=" + dept +
                '}';
    }
}
  • 2.5.4.1p Inyección de espacio de nombres

    El espacio de nombres p es una implementación abreviada de la inyección de propiedades de estilo setter. A través de él, podemos implementar la inyección de propiedades de setter en forma de propiedades de bean en lugar de usar elementos <property> anidados para lograr el propósito de simplificar la configuración XML de Spring.

    Primero necesitamos importar las siguientes restricciones XML en el elemento <beans> del archivo de configuración.

xmlns:p="http://www.springframework.org/schema/p"

Después de importar las restricciones XML, podemos implementar la inyección de atributos de la siguiente forma:

<bean id="Bean 唯一标志符" class="包名+类名" p:普通属性="普通属性值" p:对象属性-ref="对象的引用">

Al usar el espacio de nombres p para inyectar dependencias, debe prestar atención a los siguientes tres puntos:

  • Debe haber un método setter en la clase Java;

  • Debe haber un constructor sin parámetros en una clase Java (la clase no contiene ningún constructor con parámetros, el constructor sin parámetros existe por defecto);

  • Antes de usar el espacio de nombres p para implementar la inyección de atributos, las restricciones XML del espacio de nombres p deben importarse a <beans>los elementos .

contexto de aplicación.xml:

<!-- 通过p命名空间的方式,来简化依赖注入 -->
<bean id="dept" class="com.newcapec.bean.Dept" p:deptno="10" p:dname="研发部" p:loc="郑州"/>

<bean id="emp" class="com.newcapec.bean.Emp" p:empno="8000" p:ename="张三" p:dept-ref="dept"/>

prueba:

@Test
public void testPNameSpace() {
    ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");
    Emp emp = ac.getBean("emp", Emp.class);
    System.out.println(emp);
}
  • 2.5.4.2 inyección de espacio de nombres c

    El espacio de nombres c es un atajo para la inyección de constructor. A través de él, podemos realizar la inyección de atributos del método constructor en la forma del atributo <bean>, en lugar de usar el elemento anidado <constructor-arg>, para lograr el propósito de simplificar la configuración XML de Spring.

    Primero necesitamos importar las siguientes restricciones XML en el elemento <beans> del archivo de configuración.

xmlns:c="http://www.springframework.org/schema/c"

Después de importar las restricciones XML, podemos implementar la inyección de atributos de la siguiente forma:

<bean id="Bean 唯一标志符" class="包名+类名" c:普通属性="普通属性值" c:对象属性-ref="对象的引用">

Al usar el espacio de nombres c para inyectar dependencias, debe prestar atención a los siguientes 2 puntos:

  • La clase Java debe contener el constructor parametrizado correspondiente;

  • Antes de usar el espacio de nombres c para implementar la inyección de atributos, las restricciones XML del espacio de nombres c deben importarse a <beans>los elementos .

contexto de aplicación.xml:

<!-- 通过c命名空间的方式,来简化依赖注入 -->
<bean id="department" class="com.newcapec.bean.Dept" c:deptno="20" c:dname="产品部" c:loc="杭州"/>

<bean id="employee" class="com.newcapec.bean.Emp" c:empno="7369" c:ename="李四" c:dept-ref="department"/>

prueba:

@Test
public void testCNameSpace() {
    ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");
    Emp emp = ac.getBean("employee", Emp.class);
    System.out.println(emp);
}

2.5.5 montaje automático autowire

    Llamamos "cableado" al comportamiento de Spring de establecer dependencias entre Beans y Beans.

    Aunque el contenedor IOC de Spring es poderoso, es solo una cáscara vacía y no puede completar el trabajo de ensamblaje por sí mismo. Necesitamos tomar la iniciativa para poner el Bean y decirle las dependencias entre el Bean y el Bean, para que pueda completar el trabajo de ensamblaje de acuerdo con nuestros requisitos.

    En los estudios anteriores, mantuvimos manualmente la relación de dependencia entre Bean y Bean a través del atributo ref en <constructor-arg> y <property> en la configuración XML.
    
    Para aplicaciones que contienen solo una pequeña cantidad de beans, este enfoque es suficiente para nuestras necesidades. Pero con el desarrollo continuo de la aplicación, se incluirán más y más beans en el contenedor, y las dependencias entre beans se volverán cada vez más complicadas, lo que hace que la configuración XML que escribimos sea cada vez más complicada y más compleja. incómodo.

    Sabemos que una configuración XML demasiado compleja no solo es deficiente en legibilidad, sino que también es extremadamente propensa a errores cuando se escribe, lo que reduce seriamente la eficiencia de desarrollo de los desarrolladores. Para resolver este problema, Spring Framework también nos proporciona la función de "autoconexión".
    
    La función de ensamblaje automático de Spring permite que el contenedor Spring encuentre los beans de los que depende desde el contexto de la aplicación (contenedor ApplicationContext) para el bean especificado de acuerdo con ciertas reglas (reglas de ensamblaje automático, hay cinco tipos) y establece automáticamente la relación entre los beans .dependencias. Y este proceso se lleva a cabo sin usar ningún atributo ref del elemento <constructor-arg> y <property>.

    La función de ensamblaje automático de Spring puede simplificar de manera efectiva la configuración XML de las aplicaciones Spring, por lo que cuando hay muchas configuraciones, se puede usar el ensamblaje automático para reducir la carga de trabajo.

    Spring Framework no admite el ensamblaje automático de forma predeterminada. Si desea utilizar el ensamblaje automático, debe establecer el atributo de conexión automática del elemento <bean> en el archivo de configuración Spring XML.

Spring proporciona un total de 5 reglas de ensamblaje automático, que corresponden a los 5 valores del atributo autowire, como se muestra en la siguiente tabla:

valor de atributo ilustrar
por nombre Autowire por nombre. Spring buscará en el contexto ApplicationContext (contenedor IoC) de toda la aplicación según el nombre del atributo del objeto en la clase Java. Si el valor del atributo id o name de un Bean es el mismo que el nombre de este atributo de objeto, obtenga este Bean y establezca una relación de asociación con el Bean de clase Java actual.
por tipo Autowire por tipo. Spring buscará en el contexto ApplicationContext (contenedor IoC) de toda la aplicación según el tipo de propiedad del objeto en la clase Java. Si el valor del atributo de clase de un Bean coincide con el tipo del atributo del objeto, el Bean se adquiere y se asocia con el Bean de la clase Java actual.
constructor Similar al patrón byType, excepto que se aplica a los parámetros del constructor (dependencias), y se lanzará una excepción si no se encuentra ningún bean del mismo tipo que el parámetro del constructor en el contenedor. De hecho, según el tipo de datos del parámetro constructor, se realiza el ensamblaje automático del modo byType.
por defecto Indica que la regla de ensamblaje automático (default-autowire) <beans>establecida .
No El valor predeterminado significa que no se utiliza ningún ensamblado automático, y las dependencias del Bean deben <constructor-arg>definirse <property>a través de los atributos ref de los elementos y .
  • 2.5.5.1 No utilice autowire (autowire="no")

    autowire="no" significa no usar ensamblaje automático. En este momento, debemos mantener la relación de dependencia del Bean a través del <constructor-arg> del elemento <bean> y el atributo ref del elemento <property>.

  • 2.5.5.2 Autowire por nombre (autowire="byName")

    `autowire="byName"` significa autowire por nombre de atributo, el id o el nombre del Bean en el archivo XML debe ser el mismo que el nombre del atributo en la clase.
    
    Nota: Si el id o el nombre del Bean debe coincidir con el nombre del atributo en la clase, se ensamblará automáticamente; de ​​lo contrario, será el valor predeterminado.

<!-- 自动装配 -->
<bean id="dept" class="com.newcapec.bean.Dept" p:deptno="10" p:dname="研发部" p:loc="郑州"/>
<bean id="department" class="com.newcapec.bean.Dept" c:deptno="20" c:dname="产品部" c:loc="杭州"/>

<bean id="emp" class="com.newcapec.bean.Emp" p:empno="7689" p:ename="王武" autowire="byName"/>
  • 2.5.5.3 Autowire por tipo (autowire="byType")

    `autowire="byType"` significa autowire según el tipo de datos del atributo del objeto en la clase. Incluso si la identificación o el nombre del Bean en el archivo XML es diferente del nombre del atributo en la clase, siempre que el valor del atributo de clase del Bean sea del mismo tipo que el atributo del objeto en la clase, el cableado automático puede ser terminado.
    
    Nota: si existen varios beans del mismo tipo al mismo tiempo, la inyección falla y se genera una excepción.

<!-- 自动装配 -->
<bean id="dept" class="com.newcapec.bean.Dept" p:deptno="10" p:dname="研发部" p:loc="郑州"/>
<bean id="department" class="com.newcapec.bean.Dept" c:deptno="20" c:dname="产品部" c:loc="杭州"/>

<bean id="emp" class="com.newcapec.bean.Emp" p:empno="7689" p:ename="马六" autowire="byType"/>
  • 2.5.5.4 Auto cableado del constructor (autowire="constructor")

    autowire="constructor" significa realizar un ensamblaje automático de acuerdo con el constructor en la clase Java.
    
    Rara vez se usa y ya no se demuestra.

  • 2.5.5.5 Modo de cableado automático predeterminado (autowire="default")

    De forma predeterminada, la regla de ensamblaje automático (default-autowire) establecida por la etiqueta de nivel superior <beans> se usa para el ensamblaje, y el contenido de configuración en Beans.xml es el siguiente. 

<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-3.0.xsd" 
       default-autowire="byName">
    
    <!-- 自动装配 -->
    <bean id="dept" class="com.newcapec.bean.Dept" p:deptno="10" p:dname="研发部" p:loc="郑州"/>
    <bean id="department" class="com.newcapec.bean.Dept" c:deptno="20" c:dname="产品部" c:loc="杭州"/>

    <bean id="emp" class="com.newcapec.bean.Emp" p:empno="7689" p:ename="马六" autowire="default"/>
</beans>

Desventajas del cableado automático de Bean en la configuración XML:

  • Establecer el atributo de conexión automática en el archivo de configuración del bean para la conexión automática conectará todas las propiedades del bean. Sin embargo, el atributo autowire no es lo suficientemente flexible si solo desea ensamblar atributos individuales;

  • los atributos de conexión automática se conectan automáticamente por tipo o por nombre, no ambos;

  • En circunstancias normales, la función de ensamblaje automático rara vez se usa en proyectos reales, porque en comparación con los beneficios que brinda la función de ensamblaje automático, los documentos de configuración claros y claros son más convincentes;

2.6 Uso de archivos de propiedades externas

Agregue espacio de nombres y especificaciones de etiquetas:

xmlns:context="http://www.springframework.org/schema/context"

http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd

db.propiedades:

# Mysql相关配置
jdbc.mysql.driver=com.mysql.jdbc.Driver
jdbc.mysql.url=jdbc:mysql://localhost:3306/ssm?characterEncoding=utf8&useSSL=false
jdbc.mysql.username=root
jdbc.mysql.password=root

Introducir un archivo de propiedades externo:

<!-- 读取外部的资源文件-->
<context:property-placeholder location="classpath:db.properties"/>

MiFuenteDeDatos.java:

public class MyDataSource {
    private String driver;
    private String url;
    private String username;
    private String password;

    public String getDriver() {
        return driver;
    }

    public void setDriver(String driver) {
        this.driver = driver;
    }

    public String getUrl() {
        return url;
    }

    public void setUrl(String url) {
        this.url = url;
    }

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    @Override
    public String toString() {
        return "MyDataSource{" +
                "driver='" + driver + '\'' +
                ", url='" + url + '\'' +
                ", username='" + username + '\'' +
                ", password='" + password + '\'' +
                '}';
    }
}

Acceda a datos en archivos de propiedades a través de expresiones:

<bean id="myDataSource" class="com.newcapec.bean.MyDataSource">
    <property name="driver" value="${jdbc.mysql.driver}"/>
    <property name="url" value="${jdbc.mysql.url}"/>
    <property name="username" value="${jdbc.mysql.username}"/>
    <property name="password" value="${jdbc.mysql.password}"/>
</bean>

prueba:

public class ReadPropertiesTest {

    @Test
    public void test() {
        ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");

        MyDataSource myDataSource = ac.getBean("myDataSource", MyDataSource.class);
        System.out.println(myDataSource);
    }
}

2.7 Alcance del frijol

    De forma predeterminada, todos los Spring Beans son singletons, lo que significa que solo hay una instancia de Bean en toda la aplicación Spring.

    Podemos agregar el atributo scope al elemento <bean> para configurar el alcance del Spring Bean. Por ejemplo, si necesita una nueva instancia de Bean cada vez que obtiene un Bean, debe definir el atributo de alcance del Bean como prototipo. Si Spring necesita devolver la misma instancia de Bean cada vez, debe definir el atributo de alcance del Bean como único.

    Spring 5 proporciona un total de 6 ámbitos, como se muestra en la siguiente tabla.

Ámbito de actuación describir
único Valor por defecto, modo singleton . Indica que el contenedor IOC crea una instancia del bean cuando se inicializa, y solo se crea una instancia del bean en todo el ciclo de vida del contenedor.
prototipo El modo prototipo significa que el contenedor IOC no crea una instancia del bean cuando se inicializa, sino que crea una nueva instancia del bean cada vez que se usa.
pedido Cada solicitud HTTP, el contenedor creará una instancia de Bean. Este alcance solo es válido dentro de la solicitud HTTP actual.
sesión La misma sesión HTTP comparte una instancia de Bean y diferentes sesiones usan diferentes instancias de Bean. Este alcance solo es válido dentro de la sesión HTTP actual.
solicitud La misma aplicación web comparte una instancia de Bean y este alcance es válido dentro del ServletContext actual. Similar a singleton, pero singleton significa que solo hay una instancia de Bean en cada contenedor IoC, y puede haber múltiples contenedores IoC en una aplicación web, pero una aplicación web solo tendrá un ServletContext, y también se puede decir que la aplicación es la instancia del bean en una aplicación web El patrón singleton real.
enchufe web El alcance de websocket es WebSocket, que es válido en todo el WebSocket.

    Nota: en los 6 ámbitos de bean anteriores, excepto que singleton y prototipo se pueden usar directamente en contenedores Spring IoC convencionales (como ClassPathXmlApplicationContext), el resto solo se puede usar en implementaciones de ApplicationContext basadas en web (como XmlWebApplicationContext), de lo contrario, se generará una IllegalStateException. ser arrojado
    
    En esta sección, solo explicaremos en detalle los dos ámbitos de bean de singleton y prototipo. En cuanto a otros ámbitos de frijol, los presentaremos en cursos posteriores.

Libro.java:

public class Book {
    private int id;
    private String name;
    private double price;
    private String author;

    public Book(){
        System.out.println("Book对象被创建....");
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public double getPrice() {
        return price;
    }

    public void setPrice(double price) {
        this.price = price;
    }

    public String getAuthor() {
        return author;
    }

    public void setAuthor(String author) {
        this.author = author;
    }

    @Override
    public String toString() {
        return "Book{" +
                "id=" + id +
                ", name='" + name + '\'' +
                ", price=" + price +
                ", author='" + author + '\'' +
                '}';
    }
}

2.7.1 único

    singleton es el ámbito predeterminado del contenedor Spring. Cuando el alcance del bean es singleton, solo habrá una instancia de bean compartida en el contenedor Spring IoC. La instancia de Bean se almacenará en el caché, y todas las solicitudes y referencias al Bean devolverán la instancia de objeto en el caché siempre que la identificación coincida con la definición de Bean.

    Si el alcance de una definición de Bean es singleton, entonces el Bean se denomina bean singleton. En el contenedor Spring IoC, el bean singleton es la forma predeterminada de crear beans, lo que puede reutilizar mejor los objetos y ahorrar el costo de crear objetos repetidamente.

    En el archivo de configuración de Spring, puede usar el atributo de alcance del elemento <bean> para definir el alcance del Bean como un singleton. El método de configuración es el siguiente:

contexto de aplicación.xml:

<!-- singleton -->
<bean id="book" class="com.newcapec.bean.Book" p:id="101" p:name="西游记"
      p:price="98.5" p:author="吴承恩" scope="singleton"/>

2.7.2 prototipo

    Si el alcance de una definición de Bean es prototipo, entonces el Bean se denomina bean prototipo. Para prototipos de beans, el contenedor Spring creará una nueva instancia de Bean cada vez que se solicite el Bean.
    
    En cierto sentido, el contenedor Spring IoC es equivalente al nuevo operador de Java para beans prototipo. Sólo es responsable de la creación del Bean, y la gestión del ciclo de vida posterior la realiza el código del cliente.
    
    En el archivo de configuración de Spring, puede usar el atributo de alcance del elemento <bean> para definir el alcance del Bean como prototipo, y el método de configuración es el siguiente:

<!-- prototype -->
<bean id="book" class="com.newcapec.bean.Book" p:id="101" p:name="西游记"
      p:price="98.5" p:author="吴承恩" scope="prototype"/>

prueba:

public class ScopeTest {
    @Test
    public void test(){
        ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");
        System.out.println("------------分割线--------------");

        Book book1 = ac.getBean("book",Book.class);
        System.out.println(book1);
        Book book2 = ac.getBean("book",Book.class);
        System.out.println(book2);

        System.out.println(book1 == book2);
    }
}

2.8 Ciclo de vida del frijol

    En las aplicaciones Java tradicionales, el ciclo de vida de un bean es muy simple.Después de crear una instancia del bean utilizando la palabra clave new de Java, se puede utilizar el bean. Una vez que el Bean no se usa durante mucho tiempo, Java realiza automáticamente la recolección de basura.

    Por el contrario, el ciclo de vida de los frijoles en Spring es más complicado. El contenedor Spring IOC puede gestionar el ciclo de vida de los frijoles. Spring permite realizar tareas personalizadas en puntos específicos del ciclo de vida de los frijoles, que se pueden dividir aproximadamente en siguientes cinco etapas: 1.
        Instanciación del ciclo de vida del Bean
        2. Asignación de atributos del Bean
        3. Inicialización del Bean
        4. Uso del Bean
        5. Destrucción del Bean
        
    Spring selecciona el método de gestión del Bean de acuerdo con el alcance
        del Bean. El contenedor Spring IoC puede controlar con precisión cuándo se crea el Bean, cuándo se inicializa y cuándo se destruye;
        para el Bean del alcance del prototipo, el contenedor Spring IoC solo es responsable de crearlo y luego entregar la instancia Bean a la gestión del código del cliente, el contenedor Spring IoC ya no se rastreará su vida útil.

2.8.1 Proceso del ciclo de vida del resorte

    El ciclo de vida completo de Spring Bean comienza desde la creación del contenedor Spring IoC hasta que el contenedor Spring IoC final destruye el bean. El proceso específico se muestra en la figura a continuación.

Todo el proceso de ejecución del ciclo de vida del Bean se describe a continuación:

  1. Spring se inicia, encuentra y carga el Bean que debe administrar Spring y crea una instancia del Bean.

  2. Realice la inyección de propiedades en el Bean.

  3. Si el Bean implementa la interfaz BeanNameAware, Spring llama al método setBeanName() del Bean para pasar el valor de id del Bean actual.

  4. Si Bean implementa la interfaz BeanFactoryAware, Spring llama al método setBeanFactory() pasando una referencia a la instancia de fábrica actual.

  5. Si Bean implementa la interfaz ApplicationContextAware, Spring llama al método setApplicationContext() para pasar una referencia a la instancia actual de ApplicationContext.

  6. Si el Bean implementa la interfaz BeanPostProcessor, Spring llama al método de preinicialización de la interfaz postProcessBeforeInitialzation() para procesar el Bean. Esto es muy importante aquí, y el AOP de Spring se implementa usándolo.

  7. Si el bean implementa la interfaz InitializingBean, Spring llamará al método afterPropertiesSet().

  8. Si se especifica un método de inicialización a través del atributo init-method en el archivo de configuración, se llama al método de inicialización.

  9. Si BeanPostProcessor está asociado con el Bean, Spring llamará al método de inicialización de la interfaz postProcessAfterInitialization(). En este punto, el Bean está listo para ser utilizado por el sistema de aplicación.

  10. Si el alcance del bean se especifica como singleton <bean>en , coloque el bean en el grupo de búfer de Spring IoC para activar la gestión del ciclo de vida de Spring del bean; si <bean>el alcance del bean se especifica como prototipo en , entonces el bean se entrega a la persona que llama, y ​​la persona que llama administra el ciclo de vida del bean, y Spring ya no administra el bean.

  11. Si el Bean implementa la interfaz del Bean desechable, Spring llamará al método destroy() para destruir el Bean; si el método de destrucción del Bean se especifica a través del atributo destroy-method en el archivo de configuración, Spring llamará a este método para destruir el Bean.

2.8.2 Ciclo de vida de frijoles personalizados

    Podemos especificar algunos métodos de devolución de llamada del ciclo de vida para completar algunas operaciones personalizadas en un momento específico en el ciclo de vida de Spring Bean y administrar el ciclo de vida de Bean.

Hay dos métodos principales de devolución de llamada del ciclo de vida del bean:

  • Método de devolución de llamada de inicialización: se invoca después de que Spring Bean se inicializa para realizar algunas operaciones de devolución de llamada personalizadas.

  • Método de devolución de llamada de destrucción: se invoca antes de que Spring Bean se destruya para realizar algunas operaciones de devolución de llamada personalizadas.

Podemos personalizar el método de devolución de llamada del ciclo de vida del Bean de las siguientes tres maneras:

  • Implementado a través de la interfaz.

  • Implementado a través de la configuración XML

  • Implementado usando anotaciones

    Si hay varios métodos de devolución de llamada del ciclo de vida en un bean, el orden de prioridad es: anotación > interfaz > configuración XML.

Perro.java:

public class Dog {
    private String name;
    private String owner;
    private int age;

    public Dog() {
        System.out.println("Dog对象被创建...");
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        System.out.println("调用setName方法....");
        this.name = name;
    }

    public String getOwner() {
        return owner;
    }

    public void setOwner(String owner) {
        System.out.println("调用setOwner方法....");
        this.owner = owner;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        System.out.println("调用setAge方法....");
        this.age = age;
    }

    @Override
    public String toString() {
        return "Dog{" +
                "name='" + name + '\'' +
                ", owner='" + owner + '\'' +
                ", age=" + age +
                '}';
    }
}

contexto de aplicación.xml:

<bean id="dog" class="com.newcapec.bean.Dog" p:name="旺财" p:owner="小明" p:age="5"/>

prueba:

public class LifeCycleTest {
    @Test
    public void testLifeCycle() {
        System.out.println("-------容器初始化阶段---------");
        ClassPathXmlApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");

        System.out.println("-------对象使用阶段---------");
        Dog dog = ac.getBean("dog", Dog.class);
        System.out.println(dog);

        System.out.println("-------容器关闭阶段---------");
        //手动关闭容器
        ac.close();//ApplicationContext没有close()
    }
}
  • 2.8.2.1 Implementado a través de interfaces

    Podemos especificar el método de devolución de llamada del ciclo de vida del Bean implementando las interfaces InitializingBean y AvailableBean en la clase Java del Spring Bean.
    
    Nota: En general, no recomendamos especificar el método de devolución de llamada del ciclo de vida de esta manera, ya que esto conducirá a un alto acoplamiento del código.

método de devolución de llamada interfaz método ilustrar
devolución de llamada de inicialización InitializingBean afterPropertiesSet() Especifique el método de devolución de llamada de inicialización, que se llamará después de que Spring Bean se inicialice para realizar algunas operaciones de devolución de llamada personalizadas.
destruir devolución de llamada Frijol Desechable destruir() Especifique el método de devolución de llamada de destrucción, que se llamará antes de que se destruya Spring Bean, y realice algunas operaciones de devolución de llamada personalizadas.

Perro.java:

public class Dog implements InitializingBean, DisposableBean {
    private String name;
    private String owner;
    private int age;

    public Dog() {
        System.out.println("Dog对象被创建...");
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        System.out.println("调用setName方法....");
        this.name = name;
    }

    public String getOwner() {
        return owner;
    }

    public void setOwner(String owner) {
        System.out.println("调用setOwner方法....");
        this.owner = owner;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        System.out.println("调用setAge方法....");
        this.age = age;
    }

    @Override
    public String toString() {
        return "Dog{" +
                "name='" + name + '\'' +
                ", owner='" + owner + '\'' +
                ", age=" + age +
                '}';
    }

    /**
     * 初始化回调逻辑
     *
     * @throws Exception
     */
    @Override
    public void afterPropertiesSet() throws Exception {
        System.out.println(" 调用接口:InitializingBean,方法:afterPropertiesSet,无参数");
    }
    /**
     * 销毁回调逻辑
     *
     * @throws Exception
     */
    @Override
    public void destroy() throws Exception {
        System.out.println(" 调用接口:DisposableBean,方法:destroy,无参数");
    }
}
  • 2.8.2.2 Implementación mediante configuración XML

    También podemos especificar el método de devolución de llamada del ciclo de vida del Bean a través de los atributos init-method y destroy-method en el elemento <bean> en la configuración XML de Spring.

Propiedades de configuración XML describir
método de inicio Especifique el método de devolución de llamada de inicialización, que se llamará después de que Spring Bean se inicialice para realizar algunas operaciones de devolución de llamada personalizadas.
metodo de la historia Especifique el método de devolución de llamada de destrucción, que se llamará antes de que se destruya Spring Bean, y realice algunas operaciones de devolución de llamada personalizadas.

Perro.java:

public class Dog {
    private String name;
    private String owner;
    private int age;

    public Dog() {
        System.out.println("Dog对象被创建...");
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        System.out.println("调用setName方法....");
        this.name = name;
    }

    public String getOwner() {
        return owner;
    }

    public void setOwner(String owner) {
        System.out.println("调用setOwner方法....");
        this.owner = owner;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        System.out.println("调用setAge方法....");
        this.age = age;
    }

    public void init(){
        System.out.println("Dog对象的初始化方法...");
    }
    
    public void destroy(){
        System.out.println("Dog对象的销毁方法...");
    }

    @Override
    public String toString() {
        return "Dog{" +
                "name='" + name + '\'' +
                ", owner='" + owner + '\'' +
                ", age=" + age +
                '}';
    }
}

contexto de aplicación.xml:

<bean id="dog" class="com.newcapec.bean.Dog" p:name="旺财" p:owner="小明" p:age="5"  
      init-method="init" destroy-method="destroy"/>

2.9 Relación entre frijoles

2.9.1 Relación de herencia

  • Spring permite la configuración de beans heredados, y el bean heredado se llama bean padre. Un bean que hereda de este bean padre se denomina bean hijo;

  • El bean hijo hereda la configuración del bean padre, incluida la configuración de propiedades del bean;

  • Los beans secundarios también pueden anular la configuración heredada del bean principal;

  • El bean principal se puede utilizar como plantilla de configuración o como instancia de bean. Si solo desea utilizar el bean principal como plantilla, puede establecer <bean>el atributo abstracto en verdadero, de modo que Spring no instanciará este bean;

  • No <bean>todos los atributos de un elemento se heredan. Por ejemplo: autowire, resumen, etc.;

  • También puede ignorar el atributo de clase del bean principal (no es necesario crear un objeto de bean principal, solo proporcione una plantilla para el bean secundario), deje que el bean secundario especifique su propia clase y comparta la misma configuración de atributos. Pero en este momento, abstract debe establecerse en true;

Animal.java:

public class Animal {
    private String name;
    private Integer age;

    public void setName(String name) {
        this.name = name;
    }

    public void setAge(Integer age) {
        this.age = age;
    }

    @Override
    public String toString() {
        return "Animal{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}

contexto de aplicación.xml:

<!-- bean之间的继承关系 -->
<bean id="animal" class="com.newcapec.bean.Animal">
    <property name="name" value="动物"></property>
    <property name="age" value="10"></property>
</bean>
<bean id="dog" class="com.newcapec.bean.Dog" parent="animal">
    <property name="name" value="小狗"></property>
    <property name="owner" value="小黑"></property>
</bean>

prueba:

public class RelationTest {
    @Test
    public void testExtends() {
        ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");

        Dog dog = ac.getBean("dog", Dog.class);
        System.out.println(dog);
    }
}

Defina la plantilla:

    En la definición del Bean padre, hay un atributo muy importante, que es el atributo abstracto. Si el valor del atributo abstracto de un Bean principal es verdadero, indica que el Bean es abstracto.

    El Bean padre abstracto solo puede ser heredado por el Bean hijo como una plantilla, no se puede crear una instancia, ni otros Beans pueden hacer referencia a él, y no se puede obtener llamando al método getBean() de acuerdo con la identificación en el código, de lo contrario, se devolverá un error.

    En la definición del bean padre, especifique el atributo de clase o no especifique el atributo de clase. Si la definición del Bean principal no especifica explícitamente el atributo de clase, entonces el atributo abstracto del Bean principal debe ser verdadero.

contexto de aplicación.xml:

<!-- bean模版 -->
<bean id="animal" abstract="true">
    <property name="name" value="动物"></property>
    <property name="age" value="10"></property>
</bean>

<bean id="dog" class="com.newcapec.bean.Dog" parent="animal">
    <property name="name" value="小狗"></property>
    <property name="owner" value="小黑"></property>
</bean>

2.9.2 Dependencias

  • Spring permite a los usuarios configurar el bean predependiente del bean a través del atributo depende de, y el bean predependiente se creará antes de que se cree una instancia del bean;

  • Si el frente depende de múltiples beans, puede configurar el nombre del bean por coma o espacio;

Dirección.java:

public class Address {
    public Address() {
        System.out.println("Address对象创建了....");
    }
}

Usuario.java:

public class User {
    private Address address;

    public Address getAddress() {
        return address;
    }

    public void setAddress(Address address) {
        this.address = address;
    }

    public User() {
        System.out.println("User对象创建了....");
    }

    @Override
    public String toString() {
        return "User{" +
                "address=" + address +
                '}';
    }
}

contexto de aplicación.xml:

<!-- bean之间的依赖关系 -->
<bean id="user" class="com.newcapec.bean.User" p:address-ref="address" depends-on="address"/>

<bean id="address" class="com.newcapec.bean.Address"/>

prueba:

public class RelationTest {
    @Test
    public void testDependsOn(){
        ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");

        User user = ac.getBean("user", User.class);
        System.out.println(user);
    }
}

2.10 Instanciar Bean a través de fábrica

2.10.1 Fábricas estáticas

  • Llamar a un método de fábrica estático para crear un bean encapsula el proceso de creación de objetos en un método estático. Cuando el cliente necesita el objeto, solo necesita llamar al método estático sin preocuparse por los detalles de la creación del objeto;

  • Para declarar un bean creado por un método estático, debe especificar la clase que posee el método de fábrica en el atributo de clase del bean y especificar el nombre del método de fábrica en el atributo de método de fábrica. Finalmente, use <constrctor-arg>el elemento para pasar parámetros de método al método;

Gato.java:

public class Cat {
    private String name;
    private int age;

    public Cat() {
    }

    public Cat(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    @Override
    public String toString() {
        return "Cat{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}

CatStaticFactory.java:

/**
 * 一个用于创建cat对象的静态工厂
 */
public class CatStaticFactory {
    /**
     * 提供一个创建对象的静态方法
     */
    public static Cat getInstance(String name, int age){
        return new Cat(name, age);
    }
}

contexto de aplicación.xml:

<!-- 静态工厂-->
<bean id="cat1" class="com.newcapec.factory.CatStaticFactory" factory-method="getInstance">
    <constructor-arg value="汤姆猫"/>
    <constructor-arg value="2"/>
</bean>

prueba:

public class FactoryTest {
    @Test
    public void testStaticFactory() {
        ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");
        Cat cat = ac.getBean("cat1", Cat.class);
        System.out.println(cat);
    }
}

2.10.2 Fábrica de instancias

  • Encapsule el proceso de creación de un objeto en un método de otra instancia de objeto. Cuando el cliente necesita solicitar un objeto, solo necesita llamar al método de instancia sin preocuparse por los detalles de la creación del objeto;

  • Para declarar un bean creado por un método de fábrica de instancia, <bean>especifique el bean que posee el método de fábrica en el atributo factory-bean y especifique el nombre del método de fábrica en el atributo de método de fábrica. Finalmente, use <construtor-arg>etiquetas para pasar parámetros de método a métodos de fábrica;

CatInstanceFactory.java:

/**
 * 一个用于创建cat对象的实例工厂
 */
public class CatInstanceFactory {
    /**
     * 提供一个创建对象的非静态方法
     */
    public Cat getInstance(String name, int age){
        return new Cat(name, age);
    }
}

contexto de aplicación.xml:

<!-- 实例工厂-->
<bean id="instanceFactory" class="com.newcapec.factory.CatInstanceFactory"/>

<bean id="cat2" factory-bean="instanceFactory" factory-method="getInstance">
    <constructor-arg value="波斯猫"/>
    <constructor-arg value="3"/>
</bean>

prueba:

public class FactoryTest {
    @Test
    public void testInstanceFactory() {
        ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");
        Cat cat = ac.getBean("cat2", Cat.class);
        System.out.println(cat);
    }
}

2.11 FactoryBean instancia Bean

  • Hay dos tipos de frijoles en Spring, uno es un frijol normal y el otro es un frijol de fábrica, FactoryBean;

  • El bean de fábrica es diferente del bean normal, el objeto que devuelve no es una instancia de la clase especificada, devuelve el objeto devuelto por el método getObject del bean de fábrica;

CatFactoryBean.java:

public class CatFactoryBean implements FactoryBean<Cat> {
    private String name;
    private int age;

    public void setName(String name) {
        this.name = name;
    }

    public void setAge(int age) {
        this.age = age;
    }

    /**
     * 获取对象
     */
    @Override
    public Cat getObject() throws Exception {
        return new Cat(name, age);
    }

    /**
     * 生成对象的Class类型
     */
    @Override
    public Class<?> getObjectType() {
        return Cat.class;
    }

    /**
     * 设置该对象是否为单例模式
     */
    @Override
    public boolean isSingleton() {
        return true;
    }
}

contexto de aplicación.xml:

<!-- FactoryBean配置bean -->
<bean id="cat3" class="com.newcapec.factory.CatFactoryBean">
    <property name="name" value="加菲猫"/>
    <property name="age" value="5"/>
</bean>

prueba:

public class FactoryTest {
    @Test
    public void testFactoryBean(){
        ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");
        Cat cat = ac.getBean("cat3", Cat.class);
        System.out.println(cat);
    }
}

2.12 <beans>Atributos de uso común o subelementos de elementos

    El elemento <beans> de la configuración XML puede contener múltiples atributos o subelementos, y los atributos o subelementos comúnmente utilizados se muestran en la siguiente tabla.

Nombre del Atributo describir
identificación El identificador único del bean y la configuración y administración del bean por parte del contenedor Spring IoC se completan a través de esta propiedad. El valor de id debe comenzar con una letra y se pueden usar símbolos como letras, números y guiones bajos.
nombre Este atributo representa el nombre del Bean, podemos especificar varios nombres para el mismo Bean a través del atributo name, y cada nombre está separado por una coma o un punto y coma. El contenedor Spring puede configurar y administrar el Bean en el contenedor a través del atributo de nombre.
clase Este atributo especifica la clase de implementación específica del Bean, que debe ser un nombre de clase completo, es decir, el nombre completo de la clase.
alcance Indica el alcance del Bean, y el valor del atributo puede ser singleton (singleton), prototipo (prototipo), solicitud, sesión y sesión global. El valor predeterminado es singleton.
constructor-arg <bean>El elemento secundario del elemento, podemos pasar los parámetros de construcción a través de este elemento para realizar la creación de instancias del Bean. El atributo de índice de este elemento especifica el número de serie del parámetro de construcción (a partir de 0) y el atributo de tipo especifica el tipo de parámetro de construcción.
propiedad <bean>El subelemento del elemento se utiliza para llamar al método setter en la instancia de Bean para asignar valores a las propiedades, completando así la inyección de propiedades. El atributo de nombre de este elemento se usa para especificar el nombre de propiedad correspondiente en la instancia de Bean.
árbitro <property><constructor-arg> 等元素的子元索,用于指定对某个 Bean 实例的引用,即 <bean> 元素中的 id 或 name 属性。
value <property><constractor-arg> 等元素的子元素,用于直接指定一个常量值。
list 用于封装 List 或数组类型的属性注入。
set 用于封装 Set 类型的属性注入。
map 用于封装 Map 类型的属性注入。
entry <map> 元素的子元素,用于设置一个键值对。其 key 属性指定字符串类型的键值,ref 或 value 子元素指定其值。
init-method 容器加载 Bean 时调用该方法,类似于 Servlet 中的 init() 方法
destroy-method 容器删除 Bean 时调用该方法,类似于 Servlet 中的 destroy() 方法。该方法只在 scope=singleton 时有效
lazy-init 懒加载,值为 true,容器在首次请求时才会创建 Bean 实例;值为 false,容器在启动时创建 Bean 实例。该方法只在 scope=singleton 时有效

Supongo que te gusta

Origin blog.csdn.net/ligonglanyuan/article/details/124567965
Recomendado
Clasificación