Spring 3. XML自动装配、关系等细节

1. 装配Bean的可选方案

Spring容器负责创建应用程序中的bean并通过DI来协调这些对象之间的关系。
但需要告诉Spring要创建哪些Bean并且如何将其装配在一起。 Spring有三种主要的装配机制:
- 在XML中进行显式配置;
- 在java中进行显示配置(通过注解);
- 隐式的bean发现机制和自动装配。

这篇博文讲述XML高级装配。

2. XML自动装配

在上一篇博文中是通过XML手动配置的,但较麻烦,Spring为了提高开发效率,提供自动装配,来简化配置。Spring默认不支持自动装配;要想使用,需要修改Spring配置文件中<bean>标签的autowire属性。

Spring支持:

  • byName :根据当前bean的setter风格的属性名和bean的名字(id)进行自动装配。
  • byType:根据当前bean的属性的类型和bean的类型进行自动装配,若IOC容器中有多个类型匹配的bean,发生冲突。
  • constructor(不推荐使用):使用构造方法进行自动装配,根据构造方法参数的byType方式。
  • autodetect(已被弃用):自动选择:如果对象没有无参构造方法,那么自动选择constructor的自动装配方式进行构造注入。如果对象含有无参数的构造方法,那么自动选择byType的自动装配方式进行setter注入。

2.1 byName自动装配

先写两个bean:

  • Car类
public class Car {
    private String brand;

    public Car() { }

    public Car(String brand) {
        this.brand = brand;
    }

    public String getBrand() {
        return brand;
    }

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

    @Override
    public String toString() {
        return "Car{" +
                "brand='" + brand + '\'' +
                '}';
    }
}
  • Person类
public class Person {
    private String name;
    private Car car;

    public Person(){}

    public Person(String name, Car car) {
        this.name = name;
        this.car = car;
    }

    public Car getCar() {
        return car;
    }

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

    public String getName() {
        return name;
    }

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

    @Override
    public String toString() {
        return "Person{" +
                "name='" + name + '\'' +
                ", car=" + car +
                '}';
    }
}
  • SpringXML配置
<?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"
       xmlns:c="http://www.springframework.org/schema/c" 
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd">
   <bean id="car" class="demo.Car" p:brand="Audi"></bean>

   <!--手动装配-->
   <!--<bean id="person" class="demo.Person" p:name="chen" p:car-ref="car"></bean>-->
   <!--byName自动装配-->
   <bean id="person" class="demo.Person" p:name="chen" autowire="byName"></bean>
</beans>
  • 测试
public class Main {
    public static void main(String[] args) {
        ApplicationContext context = new ClassPathXmlApplicationContext("beans-autowire.xml");
        Person person = (Person) context.getBean("person");
        System.out.println(person);
    }
}

会在控制台打印出Person{name='chen', car=Car{brand='Audi'}}

2.2 byType自动装配

  • SpringXML配置
<?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"
       xmlns:c="http://www.springframework.org/schema/c" 
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd">
   <!--修改car bean的配置中id属性-->
   <bean id="carcarcarcar" class="demo.Car" p:brand="Audi"></bean>

   <!--手动装配-->
   <!--<bean id="person" class="demo.Person" p:name="chen" p:car-ref="car"></bean>-->
   <!--byType自动装配-->
   <bean id="person" class="demo.Person" p:name="chen" autowire="byType"></bean>
</beans>

修改了car bean配置中id属性之后,也能通过byType来装配。
在控制打印出相同的结果Person{name='chen', car=Car{brand='Audi'}}

2.3 constructor自动装配

  • SpringXML配置
<?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"
       xmlns:c="http://www.springframework.org/schema/c"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
   <!--修改bean的配置中id属性-->
   <bean id="carcarcarcar" class="demo.Car" p:brand="Audi"></bean>
   <bean id="namenamename" class="java.lang.String" c:value="chen"></bean>

   <bean id="person" class="demo.Person" autowire="constructor"></bean>
</beans>

修改id与bean的setter不同后,即
<bean id="carcarcarcar" class="demo.Car" c:brand="Audi"></bean>
<bean id="namenamename" class="java.lang.String" c:value="chen"></bean>

