Spring全家桶(二)Bean之间的关系、自动装配、作用域和使用外部文件

五、Bean的自动装配

Spring IOC容器可以自动装配Bean,需要在bean的autowire属性里指定自动装配的模式。

<?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.stuspring.autowire.Address" p:city="BeiJing" p:street="HuiLongGuan">
    </bean>

    <bean id="car" class="com.stuspring.autowire.Car" p:brand="AuDi" p:price="400000">
    </bean>

    <bean id="car2" class="com.stuspring.autowire.Car" p:brand="AuDi" p:price="400000">
    </bean>
    <bean id="person1" class="com.stuspring.autowire.Person" p:name="Tom" p:address-ref="address" p:car-ref="car"/>

    <!--使用autowire属性指定自动装配的方式 byName 根据bean的id和bean的setter风格属性进行自动装配,如果有匹配的,则自动装配。 byType 根据类型自动装配。car和car2都满足,byType会报错。 确定:不够灵活,实际开发中很少使用自动装配。 -->
    <bean id="person2" class="com.stuspring.autowire.Person" p:name="Lily" autowire="byName">
    </bean>

</beans>

六、Bean之间的关系

6.1 Bean的继承关系

一个Address类,有city和Street 2个属性。

package com.stuspring.relation;

/** * Created by bee on 17/4/25. */
public class Address {

    private String city;
    private String street;
    //省略setter、getter和toString方法
}

配置2个Bean:

  <bean id="address" class="com.stuspring.relation.Address"
          p:city="BeiJing" p:street="WuDaoKou"/>
    <bean id="address2" class="com.stuspring.relation.Address"
          p:city="BeiJing" p:street="XiZhiMen"/>

address2和address除了street属性不一样,其他都相同,可以使用bean的集成属性来简化配置:

    <bean id="address" class="com.stuspring.relation.Address"
          p:city="BeiJing" p:street="WuDaoKou"/>
    <bean id="address2" p:street="XiZhiMen" parent="address"/>
  1. Spring允许继承bean的配置,被继承的bean称为父bean,继承父bean的bean称为子bean。

  2. 子bean从父bean中继承配置,包括bean的属性配置

  3. 子bean也可以覆盖父bean继承过来的配置

  4. 父bean可以作为配置模板,也可以作为bean的实例。若只想把父bean作为模板,可以设置<bean>的abstract属性为true,这样spring就不会实例化这个bean

  5. 可以忽略父bean的class属性,让子bean指定自己的类,共享相同的配置,此时abstract属性必须为true。

抽象bean例子:

    <bean id="address" class="com.stuspring.autowire.Address" p:city="BeiJing" abstract="true"/>

    <bean id="address2" p:street="XiZhiMen" parent="address"/>

<!-- 覆盖父bean的配置-->
    <bean id="address3" p:city="NanJing" p:street="DaFengChang" parent="address"/>

忽略父bean的class属性:


    <bean id="address" p:city="BeiJing^" p:street="XiZhiMen" abstract="true"/>

    <bean id="address2" class="com.stuspring.autowire.Address" parent="address"/>
    <!-- 覆盖父bean的配置-->
    <bean id="address3" class="com.stuspring.autowire.Address" p:city="NanJing" p:street="DaFengChang" parent="address"/>

6.2 Bean的依赖关系

Spring允许用户通过depends-on属性设定bean前置的依赖bean,前置依赖的bean会在本bean实例化之前创建好。

如果前置依赖多个bean,可以通过逗号、空格的方式配置bean的名称。

    <bean id ="car" class="com.stuspring.autowire.Car" p:brand="Ford"
          p:price="200000"/>

    <bean id="person" class="com.stuspring.autowire.Person"
          depends-on="car"/>

bean person依赖car,car不存在person无法实例化。

七、Bean作用域

定义一个bean:

    <bean id="car" class="com.stuspring.autowire.Car"/>

测试:

  ApplicationContext ctx=new ClassPathXmlApplicationContext
                ("beans-scope.xml");
  Car car1= (Car) ctx.getBean("car");
  Car car2= (Car) ctx.getBean("car");
  System.out.println(car1==car2);

打印结果:

true

car1和car2是同一个对象。

把作用域改为prototype:

<bean id="car" class="com.stuspring.autowire.Car" scope="prototype"/>

再次比较car1和car2,运行结果:

false

作用域改成prototype后,car1和car2不再是同一个对象。

在Spring中,可以在<Bean>元素的scope属性里设置Bean的作用域,默认情况下Spring只为每个在IOC容器中声明的Bean创建唯一一个实例,整个IOC容器范围内都能共享该实例。

类别 说明
singleton 在Spring的IOC容器中仅存在一个Bean实例,以单例的方式存在
prototype 每次调用getBean()都会返回一个新的实例
request 每次Http请求都会创建一个Bean,该作用域仅适用于WebApplicationContext属性
session 同一个HTTP SESSION共享一个BEAN,不同的HTTP SESSION使用不同的BEAN。该作用域仅适用于WebApplicationContext属性。

八、使用外部属性文件

配置文件里配置Bean时,有时需要在Bean的配置里混入系统部署的细节信息,比如文件路径、数据源配置信息等,这些部署细节需要和Bean配置相分离。
Spring提供了一个PropertyPlaceholderConfigurer的BeanFactory后置处理器,这个处理器允许用户将Bean配置的部分内容外移到属性文件中。在Bean配置文件里使用形式为${var}的变量,PropertyPlaceholderConfigurer从属性文件里加载属性并使用这些属性来替换变量。

    <bean id="dataSource"
          class="com.mchange.v2.c3p0.ComboPooledDataSource">
        <property name="user" value="root"/>
        <property name="password" value="123456"/>
        <property name="driverClass" value="com.mysql.jdbc.Driver"/>
        <property name="jdbcUrl" value="jdbc:mysql:///blog"/>
    </bean>

测试:

package com.stuspring.properties;

import javax.sql.DataSource;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

/** * Created by bee on 17/4/25. */
public class Main {
    public static void main(String[] args) {
        ApplicationContext ctx=new ClassPathXmlApplicationContext
                ("beans-properties.xml");
        DataSource dataSources= (DataSource) ctx.getBean("dataSource");
        System.out.println(dataSources);
    }
}

resource目录下新建db.properties,写入连接数据库的配置信息:

jdbc.username=root
jdbc.password=123456
jdbc.driverClassName=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/blog?useUnicode=true&characterEncoding=utf-8&zeroDateTimeBehavior=convertToNull

在Spring Bean的配置文件中引入context命名空间。重新配置:

    <bean id="dataSource2" class="com.mchange.v2.c3p0.ComboPooledDataSource" destroy-method="close">
  <property name="user" value="${jdbc.username}"/>
        <property name="password" value="${jdbc.password}"/>
        <property name="driverClass" value="${jdbc.driverClassName}"/>
        <property name="jdbcUrl" value="${jdbc.url}"/>
    </bean>

测试连接是否成功:

 ApplicationContext ctx=new ClassPathXmlApplicationContext
                ("beans-properties.xml");
 DataSource dataSource= (DataSource) ctx.getBean("dataSource");
 DataSource dataSource2= (DataSource) ctx.getBean("dataSource2");
 System.out.println(dataSource);
 System.out.println(dataSource2);
 Connection conn=dataSource.getConnection();
 System.out.println(conn);

你可能感兴趣的:(spring,prototype,外部文件)