Spring 学习(三)——Spring 中的 Bean 配置

  1. 配置形式:基于 XML 文件的方式;基于注解的方式
  2. Bean 的配置方式:通过全类名(反射)、通过工厂方法(静态工厂方法 & 实例工厂方法)、FactoryBean
  3. IOC 容器 BeanFactory & ApplicationContext 概述
  4. 依赖注入的方式:属性注入;构造器注入
  5. 注入属性值细节
  6. 自动转配
  7. bean 之间的关系:继承;依赖
  8. bean 的作用域:singleton;prototype;WEB 环境作用域
  9. 使用外部属性文件
  10. spEL
  11. IOC 容器中 Bean 的生命周期
  12. Spring 4.x 新特性:泛型依赖注入

Spring 容器

Spring IOC 容器读取 Bean 配置创建 Bean 实例之前, 必须对它进行实例化. 只有在容器实例化后, 才可以从 IOC 容器里获取 Bean 实例并使用.

Spring 提供了两种类型的 IOC 容器实现.

BeanFactory: IOC 容器的基本实现.

ApplicationContext: 提供了更多的高级特性. BeanFactory 的子接口.

BeanFactory Spring 框架的基础设施,面向 Spring 本身;ApplicationContext 面向使用 Spring 框架的开发者,几乎所有的应用场合都直接使用 ApplicationContext 而非底层的 BeanFactory

无论使用何种方式, 配置文件时相同的.

ApplicationContext

ApplicationContext 的主要实现类:

ClassPathXmlApplicationContext类路径下加载配置文件

FileSystemXmlApplicationContext: 从文件系统中加载配置文件

ConfigurableApplicationContext 扩展于 ApplicationContext,新增加两个主要方法:refresh() close(), 让 ApplicationContext 具有启动、刷新和关闭上下文的能力

ApplicationContext 在初始化上下文时就实例化所有单例的 Bean

WebApplicationContext 是专门为 WEB 应用而准备的,它允许从相对于 WEB 根目录的路径中完成初始化工作

依赖注入的方式

Spring 支持 3 种依赖注入的方式

  • 属性注入
  • 构造器注入
  • 工厂方法注入(很少使用,不推荐)

1、属性注入

  • 属性注入即通过 setter 方法注入Bean 的属性值或依赖的对象
  • 属性注入使用 <property> 元素, 使用 name 属性指定 Bean 的属性名称,value 属性或 <value> 子节点指定属性值
  • 属性注入是实际应用中最常用的注入方式
<!--
    通过全类名的方式来配置 bean
    class: bean 的全类名,通过反射的方式在 IOC 容器中创建 Bean ,
    所以要求 Bean 中必须有无参的构造器
    id: 标识容器中的 bean ,id 在 IOC 容器中必须是唯一的
        若 id 没有指定,Spring 自动将权限定性类名作为 Bean 的名字
        id 可以指定多个名字,名字之间可用逗号、分号、或空格分隔
-->
<bean id="helloWorld" class="com.hzyc.spring.bean.HelloWorld">
    <property name="name" value="薛恒杰"/>
</bean>

2、构造方法注入

  • 通过构造方法注入Bean 的属性值或依赖的对象,它保证了 Bean 实例在实例化后就可以使用。
  • 构造器注入在 <constructor-arg> 元素里声明属性, <constructor-arg> 中没有 name 属性
  • 按索引匹配入参,按类型匹配入参
<!--通过构造方法来配置 bean 的属性-->
<bean id="car" class="com.hzyc.spring.bean.Car">
    <constructor-arg index="0" value="奥迪"/>
    <constructor-arg index="1" value="上海"/>
    <constructor-arg type="double" value="400000"/>
</bean>

<!--使用构造器注入属性值可以指定参数的位置和参数的类型,以区分重载的构造器-->
<bean id="car2" class="com.hzyc.spring.bean.Car">
    <constructor-arg index="0" type="java.lang.String" value="宝马"/>
    <constructor-arg index="1" type="java.lang.String" value="上海"/>
    <constructor-arg index="2" type="int" value="240"/>
