Spring4学习回顾之路05—自动装配,Bean的继承,依赖和作用域

自动装配

  xml配置里的Bean的自动装配,Spring IOC容器可以自动装配Bean,仅仅需要做的是在<bean>标签里的autowire属性里指定自动装配的模式。

  ①byType(根据类型自动装配):若IOC容器中有多个与目标Bean类型一致的Bean,在这种情况下,Spring无法判断哪个Bean与之匹配,所以不能执行自动装配。

  ②byName(根据名称自动装配):必须将目标Bean的名称和属性名设置的完全相同。

  ③constructor(通过构造器自动装配, 不推荐):当Bean中存在多个构造器时,此种自动装配方式会很复杂。

建立三个类测试,Person.java,Address.java,Car.java

Person.java

package com.lql.spring02;

/**
 * @author: lql
 * @date: 2019.10.12
 * Description:
 * Created with IntelliJ IDEA
 */
public class Person {


    private String name;


    private Address address;


    private Car car;


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

    public String getName() {
        return name;
    }

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

    public Address getAddress() {
        return address;
    }

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

    public Car getCar() {
        return car;
    }

    public void setCar(Car car) {
        this.car = car;
    }
}

 

Address.java

 

package com.lql.spring02;

/**
 * @author: lql
 * @date: 2019.10.12
 * Description:
 * Created with IntelliJ IDEA
 */
public class Address {


    private String city;

    private String street;

    @Override
    public String toString() {
        return "Address{" +
                "city='" + city + '\'' +
                ", street='" + street + '\'' +
                '}';
    }

    public String getCity() {
        return city;
    }

    public void setCity(String city) {
        this.city = city;
    }

    public String getStreet() {
        return street;
    }

    public void setStreet(String street) {
        this.street = street;
    }
}

 

Car.java

package com.lql.spring02;

/**
 * @author: lql
 * @date: 2019.10.12
 * Description:
 * Created with IntelliJ IDEA
 */
public class Car {

    private String brand;
    
    private double price;


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

    public String getBrand() {
        return brand;
    }

    public void setBrand(String brand) {
        this.brand = brand;
    }

    public double getPrice() {
        return price;
    }

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

 重新建立配置文件autowire.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"
       xmlns:P="http://www.springframework.org/schema/p"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">


    <bean id="address" class="com.lql.spring02.Address" P:city="海淀" P:street="中关村大街"></bean>

    <bean id="car" class="com.lql.spring02.Car" P:brand="凯迪拉克" P:price="9999.99"></bean>

    <bean id="person" class="com.lql.spring02.Person" P:name="lql" P:address-ref="address" P:car-ref="car"></bean>

</beans>

 

 测试类:

package com.lql.spring02;

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

/**
 * @author: lql
 * @date: 2019.10.12
 * Description:
 */
public class Test {

    public static void main(String[] args) {

        ApplicationContext app = new ClassPathXmlApplicationContext("autowire.xml");

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

        System.out.println(person);//Person{name='lql', address=Address{city='海淀', street='中关村大街'}, car=Car{brand='凯迪拉克', price=9999.99}}
    }
}

 

而自动装配则需要修改配置,如下:

<?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:P="http://www.springframework.org/schema/p"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">


    <bean id="address" class="com.lql.spring02.Address" P:city="海淀" P:street="中关村大街"></bean>

    <bean id="car" class="com.lql.spring02.Car" P:brand="凯迪拉克" P:price="9999.99"></bean>

    <!--<bean id="person" class="com.lql.spring02.Person" P:name="lql" P:address-ref="address" P:car-ref="car"></bean>-->


    <bean id="person" class="com.lql.spring02.Person" P:name="lql" autowire="byName"></bean>

</beans>

 

结果也是一样的,那么autowire=byName是指什么呢?看图

图中箭头必须保持一致,这就是ByName,如果更改了id,比如把car改成了car2,那么讲不会装配,测试则输出car=null;换一句话说,byName就是根据Bean的名字和当前Bean的setter方法的属性名进行自动装配。

但是我就想把原来的id=car叫id=car2,又不想改setter(),怎么办呢,那这时候就有了byType:根据Bean的类型和当前bean属性的类型进行自动在装配;

<?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:P="http://www.springframework.org/schema/p"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">


    <bean id="address" class="com.lql.spring02.Address" P:city="海淀" P:street="中关村大街"></bean>

    <bean id="car2" class="com.lql.spring02.Car" P:brand="凯迪拉克" P:price="9999.99"></bean>

