- 配置形式:基于 XML 文件的方式;基于注解的方式
- Bean 的配置方式:通过全类名(反射)、通过工厂方法(静态工厂方法 & 实例工厂方法)、FactoryBean
- IOC 容器 BeanFactory & ApplicationContext 概述
- 依赖注入的方式:属性注入;构造器注入
- 注入属性值细节
- 自动转配
- bean 之间的关系:继承;依赖
- bean 的作用域:singleton;prototype;WEB 环境作用域
- 使用外部属性文件
- spEL
- IOC 容器中 Bean 的生命周期
- 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);
}
}