</bean>

代码示例如下:

1、文件结构

2、spring-config.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
        class: bean 的全类名,通过反射的方式在 IOC 容器中创建 Bean ,
        所以要求 Bean 中必须有无参的构造器
        id: 标识容器中的 bean ,id 在 IOC 容器中必须是唯一的
            若 id 没有指定,Spring 自动将权限定性类名作为 Bean 的名字
            id 可以指定多个名字,名字之间可用逗号、分号、或空格分隔
    -->
    <bean id="helloWorld" class="com.hzyc.spring.bean.HelloWorld">
        <property name="name" value="薛恒杰"/>
    </bean>

    <!--通过构造方法来配置 bean 的属性-->
    <bean id="car" class="com.hzyc.spring.bean.Car">
        <constructor-arg index="0" value="奥迪"/>
        <constructor-arg index="1" value="上海"/>
        <constructor-arg type="double" value="400000"/>
    </bean>

    <!--使用构造器注入属性值可以指定参数的位置和参数的类型,以区分重载的构造器-->
    <bean id="car2" class="com.hzyc.spring.bean.Car">
        <constructor-arg index="0" type="java.lang.String" value="宝马"/>
        <constructor-arg index="1" type="java.lang.String" value="上海"/>
        <constructor-arg index="2" type="int" value="240"/>
    </bean>
</beans>

3、HelloWorld.java

package com.hzyc.spring.bean;

/**
 * @author xuehj2016
 * @Title: HelloWorld
 * @ProjectName spring01
 * @Description: TODO
 * @date 2018/12/1617:59
 */
public class HelloWorld {
    private String name;

    public HelloWorld() {
        System.out.println("HelloWorld's Constructor...");
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        System.out.println("setName:" + name);
        this.name = name;
    }

    public void hello() {
        System.out.println("hello:" + name);
    }
}

Car.java

package com.hzyc.spring.bean;

/**
 * @author xuehj2016
 * @Title: Car
 * @ProjectName spring01
 * @Description: TODO
 * @date 2018/12/1620:06
 */
public class Car {
    private String brand;
    private String place;
    private double price;
    private int maxSpeed;

    public Car(String brand, String place, double price) {
        this.brand = brand;
        this.place = place;
        this.price = price;
    }

    public Car(String brand, String place, int maxSpeed) {
        this.brand = brand;
        this.place = place;
        this.maxSpeed = maxSpeed;
    }

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

4、测试类Main.java

package com.hzyc.spring.bean;

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

/**
 * @author xuehj2016
 * @Title: Main
 * @ProjectName spring01
 * @Description: TODO
 * @date 2018/12/1618:01
 */
public class Main {
    public static void main(String[] args) {
        /*
        //创建 HelloWorld 的一个对象
        HelloWorld helloWorld = new HelloWorld();
        //给 name 属性赋值
        helloWorld.setName("薛恒杰");
        //调用 hello 方法
        helloWorld.hello();
        */

        //1.创建 Spring 的 IOC 容器对象
        //ApplicationContext 代表 IOC 容器
        //ClassPathXmlApplicationContext: 是 ApplicationContext 接口的实现类,该实现类从类路径下来加载配置文件
        ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring-config.xml");
        //2.从 IOC 容器中获取 Bean 实例
        //利用 id 定位到 IOC 容器中的 bean
        HelloWorld helloWorld = (HelloWorld) applicationContext.getBean("helloWorld");

        //利用类型返回 IOC 容器中的 bean ,但要求 IOC 容器中必须只能有一个该类型的 Bean
        //HelloWorld helloWorld = applicationContext.getBean(HelloWorld.class);

        //3.调用 hello 方法
        helloWorld.hello();

        Car car= (Car) applicationContext.getBean("car");
        System.out.println(car);

        Car car2= (Car) applicationContext.getBean("car2");
        System.out.println(car2);
    }
}

猜你喜欢

转载自blog.csdn.net/weixin_41577923/article/details/85040105