核心概念
IoC控制反转
对象的创建控制权由程序转移到外部,这种思想称为控制反转。
使用对象时,由主动new
产生对象转换为由外部提供对象,此过程中对象创建控制权由程序转移到外部,此思想时控制反转。
自己创建对象时,如果后期对象修改了,会导致相应的依赖对象都需要修改,这导致组件间高度耦合,不利于代码的维护和扩展。
Spring
提供了一个容器,称为IoC
容器,用来充当IoC
中的外部。
Ioc
容器负责对象的创建、初始化等一系列工作,被创建或被管理的对象在IoC
容器中统称为Bean
DI 依赖注入
在容器中建立bean
与bean
之间的依赖关系的过程,称为依赖注入
充分解耦
- 使用
IoC
容器管理bean
- 在
IoC
容器内将有依赖关系的bean
进行关系绑定 - 使用对象时不仅可以直接从
IoC
容器中获取,并且获取到的bean
已经绑定了所有的依赖关系
入门案例
IoC案例
老师使用的相关资料:
链接: https://pan.baidu.com/s/1Gwfogj5kbPb9rWjFS0UC5w 提取码: igmb
项目目录结构
dao
:是数据访问对象层,主要负责与数据库进行交互
service
:Service
层位于DAO
层之上,专注于业务逻辑的处理。它组合DAO
层提供的数据操作方法,实现业务规则和流程控制。
通常情况下,Controller
层调用Service
层的方法来处理业务逻辑,Service
层进一步调用DAO
层的方法来执行数据库操作。这样,每一层只关注自己的职责,降低各层之间的耦合度。
App.java
public class BookServiceImpl implements BookService {
//5.删除业务层中使用new的方式创建的dao对象
private BookDao bookDao;
public void save() {
System.out.println("book service save ...");
bookDao.save();
}
//6.提供对应的set方法
public void setBookDao(BookDao bookDao) {
this.bookDao = bookDao;
}
}
配置文件 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.xsd">
<!--1.在pmx.xml导入spring的坐标spring-context,对应版本是5.2.10.RELEASE-->
<!--2.配置bean-->
<!--bean标签标示配置bean
id属性标示给bean起名字
class属性表示给bean定义类型,是实现类-->
<bean id="bookDao" class="com.itheima.dao.impl.BookDaoImpl"/>
<bean id="bookService" class="com.itheima.service.impl.BookServiceImpl">
</bean>
</beans>
DI案例
在上面的案例上进行修改
配置文件 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.xsd">
<!--1.在pmx.xml导入spring的坐标spring-context,对应版本是5.2.10.RELEASE-->
<!--2.配置bean-->
<!--bean标签标示配置bean
id属性标示给bean起名字
class属性表示给bean定义类型,是实现类-->
<bean id="bookDao" class="com.itheima.dao.impl.BookDaoImpl"/>
<bean id="bookService" class="com.itheima.service.impl.BookServiceImpl">
<!--7.配置server与dao的关系-->
<!--property标签表示配置当前bean的属性
name属性表示配置哪一个具体的属性
ref属性表示参照哪一个bean-->
<property name="bookDao" ref="bookDao"/>
</bean>
</beans>
BookServiceImpl.java
package com.itheima.service.impl;
import com.itheima.dao.BookDao;
import com.itheima.service.BookService;
public class BookServiceImpl implements BookService {
//5.删除业务层中使用new的方式创建的dao对象
private BookDao bookDao;
public void save() {
System.out.println("book service save ...");
bookDao.save();
}
//6.提供对应的set方法
public void setBookDao(BookDao bookDao) {
this.bookDao = bookDao;
}
}
bean基础配置
别名
可以通过name
属性给bean
起别名,多个名称之间可以使用空格、逗号或者分号隔开
<bean id="bookDao" name="bookDao2 bookDao3" class="com.itheima.dao.impl.BookDaoImpl"/>
除了通过id
来引用外,还可以通过name
来获取bean
BookDao bookDao = (BookDao) applicationContext.getBean("bookDao2");
bookDao.save();
获取bean无论是通过id还是name获取,如果无法获取到都会抛出NoSuchBeanDefinitionException异常
No bean named ‘bookDao5’ available
作用范围
spring
创建的bean
默认是一个单例的,如果想要非单例模式,需要使用scope
属性
默认为单例模式可以提高性能和资源利用率。业务层对象(Service)、数据层对象(Dao)、工具对象适合交给spring
管理。而封装实体的域对象不适合
bean的实例化
bean
本质上就是对象,创建bean
使用构造方法完成
- 使用
new
的方式来创建,使用的是无参构造方法,无参方法不存在将会抛出BeanCreationException
(常用) - 静态工厂(了解)
- 实例工厂(了解)
- 使用
factionBean
实例化(使用)
BookDaoFactoryBean.java
public class BookDaoFactoryBean implements FactoryBean<BookDao> {
// 代替原始实例话工厂创建对象的方法,这里是BookDao范围更广
@Override
public BookDao getObject() throws Exception {
return new BookDaoImpl();
}
@Override
public Class<?> getObjectType() {
return BookDao.class;
}
// 指定创建的方式,是否为单例
@Override
public boolean isSingleton() {
return true;
}
}
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.xsd">
<!-- 使用 factoryBean实例化bean-->
<bean id="bookDao" class="com.itheima.factory.BookDaoFactoryBean"></bean>
</beans>
App.java
public class App {
public static void main(String[] args) {
// 3、获取IoC容器,名称刚好是与配置文件一样
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
// 4、获取bean
BookDao bookDao = (BookDao) applicationContext.getBean("bookDao");
bookDao.save();
}
}
bean生命周期
方式一
BookDaoImpl.java
public class BookDaoImpl implements BookDao {
public void save() {
System.out.println("book dao save ...");
}
// 初始化方法
public void init() {
System.out.println("init...");
}
// 销毁方法
public void destroy() {
System.out.println("destory...");
}
}
applicationContext.xml
<bean id="bookDao" class="com.itheima.dao.impl.BookDaoImpl" init-method="init" destroy-method="destroy" />
App.java
public class App {
public static void main(String[] args) {
ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
BookDao bookDao = (BookDao) applicationContext.getBean("bookDao");
bookDao.save();
// 容器关闭
applicationContext.registerShutdownHook();
}
}
方式二(了解)
使用spring
接口方式
BookDaoImpl.java
public class BookDaoImpl implements BookDao, InitializingBean, DisposableBean {
public void save() {
System.out.println("book dao save ...");
}
@Override
public void destroy() throws Exception {
System.out.println("book dao destroy ...");
}
@Override
public void afterPropertiesSet() throws Exception {
System.out.println("book dao init ...");
}
}
applicationContext.xml
<bean id="bookDao" class="com.itheima.dao.impl.BookDaoImpl" />
App.java
public class App {
public static void main(String[] args) {
ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
BookDao bookDao = (BookDao) applicationContext.getBean("bookDao");
bookDao.save();
applicationContext.close();
}
}