Spring的IOC容器学习笔记
一、IOC容器概述
1.1 IOC介绍
- IOC:控制反转,减低计算机代码之间的耦合度
- 把对象的创建和对象之间的调用过程,交给Spring进行管理
1.2 底层原理
- 底层使用xml解析,工厂设计模式,反射
1.3 IOC接口
- Spring提供IOC容器实现的两种方式(两个接口):
- (1)BeanFactory:
- IOC容器最基本的实现方式,是Spring内部使用的接口,不提供开发人员进行使用
- 加载配置文件时候不会创建(懒汉式),使用时再创建对象
- (2)ApplicationContext:
- BeanFactory接口的子接口,提供更多更强大的功能,一般有开发人员进行使用
- 加载配置文件时,就会创建配置文件对象(饿汉式)
- 把耗时耗资源的操作,交给启动服务器时使用更好
- (1)BeanFactory:
- ApplicationContext的实现类
- ClassPathXmlApplicationContext
- FileSystemXmlApplicationContext
二、xml配置文件实现bean管理
2.1 属性注入
- (1)通过set方法
- 在类中创建set方法
1 | <!--xml配置文件--> |
- (2)通过带参构造器
- 在类中创建一个带参构造器
1 | <!--省略了beans配置内容--> |
- (3)p名称空间—简化了set方法
1 |
|
- (4)外部bean注入
- 举例:
- 1.创建两个类service类和dao类
- 2.在service类中调用dao里面的方法
- 3.在Spring配置文件中进行配置
- 利用property中ref属性,来进行对象赋值
1 | <!--省略beans配置内容> |
- (5)内部bean注入
- 跟外部bean类似,只是另外一个对象bean不再外面创建,而在一个bean里面创建
- 在
<property>
标签中,添加<bean>
标签进行内部创建
1 | <!--省略beans配置内容> |
- (6)级联赋值
- 方法一:跟外部bean操作一样,就是在创建外部bean的同时,用
<property>
标签进行赋值 - 方法二:跟外部bean操作类似,但不在外部bean创建时进行赋值
- 方法一:跟外部bean操作一样,就是在创建外部bean的同时,用
1 | <!--省略beans配置内容> |
- (7)集合属性注入
- 在
<property>
标签内,添加对应的集合标签;数组用<array>
,List集合用<List>
,Set集合用<Set>
,Map使用<Map>
- Map集合在对应的
<Map>
下,还要添加<entry>
标签才可以 - 集合注入的内容是对象时,需要添加
<ref>
标签进行赋值
- 在
1 | <!--省略beans配置内容> |
- (8)把集合注入部分提取出来
- 1.在Spring配置文件中引入名称空间util
- 2.使用util标签完成list集合注入提取
1 |
|
2.2 工厂bean(FactoryBean)
- (1)Spring有两种类型的bean,一种是普通bean,另外一种是工厂bean(Factory Bean)
- (2)普通Bean特点:
- 在配置文件中定义bean类型就是返回类型
- (3)工厂Bean特点:
- 在配置文件中定义Bean类型可以和返回类型不一样
- (4)使用工厂Bean:
- 创建一个类,让其实现接口FactoryBean,作为工厂Bean
- 实现接口里面的方法,在实现方法中定义返回的Bean类型
1 | //类实现FactoryBean接口,泛型填想要实现的另外一个类型 |
1 | <!--跟普通创建bean方法一样--> |
1 | //实现代码 |
2.3 bean的作用域
- (1)在Spring里面,设置创建Bean实例是单实例还是多实例
(2)在Spring情况下,默认情况下是单实例对象
(3)如何设置单实例还是多实例
- 在Spring配置文件bean标签里面,有属性(scope)设置用于单实例还是多实例
- scope属性值:
- singleton:表示单实例对象,是默认值
- prototype,表示多实例对象
- singleton和prototype区别:
- singleton单实例,protptype是多实例
- 设置scope值是singleton时候,加载spring配置文件时候就会创建单实例对象
- 设置scope值是prototype时候,不是在加载spring配置文件时候创建对象,在调用getBean()时候才创建多实例对象
1 | <!--省略beans配置内容--> |
1 | //单实例演示 |
- (4)还有其他不常用值:requesy、session
2.4 bean生命周期
- (1)生命周期:从对象的创建到对象的销毁的过程
(2)bean的生命周期
- 通过构造器创建Bean实例(无参数构造器)
- 通过构造器创建Bean实例(无参数构造器)
- 通过构造器创建Bean实例(无参数构造器)
- bean可以使用(对象获取到了)、
- 当容器关闭时,调用bean的销毁的方法(需要进行配置销毁的方法)
(3)演示Bean的生命周期
- 第一步,执行无参构造器创建Bean实例
- 第二步,调用set方法设置属性值
- 第三步,执行初始化方法
- 第四步,获取创建Bean实例对象
- ClassPack.LifeCycleBean@34123d65
- 第五步,执行销毁的方法
1 | //类 |
1 | <!--省略了beans配置内容--> |
1 | //执行代码 |
- (4)Bean的后置处理器,bean的生命周期变成7步
- 第一步,执行无参构造器创建Bean实例
- 第二步,调用set方法设置属性值
- 把bean实例传递给bean后置处理器的方法:
postProcessBeforeInitialization
- 第三步,执行初始化方法
- 把bean实例传递给bean后置处理器的方法:
postProcessAfterInitialization
- 第四步,获取创建Bean实例对象
- ClassPack.LifeCycleBean@34123d65
- 第五步,执行销毁的方法
- (5)实现方法:
- 在上面的基础上,新建一个类,实现BeanPostProcessor接口,作为后置处理器
- 在xml配置文件中配置
1 | //后置处理器类 |
1 | <!--配置后置处理器--> |
2.5 自动装配
- 自动装配:根据指定的装配规则(属性名称或者属性类型),Spring自动将匹配的属性值进行注入
1 | <!--省略beans配置内容--> |
2.6 引入外部属性文件
- 一般将属性值比较固定的,通过文件进行保存,通过读取文件来获取属性内容(例如:连接数据库的内容)
- 举例:连接 数据库连接池
- (1)直接配置数据库信息
- 引入德鲁伊连接池依赖的jar包
- 在xml文件中配置信息
- (1)直接配置数据库信息
1 | <!--直接配置--> |
- (2)通过引入外部属性文件配置数据库连接池
- 创建properties文件信息
- 创建context名称空间(和之前的util一致)
- 在配置文件使用标签引入外部属性文件
- (2)通过引入外部属性文件配置数据库连接池
1 |
|
- 创建对象的方式没有改变的就不演示了
三、注解形式实现bean管理
3.1 注解介绍
- 注解是代码特殊标记,格式:@注解名称(属性名称=属性值, 属性名称=属性值…)
- 注解可以作用在类,属性,方法上
- 简化xml配置
3.2 利用注解创建对象
- 创建对象的四个注解:
- (1)@Component
- (2)@Service
- (3)@Controller
- (4)@Repository
- 四个注解功能是一样的,但一般为了区分,会在不同的地方使用不同注解
- 创建方法:
- (1)引入以来jar包:aop
- (2)xml配置文件开启组件扫描,需要引入context名称空间
- (3)类添加创建注解,创建方法和xml配置方法一致
1 |
|
1 | //创建带注解的类 |
- 补充: 组件扫描可以开启更细致的扫描
1 | <!--use-default-filters:是否扫描全部类--> |
1 | <!--exclude-filter:不扫描指定内容--> |
3.3 属性注入
- 属性注入的注解:
- (1)@AutoWired:
- 自动装填,根据属性类型进行注入
- (2)@Qualifier:
- 根据属性的名称进行注入,此注解要和@AutoWired一起使用
- (3)@Resource:
- 可以根据类型注入,可以根据名称注入
- 此注解为javax.annotation.Resource当中,新版本JDK摒弃了此API,官方推荐用上面两注解来实现
- 新版本JDK没有@Resource解决方法:https://blog.csdn.net/qq_44518192/article/details/107644905
- (4)@Value:
- 注入普通类型属性
- (1)@AutoWired:
1 | //类: |
1 | public class attributeInjection { |
3.4 纯注解开发
(1)创建配置类,替代xml配置文件
@Configuration
:作为配置类,替代xml配置文件@ComponentScan(basePackages = {"ClassPack"})
:扫描注解路径,跟xml的开启组件扫描一样
(2)
public AnnotationConfigApplicationContext(Class<?>... componentClasses)
:加载配置类
1 | //配置类 |
1 | //创建对象 |
- 此纯注解开发,一般是SpringBoot才使用到