Spring入门-笔记02-IoC容器
目录
- IoC概述
- Bean的生命周期
- 配置IoC
1. IoC概述
Spring框架的核心功能是控制反转(IoC),面向切面编程AOP和声明式事务管理等功能都依赖于IoC。
IoC,即通过容器来控制业务对象之间的依赖关系,而非传统实现中的通过代码直接操控,即控制权由应用代码转移到了外部容器,控制权的转移就是反转。
为实现IoC功能,Spring提供了两个访问接口
-
BeanFactory:
BeanFactory是Spring IoC容器的核心接口,是制造Bean的工厂,用于向使用者提供Bean的实例。其主要功能是完成容器管理对象的实例化,并根据预定的配置完成对象之间依赖关系的组装,最终向使用者提供已装配的可用对象。
-
ApplicationContext:
ApplicationContext是BeanFactory的子接口,代表一个应用的上下文,在BeanFactory的基础知识,提供了更多的实用功能。如Bean的生命周期管理,框架事件体系,国际化支持等功能。
BeanFactory初始化 和 ApplicationContext初始化的区别
-
BeanFactory初始化容器时,并未实例化Bean,直到第一次访问某个Bean时才实例化目标Bean。
-
ApplicationContext初始化上下文时,实例化所有单实例Bean。
2. Bean的生命周期
3. 配置IoC
有XML文件和java注解两种方式来配置IoC。
XML文件方式
- 在resources文件夹中创建applicationContext.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-2.0.xsd">
</beans>
- 创建pojo类,在配置文件中添加bean元素
User.java
package com.chapter08.bean;
public class User {
private int id;
private String username;
private String password;
public User() {
}
public User(int id, String username, String password) {
this.id = id;
this.username = username;
this.password = password;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
}
applicationContext.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-2.0.xsd">
<bean class="com.chapter08.bean.User" id="user">
</bean>
</beans>
- id:id属性确定该Bean的唯一标识符,容器对bean的管理和访问以及该bean的依赖关系,都通过该属性完成。在java代码中通过getBean(“名称”)的方法即可获取相应的Bean。
- class:class属性指定该Bean的具体实现类,
- property标签:为属性赋值,其中id对应javaBean的属性,value为要赋予的值
配置依赖注入
依赖注入和控制反转是同一个概念,都是为了处理对象间的依赖关系。
两种注入方式:
- setter方法注入
<?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-2.0.xsd">
<!-- ======================= 依赖注入 ====================== -->
<!--setter方式注入-->
<bean class="com.chapter08.bean.User" id="user">
<property name="id" value="1"/>
<property name="username" value="AlanLee"/>
<property name="password" value="123456"/>
</bean>
</beans>
- 构造方法注入
<?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-2.0.xsd">
<!-- ======================= 依赖注入 ====================== -->
<!--构造方法方式注入-->
<bean class="com.chapter08.bean.User" id="user2">
<constructor-arg name="id" value="1"/>
<constructor-arg name="username" value="AlanLee"/>
<constructor-arg name="password" value="123456"/>
</bean>
</beans>
两种注入方式的对比
- setter方法注入比较直观,自然,易懂
- 构造方法注入可以决定注入的顺序,但注入复杂的关系时显得臃肿,难以阅读。
注入值类型
有三种注入值类型:字面值,其他Bean的引用,集合类型。
Order.java
public class Order {
private int id;
private String orderNo;
private double amount;
//测试其他Bean的引用
private OrderItem orderItem;
//省略setter/getter方法
}
OrderItem.java
package com.chapter08.bean;
public class OrderItem {
private int id;
private String product;
private float price;
private int count;
//省略setter/getter方法
}
- 字面值类型
字面值一般是指可用字符串表示的值,默认情况下,基本数据类型及其封装类、String等类型都可以采取字面值方式注入。
<!-- 字面值方式 -->
<bean class="com.chapter08.bean.Order" id="order">
<constructor-arg name="id" value="100"/>
<constructor-arg name="orderNo" value="ABCDEF"/>
<constructor-arg name="amount" value="222.33"/>
</bean>
- 其他Bean的引用
如果Bean需要注入的属性是对象类型,则可以通过<ref>
元素或者ref属性注入
<!-- 字面值方式 -->
<bean class="com.chapter08.bean.Order" id="order">
<constructor-arg name="id" value="100"/>
<constructor-arg name="orderNo" value="ABCDEF"/>
<constructor-arg name="amount" value="222.33"/>
<!--其他Bean的引用-->
<property name="orderItem" ref="orderItem"/>
</bean>
<!--测试 其他Bean的引用 在Order中引用这个bean-->
<bean class="com.chapter08.bean.OrderItem" id="orderItem">
<property name="id" value="1"/>
<property name="product" value="电视机"/>
<property name="price" value="6000"/>
<property name="count" value="1"/>
</bean>
- 集合类型
使用<array>,<list>,<set>,<map><props>
元素分别设置类型为数组、List、Set、Map和Properties的集合属性。
Order2.java
public class Order2 {
private int id;
private String orderNo;
private double amount;
//测试其他Bean的引用
private OrderItem orderItem;
//测试集合类型注入
private Object[] myArray;
private List<?> myList;
private Set<?> mySet;
private Map<?,?> myMap;
private Properties myProp;
//省略setter/getter方法
}
<!--测试集合类型注入-->
<bean class="com.chapter08.bean.Order2" id="order2">
<constructor-arg name="id" value="100"/>
<constructor-arg name="orderNo" value="ABCDEF"/>
<constructor-arg name="amount" value="222.33"/>
<!--其他Bean的引用-->
<!-- <property name="orderItem" ref="orderItem"/>-->
<!--测试集合类型注入-->
<property name="myArray">
<array>
<value>1234</value>
<ref bean="orderItem"/>
</array>
</property>
<property name="myList">
<list>
<value>1234</value>
<ref bean="orderItem"/>
</list>
</property>
<property name="mySet">
<set>
<value>1234</value>
<ref bean="orderItem"/>
</set>
</property>
<property name="myMap">
<map>
<entry key="1" value="1234"/>
<entry key="2" value-ref="orderItem"/>
</map>
</property>
<property name="myProp">
<props>
<prop key="aaa">AAA</prop>
<prop key="bbb">BBB</prop>
</props>
</property>
</bean>
Bean之间的关系
- 继承
添加parent属性
<bean id="user2" parent="user"/>
这里的继承不是java中类的继承,而是继承有相同属性的bean
- 依赖
添加depend-on属性
<bean id="userDao" class="xxx.xxx.UserDao"/>
<bean id="userService" class="xxx.xxx.UserService" depend-on="userDao"/>
构造userService时,需要先构造userDao。
Bean的作用域
Bean的作用域通过scope属性完成
Spring支持5中Bean的作用域
介绍常用的作用域:
- singleton
singleton作用域用于提供单实例的Bean对象,只创建一个该Bean对象的实例,这个唯一实例会被缓存起来,当有请求使用时,直接返回该实例,不会创建新的实例。
<!--singleton作用域-->
<bean class="com.chapter08.bean.Order" id="order" scope="singleton">
Bean的默认作用域就是singleton
- prototype
prototype作用域用于向请求者每次请求提供新实例。
<!--prototype作用域-->
<bean class="com.chapter08.bean.Order" id="order" scope="prototype">
由于频繁的创建和销毁实例会带来很大的开销,所以尽量不使用prototype作用域。
自动装配
自动装配就是我们在不使用和注入数据的情况下,Spring容器自动装配相互协作的bean 的关系
这种方式可以有效减少配置文件的体积
<bean class="com.chapter08.bean.Order" id="order" autowire="装配方式">
有5种自动装配方式:
- no:不使用自动装配
- byName:当我们这么设置时,Spring 容器会扫描xml配置文件,根据java bean中那个引用类型的参数名称类查找xml配置中是否有符合的名字相同bean配置,找到就注入到该参数;
- byType:从Spring环境中获取目标对象时,目标对象中的属性会根据类型在整个spring环境中查找标签的class属性值。如果有相同的,那么获取这个对象,实现关联。
- constructor:根据javaBean的构造函数去匹配xml中的一个bean,尝试去寻找匹配项;也不受名称限制
- autodetect:通过Bean类的自省机制来决定使用constructor还是byType方式进行自动装配。