Spring框架应该是作为Java开发耳熟能详的一个,并且要能够熟练掌握。但是里面知识点的零碎可能随着时间的流逝,一些知识也会变的陌生起来。Spring这一系列的文章主要是将自己对Spring的一些认识梳理一下,其中这篇文章讲的主要是IOC相关的。
在很早的时候也写过两篇将IOC容器的文章,供君参考,这篇文章更多的是对IOC中相关知识的梳理,内容在下面的两篇文章中也都有:
https://blog.csdn.net/lmlzww/article/details/105363279?spm=1001.2014.3001.5502
https://blog.csdn.net/lmlzww/article/details/105418953?spm=1001.2014.3001.5502
Spring是一个体量小、可以独立使用的轻量级框架,开源并且是为简化企业应用开发的复杂性而生。就像其中的IOC是为Bean容器的创建以及降低耦合度而生,而AOP作为动态代理为原理实现的特性,也可以从分离业务逻辑以及非业务逻辑的角度来降低系统的耦合行,提升可扩展能力,他的优势如下:
那么IOC容器到底是什么呢?我们可以分开理解:IOC(Inversion of Control)控制反转、容器——在IOC容器中提供了提供了我们在配置文件中配置的对象,程序中使用到的对象我们可以通过这个获取,而不需要在程序中通过new创建,正是因为不需要通过new创建了,所以对对象的创建权利实现了翻转,以前通过new创建对象对于程序来说是主动的,但是现在对象是通过Spring框架的IOC容器提供得来的,相对来说是被动的。
在我们学习IOC的时候实际也就围绕两个核心展开——实例的创建、实例的应用,对象的创建主要关注亮点一个是对象创建的形式、还有一个就是对象各种属性的赋值也就是说依赖注入。既然有对象的创建那么就会有他的生命周期,这里要与AOP中的区分开来。总而言之一切都是围绕对象展开的!
底层主要通过xml解析、工厂模式、反射(通过获取到class文件从而再来创建具体对象)三个模块进行实现。主要的一个流程就是:
获取XML并进行解析——>根据配置配置信息获取到class文件——>根据class生成对象实例
❓如果要是用指定的容器获取对象那么框架为给我们默认单例、多例,如果要是我们指定了单例、多例那么系统也会给我们选默认的容器。
ApplicationContext是一个接口,他有很多不同类型的实现子类:

IOC帮助我们完成实例的创建,我们可以理解通常我们有几种对象的创建方式,实际上就是构造函数以及工厂方法,工厂方法又根据方法是否为静态的可以分为两种配置形式。
<bean id="accountService" class="com.itheima.service.impl.AccountServiceImpl">bean>
<bean id="instanceFactory" class="com.itheima.factory.InstanceFactory">bean>
<bean id="accountService" factory-bean="instanceFactory" factory-method="getAccountService">bean>
<bean id="accountService" class="com.itheima.factory.StaticFactory" factory-method="getAccountService">bean>
- id: 给对象起一个别名,用来获取对象
- class: 类的全路径
- name: 与id作用相同,相对于id来说可以添加一些特殊 字符,主要服务于struct1框架,现在不用
创建类,让这个类作为工厂Bean,实现接口FactoryBean
实现接口里面的方法实现的方法中返回的Bean类型
上面说的是通过xml配置文件形式来进行容器对象创建进行制定,通过xml我们也可以使用p名称空间注入简化xml中的配置。开发中我们更常用的是注解形式:@Component、@Service、@Controller、@Repository这四个注解功能是一样的都可以用来创建Bean实例,主要是为了开发人与进行区分。
这里说的容器依赖注入理解为一个Bean依赖于另一个Bean,也就是说以属性的形式存在,属性我们通常会设置为private,这时候想要对对象进行赋值就有两种方式:
<bean id="accountService" class="com.itheima.service.impl.AccountServiceImpl">
<constructor-arg name="name" value="泰斯特">constructor-arg>
<constructor-arg name="age" value="18">constructor-arg>
<constructor-arg name="birthday" ref="now">constructor-arg>
bean>
<bean id="now" class="java.util.Date">bean>
<bean id="accountService3" class="com.itheima.service.impl.AccountServiceImpl3">
<property name="myStrs">
<set>
<value>AAAvalue>
<value>BBBvalue>
<value>CCCvalue>
set>
property>
<property name="myList">
<array>
<value>AAAvalue>
<value>BBBvalue>
<value>CCCvalue>
array>
property>
<property name="mySet">
<array>
<value>222222value>
array>
property>
<property name="myMap">
<props>
<prop key="testC">cccprop>
<prop key="testD">dddprop>
props>
property>
<property name="myProps">
<map>
<entry key="testA" value="aaa">entry>
<entry key="testB">
<value>BBBvalue>
entry>
map>
property>
bean>
![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-wq6xznpR-1663328880605)(F:\typroa\aimages\image-20220914200156746.png)]](https://1000bd.com/contentImg/2023/11/08/231924065.png)
设置为null值是通过null标签,而非是标签里的value值
特殊字符的话通过转义符<或是> ;把特殊符号内容写到cdata的接口
![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-cmlklHGv-1663328880606)(F:\typroa\aimages\image-20220914191053655.png)]](https://1000bd.com/contentImg/2023/11/08/231924113.png)
![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-CmyaPXMm-1663328880606)(F:\typroa\aimages\image-20220914192958367.png)]](https://1000bd.com/contentImg/2023/11/08/231924328.png)

上面也说到依赖注入实际上就是给属性赋值,那么我们也可以通过注解的方式来实现:
@AutoWired:根据属性类型进行自动注入
@Qualifier:根据属性的名称进行注入,需要与@Autowired配合使用,当一个接口有多个实现类的时候就可以根据名称进行赛选了
@Resource:可以根据属性进行注入也可以根据名称进行注入,在使用
@Value:注入普通类型的属性
这里可以联想到容器对象构建的时候@Component、@Bean等注解可以给穿件的Bean命名
scope属性:singleton—单实例(加载配置文件的时候就会创建一个单实例对象);prototype—多实例对象(不是在加载配置文件的时候创建对象而是在调用getBean的时候创建多实例对象);request—每次创建对象会凡在request中;session—创建之后放在session中
声明周期——从对象的创建到对象的销毁
通过构造器创建bean
为bean的属性设置和对其他bean的引用
初始化之前吧bean实例传递给bean的前置处理器方法
调用bean的初始化方法(需要进行配置)
把bean的实例传递给bean的后置处理器方法
bean可以使用了——对象已经获取到
当容器关闭的时候,调用bean的销毁方法(需要进行配置)

后置处理器的实现方法——实现BeanPostProcessor
![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-2Av736gi-1663328880609)(F:\typroa\aimages\image-20220914213848567.png)]](https://1000bd.com/contentImg/2023/11/08/231924297.png)
![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-pLsZzObe-1663328880610)(F:\typroa\aimages\image-20220914214205055.png)]](https://1000bd.com/contentImg/2023/11/08/231924327.png)
创建一个外部的配置文件
![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-pDQu9J8R-1663328880610)(F:\typroa\aimages\image-20220914221338472.png)]](https://1000bd.com/contentImg/2023/11/08/231924022.png)
把外部的属性文件引入到spring的配置为文件中,并配置名称空间
![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-OOaeWcV1-1663328880611)(F:\typroa\aimages\image-20220914221654488.png)]](https://1000bd.com/contentImg/2023/11/08/231924355.png)