Spring配置Bean-XML方式

114 阅读1分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第22天,点击查看活动详情


1 字面值

  • 字面值:可用字符串表示的值,可以通过 元素标签或 value 属性进行注入。
  • 基本数据类型及其封装类、String 等类型都可以采取字面值注入的方式。
  • 若字面值中包含特殊字符,可以使用 把字面值包裹起来。
<bean id="user2" class="site.exciter.spring.model.User">
        <!--如果包含特殊字数,可以使用<![CDATA[]]>标签将特殊字符包裹起来-->
        <!--属性值可以使用value子节点进行配置-->
        <constructor-arg name="name" type="java.lang.String">
            <value><![CDATA[_张三$]]></value>
        </constructor-arg>
        <constructor-arg name="gender" type="java.lang.String" value="男"/>
        <constructor-arg name="height" type="double">
            <value>175</value>
        </constructor-arg>
</bean>

2 引用其他的Bean

可以使用ref属性来引入其他Bean。

新建JavaBean类App.java

package site.exciter.spring.model;

public class App {
    private String name;
    private double version;
    private User user;

    public String getName() {
        return name;
    }

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

    public double getVersion() {
        return version;
    }

    public void setVersion(double version) {
        this.version = version;
    }

    public User getUser() {
        return user;
    }

    public void setUser(User user) {
        this.user = user;
    }