    <!--<bean id="person" class="com.lql.spring02.Person" P:name="lql" P:address-ref="address" P:car-ref="car"></bean>-->


    <bean id="person" class="com.lql.spring02.Person" P:name="lql" autowire="byType"></bean>

</beans>

 

结果也是没问题的,但是byType有个问题,就是如果有多个同类型的Bean,那么就会报错。“expected single matching bean but found 2”,新版的idea直接报语法错误。

XML自动装配的缺点:

首先不够灵活,要么是byName,要么是byType,两者不能同时使用,缺少灵活性。其次autowire是定义在bean里的,意味着要用就全部自动装配,没有一半装配另一半不装配这样的局限性。

Bean的继承

  Spring允许继承bean的配置,子Bean从父Bean中继承配置,包括Bean的属性配置,子Bean也可以覆盖继承过来的配置。并不是所有的属性都会被继承,比如autowire,abstract等,也可以忽略父Bean的class属性,让子Bean指定自己的Bean,而共享相同的属性配置,但此时的abstract必须为true,父Bean若设置abstract属性为true,则Spring不会实例化这个Bean.

简单的演示配置如下:

<?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:P="http://www.springframework.org/schema/p"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">

    <bean id="car" class="com.lql.spring02.Car" P:brand="凯迪拉克" P:price="9999.99"></bean>


    <bean id="car2"  P:brand="宝马" parent="car"></bean>
</bean>

 

如果想要继承Bean,则只需要在子Bean中使用parent属性指定即可,测试输入如下:

package com.lql.spring02;

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

/**
 * @author: lql
 * @date: 2019.10.12
 * Description:
 */
public class Test {

    public static void main(String[] args) {
        ApplicationContext app = new ClassPathXmlApplicationContext("autowire.xml");
        Car car = app.getBean("car", Car.class);
        System.out.println(car);
        Car car2 = app.getBean("car2", Car.class);
        System.out.println(car2);

//Car{brand='凯迪拉克', price=9999.99}
//Car{brand='宝马', price=9999.99}
    }
}

 

 Bean的依赖

  Spring允许用户通过depends-on属性设定Bean前置依赖的Bean,前置依赖的Bean会在本Bean实例化之前创建好,如果前置依赖多个Bean,则可以通过逗号,空格方式配置Bean的名称。配置如下:

<?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:P="http://www.springframework.org/schema/p"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
    <bean id="address2" class="com.lql.spring02.Address" P:city="海淀" P:street="中关村大街"></bean>
    <bean id="car" class="com.lql.spring02.Car" P:brand="凯迪拉克" P:price="9999.99"></bean>
    <!--<bean id="person" class="com.lql.spring02.Person" P:name="lql" P:address-ref="address" P:car-ref="car"></bean>-->
    <bean id="person" class="com.lql.spring02.Person" P:name="lql" depends-on="address2"></bean>
</beans>

Bean的作用域 

singleton(单例)、prototype(多例)、request(HTTP请求)、session(会话)、global-session(全局会话)。

singleton和prototype作用域是Spring中经常用到的,简单来说,singleton作用域的Bean,IOC容器每次都返回同一个实例,而prototype作用域的Bean,IOC容器会每次产生一个新的实例。(Spring默认的作用域是singleton)

新建Student.java

package com.lql.spring03;

/**
 * @author: lql
 * @date: 2019.10.12
 * Description:
 * Created with IntelliJ IDEA
 */
public class Student {


    private String name;

    private int 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;
    }
}

 

配置文件如下:此时的<bean>中的scope的值是prototype.

<?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:p="http://www.springframework.org/schema/p"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
    <bean id="student" class="com.lql.spring03.Student" p:name="lql" p:age="17" scope="prototype"></bean>
</beans>

 

测试类:

package com.lql.spring03;

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

/**
 * @author: lql
 * @date: 2019.10.12
 * Description:
 * Created with IntelliJ IDEA
 */
public class Test {
    public static void main(String[] args) {
        ApplicationContext app = new ClassPathXmlApplicationContext("scope.xml");
        Student student = app.getBean("student", Student.class);
        Student student1 = app.getBean("student", Student.class);
        System.out.println(student==student1);     //false
    }
}

 

内存地址不一样,所以是两个对象。当换掉scope="singleton"或直接不写就是true

<?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:p="http://www.springframework.org/schema/p"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
    <bean id="student" class="com.lql.spring03.Student" p:name="lql" p:age="17" scope="singleton"></bean>
</beans>

 

posted @ 2019-10-12 17:33  DC红茶  阅读(270)  评论(0编辑  收藏  举报