# 概要
- IOC & DI 概述
- 配置 bean
- 配置形式:基于 XML 文件的方式;基于注解的方式
- Bean 的配置方式:通过全类名(反射)、通过工厂方法(静态工厂方法 & 实例工厂方法)、FactoryBean
- IOC 容器 BeanFactory & ApplicationContext - - 概述
- 依赖注入的方式:属性注入;构造器注入
- 注入属性值细节
- 自动转配
- bean 之间的关系:继承;依赖
- bean 的作用域:singleton;prototype;WEB 环境作用域
- 使用外部属性文件
- spEL
- IOC 容器中 Bean 的生命周期
- Spring 4.x 新特性:泛型依赖注入
IOC 和 DI
- IOC(Inversion of Control):其思想是反转资源获取的方向. 传统的资源查找方式要求组件向容器发起请求查找资源. 作为回应, 容器适时的返回资源. 而应用了 IOC 之后, 则是容器主动地将资源推送给它所管理的组件, 组件所要做的仅是选择一种合适的方式来接受资源. 这种行为也被称为查找的被动形式
- DI(Dependency Injection) — IOC 的另一种表述方式:即组件以一些预先定义好的方式(例如: setter 方法)接受来自如容器的资源注入. 相对于 IOC 而言,这种表述更直接
具体设计
Car 类设计
package www.xq.spring.beans;
public class Car {
private String brand;
private String crop;
private double price;
private int maxSpeed;
public Car(String brand, String crop, double price) {
super();
this.brand = brand;
this.crop = crop;
this.price = price;
}
public Car(String brand, String crop, int maxSpeed) {
super();
this.brand = brand;
this.crop = crop;
this.maxSpeed = maxSpeed;
}
public String toString() {
return "Car [brand=" + brand + ", crop=" + crop + ", price=" + price
+ ", maxSpeed=" + maxSpeed + "]";
}
public void setPrice(double price) {
this.price = price;
}
public void setMaxSpeed(int maxSpeed) {
this.maxSpeed = maxSpeed;
}
}
Person 类设计
package www.xq.spring.beans;
public class Person {
private String name;
private int age;
private Car car;
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 Car getCar() {
return car;
}
public void setCar(Car car) {
this.car = car;
}
public String toString() {
return "Person [name=" + name + ", age=" + age + ", car=" + car + "]";
}
public Person() {
super();
}
public Person(String name, int age, Car car) {
super();
this.name = name;
this.age = age;
this.car = car;
}
}
Spring 配置文件 applicationContext.xml
<!-- 配置 bean class:bean 的全类名,通过反射的方式在 IOC 容器中创建 Bean.所以要求 Bean 中必须有无参数的构造器
id:标识容器中的 bean.id 唯一. -->
<!-- 通过构造方法来配置 bean 的属性 -->
<bean id="car" class="www.xq.spring.beans.Car">
<constructor-arg value="Audi" index="0"></constructor-arg>
<constructor-arg value="ShangHai" type="java.lang.String"></constructor-arg>
<constructor-arg value="500000" type="double"></constructor-arg>
</bean>
<!-- 使用构造器注入属性值可以指定参数的位置和参数的类型!以区分重载的构造器! -->
<bean id="car2" class="www.xq.spring.beans.Car">
<constructor-arg value="BaoMa" type="java.lang.String"></constructor-arg>
<!-- 如果字面上包含特殊字符可以使用 <![CDATA[]]> 包裹起来 -->
<!-- 属性值也可以使用 value 子节点进行配置 -->
<constructor-arg index="1">
<value><![CDATA[<shanghai^>]]></value>
</constructor-arg>
<constructor-arg type="int">
<value>250</value>
</constructor-arg>
</bean>
<bean id="person" class="www.xq.spring.beans.Person">
<property name="name" value="Tom"></property>
<property name="age" value="24"></property>
<!-- 可以使用 property 的 ref 属性建立 bean 之间的引用关系 -->
<!-- <property name="car" ref="car2"></property> -->
<!-- <property name="car"> <ref bean="car2"/> </property> -->
<!-- 内部 bean,不能被外部引用. 只能在内部使用 -->
<property name="car">
<bean class="www.xq.spring.beans.Car">
<constructor-arg value="Ford"></constructor-arg>
<constructor-arg value="Changan"></constructor-arg>
<constructor-arg value="200000" type="double"></constructor-arg>
</bean>
</property>
<property name="car.maxSpeed" value="260"></property>
</bean>
<bean id="person2" class="www.xq.spring.beans.Person">
<constructor-arg value="Jerry"></constructor-arg>
<constructor-arg value="25"></constructor-arg>
<!-- <constructor-arg ref="car"></constructor-arg> -->
<!-- 测试赋值 null -->
<!-- 可以自己测试 -->
<!-- <constructor-arg><null/></constructor-arg> -->
<constructor-arg ref="car"></constructor-arg>
<!-- 为级联属性赋值. 注意:属性需要先初始化后才可以为级联属性赋值.否则会有异常,和 Struts2不同. -->
<property name="car.maxSpeed" value="300"></property>
</bean>
main 函数设计
public static void main(String[] args) {
// 1. 创建 Sring 的 IOC 容器对象
// ApplicationContext 代表 IOC 容器
// ClassPathXmlApplicationContext:是 ApplicationContext 接口的实现类.该实现类从类路径下来加载配置文件.
ApplicationContext ctx = new ClassPathXmlApplicationContext(
"applicationContext.xml");
// 2. 从 IOC 容器中获取 Bean 实例
//利用 id 定位到 IOC 容器中的 bean
Car car = (Car) ctx.getBean("car");
System.out.println(car);
//利用类型返回 IOC 容器中的 Bean,但要求 IOC 容器中必须只能有一个该类型的 Bean
car = (Car) ctx.getBean("car2");
System.out.println(car);
Person person = (Person) ctx.getBean("person");
System.out.println(person);
person = (Person) ctx.getBean("person2");
System.out.println(person);
}
学习总结
基本内容
- BeanFactory:IOC 容器的基本实现.
- ApplicationContext: 提供了更多的高级特性. 是 BeanFactory 的子接口.
- BeanFactory 是 Spring 框架的基础设施,面向 Spring 本身;ApplicationContext 面向使用 Spring 框架的开发者,几乎所有的应用场合都直接使用 ApplicationContext 而非底层的 BeanFactory
- 配置 bean class:bean 的全类名,通过反射的方式在 IOC 容器中创建 Bean.所以要求 Bean 中必须有无参数的构造器
id:标识容器中的 bean.id 唯一.
依赖注入的方式
- 依赖注入
-
属性注入
- 属性注入即通过 setter 方法注入Bean 的属性值或依赖的对象
- 属性注入使用 元素, 使用 name 属性指定 Bean 的属性名称,value 属性或 子节点指定属性值
- 属性注入是实际应用中最常用的注入方式
-
构造器注入
- 通过构造方法注入Bean 的属性值或依赖的对象,它保证了 Bean 实例在实例化后就可以使用。
- 构造器注入在 元素里声明属性, 中没有 name 属性
-