    @Override
    public String toString() {
        return "App{" +
                "name='" + name + ''' +
                ", version=" + version +
                ", user=" + user +
                '}';
    }
}

配置Bean

 		<!--ref:引用其他的Bean-->
    <bean id="app" class="site.exciter.spring.model.App">
        <property name="name" value="抖音"/>
        <property name="version" value="10.0"/>
        <property name="user" ref="user2"/>
    </bean>

		<!--或者使用ref子节点也可以-->
    <bean id="app" class="site.exciter.spring.model.App">
        <property name="name" value="抖音"/>
        <property name="version" value="10.0"/>
        <property name="user">
            <ref bean="user2"/>
        </property>
    </bean>

		<!--或者使用内部Bean,不能被外部引用,只能内部使用-->
    <bean id="app" class="site.exciter.spring.model.App">
        <property name="name" value="抖音"/>
        <property name="version" value="10.0"/>
        <property name="user">
            <bean class="site.exciter.spring.model.User">
                <constructor-arg name="name" value="赵子龙" index="0"/>
                <constructor-arg name="gender" value="男" index="1"/>
                <constructor-arg name="age" value="33" index="2"/>
            </bean>
        </property>
    </bean>

3 级联属性

   <bean id="app" class="site.exciter.spring.model.App">
        <constructor-arg name="name" value="抖音"/>
        <constructor-arg name="version" value="1.0"/>
        <constructor-arg name="user" ref="user2"/>
        <!--级联属性 引入外部Bean后,再去修改引入Bean的值-->
        <property name="user.name" value="李四"/>
    </bean>

4 返回List

Car.java

package site.exciter.spring.model;

public class Car {

    private String brand;
    private double 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;
    }

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

Person.java

package site.exciter.spring.model;

import java.util.List;

public class Person {
    private String name;
    private int age;
    private List<Car> cars;

    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 List<Car> getCars() {
        return cars;
    }

    public void setCars(List<Car> cars) {
        this.cars = cars;
    }

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

配置:使用list标签

<bean id="car" class="site.exciter.spring.model.Car">
        <property name="brand" value="BMW"/>
        <property name="price" value="300000"/>
    </bean>

    <bean id="person" class="site.exciter.spring.model.Person">
        <property name="name" value="冠宇"/>
        <property name="age" value="39"/>
        <property name="cars">
            <list>
                <ref bean="car"/>
                <ref bean="car"/>
                <ref bean="car"/>
            </list>
        </property>
    </bean>

5 返回Map

Person2.java

package site.exciter.spring.model;

import java.util.Map;

public class Person2 {

    private String name;
    private int age;
    private Map<String, Car> cars;

    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 Map<String, Car> getCars() {
        return cars;
    }

    public void setCars(Map<String, Car> cars) {
        this.cars = cars;
    }

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

配置

    <bean id="person2" class="site.exciter.spring.model.Person2">
        <property name="name" value="司马懿"/>
        <property name="age" value="50"/>
        <property name="cars">
            <map>
                <entry key="AA" value-ref="car"/>
                <entry key="BB" value-ref="car"/>
                <entry key="CC" value-ref="car"/>
            </map>
        </property>
    </bean>

6 配置properties

package site.exciter.spring.model;

import java.util.Properties;

public class DataSource {

    private Properties properties;

    public Properties getProperties() {
        return properties;
    }

    public void setProperties(Properties properties) {
        this.properties = properties;
    }

    @Override
    public String toString() {
        return "DataSource{" +
                "properties=" + properties +
                '}';
    }
}
<!--配置properties-->
    <bean id="dataSource" class="site.exciter.spring.model.DataSource">
        <property name="properties">
            <props>
                <prop key="user">root</prop>
                <prop key="password">root</prop>
                <prop key="jdbcUrl">jdbc:mysql://test</prop>
                <prop key="driverClass">com.mysql.jdbc.Driver</prop>
            </props>
        </property>
    </bean>

7 抽取集合Bean

<!--抽取集合Bean,方便多个bean复用-->
    <util:list id="cars">
        <ref bean="car"/>
        <ref bean="car2"/>
    </util:list>

    <bean id="person3" class="site.exciter.spring.model.Person">
        <property name="name" value="曹操"/>
        <property name="age" value="50"/>
        <property name="cars" ref="cars"/>
    </bean>

8 通过P命名空间为Bean赋值

<bean id="person4" class="site.exciter.spring.model.Person" p:name="貂蝉" p:age="20" p:cars-ref="cars"/>

9 自动装配

Address.java

package site.exciter.spring.autowire;

public class Address {
    private String city;
    private String 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;
    }

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

Car.java

package site.exciter.spring.autowire;

public class Car {
    private String brand;
    private double 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;
    }

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

Person.java

package site.exciter.spring.autowire;

public class Person {
    private String name;
    private Address address;
    private 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;
    }

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

配置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="site.exciter.spring.autowire.Address"
          p:city="北京" p:street="天通苑"/>

    <bean id="car" class="site.exciter.spring.autowire.Car"
          p:brand="Tesla" p:price="300000"/>

    <!-- autowire自动装配: 只声明 bean, 而把 bean 之间的关系交给 IOC 容器来完成 -->
    <!--
        byType: 根据类型进行自动装配. 但要求 IOC 容器中只有一个类型对应的 bean, 若有多个则无法完成自动装配.
        byName: 若属性名和某一个 bean 的 id 名一致, 即可完成自动装配. 若没有 id 一致的, 则无法完成自动装配
    -->
    <!-- 在使用 XML 配置时, 自动转配用的不多. 但在基于 注解 的配置时, 自动装配使用的较多-->
    <bean id="person" class="site.exciter.spring.autowire.Person"
          p:name="Tom" autowire="byName"/>
</beans>

10 Bean之间的关系:继承&依赖

继承:

  • Spring允许继承bean的配置,被继承的bean称为父 bean;继承这个父 Bean的Bean称为子 Bean。
  • 子Bean从父Bean中继承配置,包括Bean的属性配置。
  • 子Bean也可以覆盖从父Bean继承过来的配置。
  • 父Bean可以作为配置模板,也可以作为Bean实例;若只想把父 Bean 作为模板,可以设置的abstract属性为true,这样 Spring 将不会实例化这个Bean。
  • 并不是元素里的所有属性都会被继承;比如autowire、abstract等。
  • 也可以忽略父Bean的class属性,让子Bean指定自己的类,而共享相同的属性配置,但此时abstract必须设为true。

Address.java:

package site.exciter.spring.relation;

public class Address {
    private String city;
    private String 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;
    }

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

配置文件:

<?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="site.exciter.spring.relation.Address"
          p:city="北京" p:street="立水桥"/>

    <!--Bean配置的继承:使用Bean的parent属性指定继承na哪个Bean配置-->
    <bean id="address2" parent="address" p:street="天通苑南"/>
</beans>

如果只把父Bean当做模板,则将父Bean的abstract指定为true,这样父Bean就不能被IOC容器实例化:

  <bean id="address" class="site.exciter.spring.relation.Address" abstract="true"
          p:city="北京" p:street="立水桥"/>

依赖:

<bean id="car" class="site.exciter.spring.autowire.Car"
          p:brand="特斯拉" p:price="270000"/>

    <!--Bean配置的依赖:使用Bean的depends-on属性表示这个Bean必须包含被依赖的Bean,不然IOC容器会报错-->
    <bean id="person" class="site.exciter.spring.autowire.Person"
          p:name="马斯克" depends-on="car"/>

11 作用域

  • 在 Spring 中, 可以在 元素的 scope 属性里设置 Bean 的作用域。
  • 默认情况下, Spring 只为每个在 IOC 容器里声明的 Bean 创建唯一一个实例, 整个 IOC 容器范围内都能共享该实例:所有后续的 getBean() 调用和 Bean 引用都将返回这个唯一的 Bean 实例.该作用域被称为 singleton, 它是所有 Bean 的默认作用域。

12 使用外部属性文件

外部数据库配置文件db.properties:

user=root
password=root
driverClass=com.mysql.jdbc.Driver
jdbcUrl=jdbc:mysql:///test

在Bean配置中使用:

    <!--property-placeholder:引入外部配置文件-->
    <context:property-placeholder location="classpath:db.properties"/>

    <!--通过${}的方式获取外部配置文件的值-->
    <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
        <property name="user" value="${user}"/>
        <property name="password" value="${password}"/>
        <property name="driverClass" value="${driverClass}"/>
        <property name="jdbcUrl" value="${jdbcUrl}"/>
    </bean>

12 通过静态工厂方法配置Bean

Car.java:

package site.exciter.spring.factory;

public class Car {
    private String brand;
    private Double price;

    public Car(String brand, Double price) {
        this.brand = brand;
        this.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;
    }

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

StaticCarFactory.java:

package site.exciter.spring.factory;

import java.util.HashMap;
import java.util.Map;

/**
 * 静态工厂
 */
public class StaticCarFactory {
    private static Map<String, Car> cars = new HashMap<>();

    static {
        cars.put("奥迪", new Car("奥迪", 400000.0));
        cars.put("特斯拉", new Car("特斯拉", 300000.0));
    }

    public static Car getCar(String name) {
        return cars.get(name);
    }
}

Bean配置:

    <!--通过静态工厂方法来配置Bean实例-->
    <!--
        class:指向静态工厂方法的全类名
        factory-method:指向静态工厂方法名
        constructor-arg:为工厂方法配置参数
    -->
    <bean id="car1" class="site.exciter.spring.factory.StaticCarFactory" factory-method="getCar">
        <constructor-arg value="奥迪"/>
    </bean>

13 通过实例工厂方法配置Bean

InstanceCarFactory.java:

package site.exciter.spring.factory;

import java.util.HashMap;
import java.util.Map;

/**
 * 实例工厂
 */
public class InstanceCarFactory {
    private Map<String, Car> cars = null;

    public InstanceCarFactory() {
        cars = new HashMap<>();
        cars.put("奥迪", new Car("奥迪", 300000.0));
        cars.put("特斯拉", new Car("特斯拉", 250000.0));
    }

    public Car getCar(String brand) {
        return cars.get(brand);
    }
}

Bean配置:

    <!--配置工厂实例-->
    <bean id="instanceFactory" class="site.exciter.spring.factory.InstanceCarFactory"/>

    <!--通过实例工厂配置Bean-->
  	<!--
      factory-bean:指向实例工厂的Bean
      factory-method:指向实例工厂方法名
      constructor-arg:为工厂方法配置参数
    -->
    <bean id="car2" factory-bean="instanceFactory" factory-method="getCar">
        <constructor-arg value="特斯拉"/>
    </bean>

14 通过FactoryBean去配置Bean

CarFactoryBean.java:

package site.exciter.spring.factorybean;

import org.springframework.beans.factory.FactoryBean;

/**
 * 继承Spring的FactoryBean
 */
public class CarFactoryBean implements FactoryBean<Car> {

    @Override
    public Car getObject() throws Exception {
        return new Car("蔚来", 500000.0);
    }

    @Override
    public Class<?> getObjectType() {
        return Car.class;
    }

    @Override
    public boolean isSingleton() {
        return true;
    }
}

Bean配置:

<bean id="car" class="site.exciter.spring.factorybean.CarFactoryBean"/>

关注木水小站 (zhangmushui.cn)和微信公众号【木水Code】,及时获取更多最新技术干货。