1. 核心概念
1.1 IOC(Inversion of Control),控制反转
1.2 Spring与IOC的关系
- Spring技术对IOC思想进行了实现
-
Spring 提供了一个容器,称为 IOC 容器 ,用来充当 IOC 思想中的 " 外部 "
-
IOC 思想中的“ 外部” 指的就是 Spring 的 IOC容器
1.3 IOC容器的作用
- IOC容器负责对象的创建、初始化等一系列工作,其中包含了数据层和业务层的类对象
-
被创建或被管理的对象在 IOC 容器中统称为 Bean
-
IOC 容器中放的就是一个个的 Bean 对象
1.4 DI(Dependency Inject),依赖注入
2. 配置文件
要确定生成哪些bean以及建立bean与bean之间的依赖关系,可以通过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,
bean的id属性唯一,也可以加别名name,name属性唯一
class属性表示生成该bean的类
scope属性表示bean的作用范围,默认值是singleton,表示单例的,每次获取到的都是同一个对象。prototype表示非单例的,每次获取到的都是新的对象 -->
<bean id="bookDao" class="com.lan.dao.impl.BookDaoImpl" scope="singleton"/>
<bean id="bookService" class="com.lan.service.impl.BookServiceImpl">
<!--property标签表示配置当前bean的属性
name属性表示配置哪一个具体的属性
ref属性表示引用哪一个bean,或者说注入哪个bean,其值可以是被引用的bean的id或name
注意,com.lan.service.impl.BookServiceImpl要提供对应的setter方法-->
<property name="bookDao" ref="bookDao"/>
<property name="name" value="hello, world"/>
</bean>
</beans>
bean标签用来定义bean,bean的id属性唯一,class属性标识该bean对应的类,scope属性表示bean的作用范围,默认值是singleton,表示单例的,每次获取到的都是同一个对象。prototype表示非单例的,每次获取到的都是新的对象。
bean/property标签,标识该bean需要注入的属性,name是属性名,ref是引用类型的注入,value是非引用类型的注入。
bean/contructor-arg标签,
3. 初始化IOC容器
App
package com.lan;
import com.lan.dao.BookDao;
import com.lan.service.BookService;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class App {
public static void main(String[] args) {
// 初始化IOC容器,创建xml中定义的bean,并处理依赖注入
ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
// 从IOC容器中获取id为bookDao的bean
BookDao bookDao = (BookDao) ctx.getBean("bookDao");
// 从IOC容器中获取id为bookService的bean
BookService bookService = (BookService) ctx.getBean("bookService");
}
}
BookServiceImpl
package com.lan.service.impl;
import com.lan.dao.BookDao;
import com.lan.service.BookService;
public class BookServiceImpl implements BookService {
private BookDao bookDao;
private String name;
public void save() {
System.out.println("book service save ...");
bookDao.save();
}
// 提供对应的setter方法
public void setBookDao(BookDao bookDao) {
this.bookDao = bookDao;
}
public void setName(String name) {
this.name = name;
}
}
注意,上面提供了要被注入的属性的setter方法,对应xml的bean/property标签,去掉setter方法会注入失败。当然还可以通过构造方法传参的方式进行注入,对应bean/constructor-arg标签。
4. 依赖注入的方式
上面也提到了,依赖注入有两种方式:
- setter方式,对应xml的bean/property标签
- 构造方法方法,对应bean/constructor-arg标签
另外,也可以不填写bean/property或者bean/construct-arg,直接根据类型进行自动注入
<!--autowire属性:开启自动装配,通常使用按类型装配-->
<bean id="bookService" class="com.lan.service.impl.BookServiceImpl" autowire="byType"/>
5. bean的实例化方式
5.1 构造方法的方式
构造方法是bean的默认实例化方式,也是常用的方式
<bean id="bookDao" class="com.lan.dao.impl.BookDaoImpl"/>
5.2 静态工厂的方式
该方式可以友好兼容其它类型的IOC容器
<!-- factory-method指定调用静态工厂类的哪个方法实例化所需要的bean -->
<bean id="orderDao" class="com.lan.factory.OrderDaoFactory" factory-method="getOrderDao"/>
5.3 实例工厂的方式
<bean id="userFactory" class="com.lan.factory.UserDaoFactory"/>
<!-- factory-bean指定实例工厂bean -->
<bean id="userDao" factory-method="getUserDao" factory-bean="userFactory"/>
5.4 FactoryBean方式
<!-- com.lan.factory.UserDaoFactoryBean实现了FactoryBean接口 -->
<bean id="userDao" class="com.lan.factory.UserDaoFactoryBean"/>
UserDaoFactoryBean
package com.lan.factory;
import com.lan.dao.UserDao;
import com.lan.dao.impl.UserDaoImpl;
import org.springframework.beans.factory.FactoryBean;
public class UserDaoFactoryBean implements FactoryBean<UserDao> {
public UserDao getObject() throws Exception {
return new UserDaoImpl();
}
public Class<?> getObjectType() {
return UserDao.class;
}
}
6. bean的生命周期
<!--init-method:设置bean初始化生命周期回调函数-->
<!--destroy-method:设置bean销毁生命周期回调函数,仅适用于单例对象-->
<bean id="bookDao" class="com.itheima.dao.impl.BookDaoImpl" init-method="init" destroy-method="destory"/>
另外,bean可以实现InitializingBean接口来代替init-method配置,实现DisposableBean接口来代替destroy-method配置
7. 加载Properties文件
<!--
classpath:jdbc.properties 表示加载当前工程或者当前jar的类路径下的jdbc.properties
classpath*:*.properties 表示加载当前工程类路径和当前工程所依赖的所有jar包中的所有properties文件
-->
<context:property-placeholder location="classpath*:*.properties"/>
<bean id="bookDao" class="com.lan.dao.impl.BookDaoImpl">
<property name="name" value="${username}"/>
</bean>
配置<context:property-placeholder>,然后在bean/property的value属性,用${变量名}的方式引用。
注意,若有同名的系统变量,会优先使用系统变量,<context:property-placeholder>增加属性system-properties-mode="NEVER"可以屏蔽系统变量