修改id后依旧可以通过constructor自动装配获取,可以验证是通过构造方法的参数byType自动装配的。

3. Bean之间的关系

这里的关系是指bean 的配置之间的关系,而不是指实际意义上类与类之间的继承与依赖。

3.1 继承(parent)

使用bean的parent属性指定继承bean的配置
1.子bean可以覆盖从父bean继承的配置
2.将父bean作为模板,可以设置<bean>的abstract属性为true,Spring不会实例化这个bean
3.autowire、abstract等属性不会被继承
4.可以忽略父bean的class属性,让子bean指定自己的类,从而共享相同的属性配置,但此时abstract必须设为true

  • SpringXML配置
<?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"
       xmlns:c="http://www.springframework.org/schema/c"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">

   <bean id="car1" class="demo.Car" p:brand="BMW" abstract="true"></bean>
   <bean id="car2" class="demo.Car" parent="car1"></bean>

   <bean id="person" class="demo.Person" p:name="chen" p:car-ref="car2"></bean>
</beans>

这段代码就出现了两个属性abstract="true"parent="car1"

3.2 依赖(depend-on)

不指定 depends-on 属性,IOC 容器默认实例化的顺序是按照 bean 在配置文件中的顺序来实例化的。
指定后,依赖的bean会在本bean实例化之前创建。可以指定多个依赖bean。
- SpringXML配置

<?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">
    <!-- depends-on :person这个bean必须依赖于car,若依赖多个bean,通过逗号和空格来指定-->
    <bean id="person" class="demo.Person" p:name="chen" p:car-ref="car2 car1"></bean>

    <bean id="car1" class="demo.Car" p:brand="BMW"></bean>
    <bean id="car2" class="demo.Car" parent="car1"></bean>
</beans>

4. Bean的作用域(scope)

定义在bean的一个属性scope,默认为singleton,如:
<bean id="car" class="demo.Car" scope="singleton"></bean>

作用域描述
singleton单例模式,在整个Spring IoC容器中,使用singleton定义的Bean将只有一个实例
prototype原型模式,每次通过容器的getBean方法获取prototype定义的Bean时,都将产生一个新的Bean实例
request对于每次HTTP请求,使用request定义的Bean都将产生一个新实例,即每次HTTP请求将会产生不同的Bean实例。只有在Web应用中使用Spring时,该作用域才有效
session对于每次HTTP Session,使用session定义的Bean都将产生一个新实例。同样只有在Web应用中使用Spring时,该作用域才有效
globalSession每个全局的HTTP Session,使用session定义的Bean都将产生一个新实例。典型情况下,仅在使用portlet context的时候有效。同样只有在Web应用中使用Spring时,该作用域才有效

5. 使用外部属性文件

当出现:

  1. 参数在某些阶段是常量
  2. 参数在不同阶段可能需要改变

对于这种情况Spring可以引入<content:property-placeholder>元素。
下面用过连接数据库的例子。

在context命名空间(通过xmlns:context="http://www.springframework.org/schema/context"声明)

  • SpringXML配置
<context:property-placeholder location="classpath:db.properties"/>

另一种:

  • SpringXML配置
<bean id="propertyPlaceholderConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
    <property name="locations">
        <list>
            <value>db.properties</value>
        </list>
    </property>
</bean>

如果location中有多个文件,将依次加载,但如果前面一个文件的属性名和后面的一个文件属性名相同,最终取得的是后面文件的值。
所以需要避免不同文件中的属性名重名。

  • db.properties配置文件
#jdbc配置
user=root
password=root
driverClass=com.mysql.jdbc.Driver
jdbcUrl=jdbc:mysql:///library
  • SpringXML配置
<!-- 使用外部化属性文件的属性 -->
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
    <property name="user" value="${user}" ></property>
    <property name="password" value="${password}"></property>
    <property name="driverClass" value="${driverClass}"></property>
    <property name="jdbcUrl" value="${jdbcUrl}"></property>
</bean>

这里出现了类似于EL表达式的${}形式。

Spring容器仅允许最多定义一个PropertyPlaceholderConfigurer<content:property-placeholder>其余的会被Spring忽略。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值