Spring随笔
Spring随笔
视频是黑马的SSM教程,传送门,记录些知识点,主要是概念及使用,本篇不涉及源码相关。
1. Spring核心概念
Spring核心概念这部分内容中主要包含IOC/DI、IOC容器和Bean。
1.1 提出概念前,项目中的问题?
(1)业务层需要调用数据层的方法,就需要在业务层new数据层的对象
(2)如果数据层的实现类发生变化,那么业务层的代码也需要跟着改变,发生变更后,都需要进行编译打包和重部署
(3)所以,现在代码在编写的过程中存在的问题是:耦合度偏高
针对这个问题,该如何解决呢?
我们就想,如果能把框中的内容给去掉,不就可以降低依赖了么,但是又会引入新的问题,去掉以后程序能运行么?
答案肯定是不行,因为bookDao没有赋值为Null,强行运行就会出空指针异常。
所以现在的问题就是,业务层不想new对象,运行的时候又需要这个对象,该咋办呢?
针对这个问题,Spring就提出了一个解决方案:
- 使用对象时,在程序中不要主动使用new产生对象,转换为由外部提供对象
这种实现思就是Spring的一个核心概念
1.2 IOC、IOC容器、Bean、DI概念
1.2.1 IOC(Inversion of Control)控制反转
(1) 什么是控制反转呢?
使用对象时,由主动new产生对象转换为由外部提供对象,此过程中对象创建控制权由程序转移到外部,此思想称为控制反转。
- 控制 :指的是对象创建(实例化、管理)的权力
- 反转 :控制权交给外部环境(Spring 框架、IoC 容器)
(2) IOC容器的作用以及内部存放的是什么?
- IOC容器类似于一个工厂,负责对象的创建、初始化等一系列工作
- 被创建或被管理的对象在IOC容器中统称为Bean
- IOC容器中放的就是一个个的Bean对象
在 Spring 中, IoC 容器是 Spring 用来实现 IoC 的载体, IoC 容器实际上就是个 Map(key,value),Map 中存放的是各种对象。
1.2.2 DI(Dependency Injection)依赖注入
(1) 什么是依赖注入呢?
在容器中建立bean与bean之间的依赖关系的整个过程,称为依赖注入。
(2) IOC容器中的Bean需要根据具体的业务来建立关系
IOC和DI的目的就是充分解耦
- 使用IOC容器管理bean(IOC)
- 在IOC容器内将有依赖关系的bean进行关系绑定(DI)
- 最终结果为:使用对象时不仅可以直接从IOC容器中获取,并且获取到的bean已经绑定了所有的依 赖关系.
1.2.3 小结
(1) 什么IOC/DI思想?
- IOC:控制反转,控制反转的是对象的创建权
- DI:依赖注入,绑定对象与对象之间的依赖关系
(2) 什么是IOC容器?
Spring创建了一个容器用来存放所创建的对象,这个容器就叫IOC容器
(3) 什么是Bean?
容器中所存放的一个个对象就叫Bean或Bean对象
1.3 IOC相关
1.3.1 bean的基础配置
1 | <bean |
1.3.2 bean的实例化
Spring的IOC实例化对象的三种方式:
- 构造方法:底层用的是反射
- 静态工厂
- 实例工厂
- FactoryBean
1.实例工厂的步骤:
(1) 配置:
1 | <bean id="userFactory" class="com.itheima.factory.UserDaoFactory"/> |
(2) 创建实例化工厂对象,对应第一行配置;调用对象中的方法来创建bean,对应第二行的配置
其中,factory-bean是工厂的实例对象;factory-method是工厂对象中的具体创建对象的方法名
2.FactoryBean的步骤:
实现FactoryBean接口,重写接口方法:
1 | public class UserDaoFactoryBean implements FactoryBean<UserDao> { |
配置:
1 | <bean id="userDao" class="com.itheima.factory.UserDaoFactoryBean"/> |
FactoryBean接口有三个方法:
1 | // 被重写后,会创建对象并返回 |
1.3.3 bean的生命周期
- Bean 容器找到配置文件中 Spring Bean 的定义。
- Bean 容器利用 Java Reflection API 创建一个 Bean 的实例。
- 如果涉及到一些属性值 利用
set()
方法设置一些属性值。 - 如果 Bean 实现了
BeanNameAware
接口,调用setBeanName()
方法,传入 Bean 的名字。 - 如果 Bean 实现了
BeanClassLoaderAware
接口,调用setBeanClassLoader()
方法,传入ClassLoader
对象的实例。 - 如果 Bean 实现了
BeanFactoryAware
接口,调用setBeanFactory()
方法,传入BeanFactory
对象的实例。 - 与上面的类似,如果实现了其他
*.Aware
接口,就调用相应的方法。 - 如果有和加载这个 Bean 的 Spring 容器相关的
BeanPostProcessor
对象,执行postProcessBeforeInitialization()
方法 - 如果 Bean 实现了
InitializingBean
接口,执行afterPropertiesSet()
方法。 - 如果 Bean 在配置文件中的定义包含 init-method 属性,执行指定的方法。
- 如果有和加载这个 Bean 的 Spring 容器相关的
BeanPostProcessor
对象,执行postProcessAfterInitialization()
方法 - 当要销毁 Bean 的时候,如果 Bean 实现了
DisposableBean
接口,执行destroy()
方法。 - 当要销毁 Bean 的时候,如果 Bean 在配置文件中的定义包含 destroy-method 属性,执行指定的方法。
1.3.4 核心容器总结
-
容器相关
- BeanFactory是IoC容器的顶层接口,初始化BeanFactory对象时,加载的bean延迟加载
- ApplicationContext接口是Spring容器的核心接口,初始化时bean立即加载
- ApplicationContext接口提供基础的bean操作相关方法,通过其他接口扩展其功能
- ApplicationContext接口常用初始化类:ClassPathXmlApplicationContext(常用)、FileSystemXmlApplicationContext
-
bean相关
1.4 DI相关
两种注入方式:setter注入和构造器注入;两种数据类型:简单类型和引用类型。
1.4.1 setter注入
对于引用数据类型使用:
1 | <bean ...> |
对于简单数据类型使用:
1 | <bean ...> |
1.4.2 构造器注入
对于引用类型:
1 | <bean id="bookService" class="com.itheima.service.impl.BookServiceImpl"> |
对于简单类型:
1 | <bean id="bookDao" class="com.itheima.dao.impl.BookDaoImpl"> |
两个constructor-arg
的顺序可以任意。
如果参数类型重复,可以通过配置index属性,来确认顺序:
1 | <bean id="bookDao" class="com.itheima.dao.impl.BookDaoImpl"> |