Spring IoC?看这篇带你吃透 IoC 原理(下)

11月12日 收藏 0 评论 11 java开发

Spring IoC?看这篇带你吃透 IoC 原理(下)

文章申明:转载来源:https://juejin.im/user/254742431009960

本文是《Spring IoC?看这篇带你吃透 IoC 原理(上)》的续集

搭建 Spring 项目

知道要导入哪些 jar 包了,那就找吧。

一、手动加载 jar 包的方式

1. 下载

下载地址:

如果你要问我怎么找的,那就还是从刚才 4.3.26 版本的 Reference Doc 中进去,然后刚开头就有一个 Distribution Zip Files,

好奇心带着我打开了它,发现...

发现了仓库地址!

打开后发现是各个版本的 jar 包啊~

我们搜 5.2.3 版的,它在最下面:

然后就可以愉快的使用了~

1、Dist.zip 是 jar 包
2、Docs.zip 是文档

其他的暂时先不用管~

下载好了之后,就好好看看 Spring 送我们的这份大礼包吧。

此处回答上文的遗留问题:哪里找 Spring Framework 框架图。

答案是:下载的 docs.zip → spring-framework-reference → images → spring-overview

我们需要导入 Intellij 的 jar 包在哪里呢?Dist.zip → libs

这里可以看到,每个黑色框对应3个 jar 包,我们要导入 Intellij 的是 RELEASE.jar.

2. 不用 IoC 构建项目

我们 new project,不用 maven 构架,就新建一个普通的 Java 项目,比如我就叫它 Spring_HelloWorld,然后还是用我常用的 class Rectangle 的例子。

然后在 External Libraries 中导入我们刚才在模块图里看到的那4个模块所对应的 jar 包,结构如下:

这样你以为就大功告成了吗?Too young too simple 啊~

来运行一下:

出现了老盆友:no class def found error, 就是找不到这个类。

我们谷歌 Maven common logging 并下载它的 jar 包,再加到项目里就可以了。

我上图里是已经加过了的,所以你会看到一个 commons-logging-1.2.

再运行一下就可以了。这里的两个文件上文都有截图。

目前为止我们是手动用 set() 方法设置对象的,那怎么用 Spring IoC 呢?

3. Spring IoC 配置文件详解

还需要有一个配置文件,可是这个文件需要配置啥,该怎么配置呢?

官网里都给我们写好了:

第一段是一些命名空间及其规范的介绍,

第二段就是给 bean 的属性赋值了。

这里注意下 bean 里面的配置要改一下,改成我们这个项目对应的。

这里的 id, class 是什么意思呢?官网上也有解释,我这里简单概括下:

1、bean 标签:告诉 Spring 要创建的对象
2、id: 对象的唯一标识,就像每个人的身份证一样,不可重复
3、class: bean 的完全限定名,即从 package name 到 class name
4、property:给属性赋值,name 的名称取决于 set() 方法后面的参数;

其实也可以用 constructor 来赋值,name 的名称取决于参数列表;更多给复杂数据类型赋值的使用可以在官网查到。

当然,在工作中更常用的是注解。但是往往也会有 xml 文件配合着一起使用的,所以还是要懂的。

我的 service 文件配置如下:

4. 最后一步,我们再来看它是怎么用的:

这里面并没有直接的 new 这个 service,但是 Spring 容器帮我们创建了这个对象。

那么 Spring 是如何帮我们创建对象的呢?

ApplicationContext 是 IoC 容器的入口,其实也就是 Spring 程序的入口, 刚才已经说过了它的两个具体的实现子类,在这里用了从 class path 中读取数据的方式;

然后第二行,就是获取具体的 bean 了。这个其实有很多方式,在使用的时候就能看到:

点进去发现,是在 BeanFactory.class 里定义的:

这其中比较常用的是通过
1、Id → 需要 cast
2、Bean 的类型 → 只能在 Singleton 的时候使用,否则不知道用哪个呀
3、Id + 类型 → 下图代码示例

来获取对象,最后两种 String, Class objects 这种可变参数的方式用的很少。

照猫画虎,我的 test 文件改动如下:


成功运行~~

Follow up 1. 对象在容器中默认是单例的

实践是检验的唯一标准:

再用 getBean() 得到一个对象,测试是否还是同一个。

即:

public class MyTest {
public void test myTest() {
ApplicationContext context = new ClassPathXmlApplicationContext("service.xml");
Rectangle rect = context.getBean("rectangle", Rectangle.class);
Rectangle rect2 = context.getBean("rectangle", Rectangle.class);
System.out.println(rect == rect2);
}
}
}

返回 True or False?

答:True

因为默认是单例的,如果要改,需要在配置文件里改.

至于这些标签的用法,这里不再延伸了~

Follow up 2. 容器中的对象是什么时候创建的?

实践是检验的唯一标准:

定义一个无参的 constructor,里面打印一句话,然后只 new ClassPathXmlApplicationContext,如下图:

发现也是可以打印的,所以其实是每次启动容器的时候,就已经创建好容器中的所有对象了。(当然,这在 scope = "prototype" 的时候不适用,只是 singleton 的时候。)

多说一句,其实最好应该一直保留一个无参的 constructor,因为这里 bean 对象的创建是通过反射,

· clazz.newInstance() 默认是调用无参的 constructor

不过,现在已经被弃用掉了,换用了这个:

· clazz.getDeclaredConstructor().newInstance()

二、使用 Maven 构建项目

我们再回到最开始的构建项目,相信大家都体会到了手动导入 jar 包的繁琐之处,其实我们还可以用 Maven 来管理项目中的 jar 包,在公司中也是比较常用的一种方式,免除了手动下载 jar 包的过程。

1. 新建项目

使用 Maven 的话就简化很多了,首先我们创建一个 Maven 项目,不同于刚才的过程在于:

New Project 的时候要选择从 Maven 构建,而不是一个简单的 Java 项目。

建好之后,我们会发现比起刚才的 Java 项目,多了很多东西:

和之前的空项目不太一样,这里有 main, test,其中 resources 是放配置文件的地方,也就是我们刚才的 service.xml 应该放在这里,如果没有放对位置是代码找不到哦~

2. 添加对应的 pom 依赖,就不用手动导 jar 包了

1、仓库地址 mvnrepository.com/
2、搜 spring
3、选择 Spring context → 5.2.3 release,把里面的配置 copy 到 pom.xml 中

最终在左边 external libraries 会自动出现所需的包,一键导入,不要太方便~

3. 写代码~~

小结

我们最后再来体会一下用 Spring 创建对象的过程:

通过 ApplicationContext 这个 IoC 容器的入口,用它的两个具体的实现子类,从 class path 或者 file path 中读取数据,用 getBean() 获取具体的 bean instance。

那使用 Spring 到底省略了我们什么工作?

答:new 的过程。把 new 的过程交给第三方来创建、管理,这就是「解藕」。

Spring 也是用的 set() 方法,它只不过提供了一套更加完善的实现机制而已。

而说到底,底层的原理并没有很复杂,只是为了提高扩展性、兼容性,Spring 提供了丰富的支持,所以才觉得源码比较难。

因为框架是要给各种各样的用户来使用的,它们考虑的更多的是扩展性。如果让我们来实现,或许三五行就能搞定,但是我们实现的不完善、不完整、不严谨,总之不高大上,所以它写三五十行,把框架设计的尽可能的完善,提供了丰富的支持,满足不同用户的需求,才能占领更大的市场啊。

C 11条回复 评论
拾柒

简直是我梦想中的offer,好想去上班

发表于 2023-01-14 23:00:00
0 0
寒武紀三葉草

等了好久,终于开放投递通道了

发表于 2022-10-28 22:00:00
0 0
米线还有吗

热门考点啊,好多公司真题都有这道

发表于 2022-09-30 23:00:00
0 0
摔伤脚踝的流星

资源还可以

发表于 2022-04-26 21:00:00
0 0
是小橘子吖

大厂陆续开放校招了要抓紧时间

发表于 2022-02-12 21:00:00
0 0
鹜落霜洲

太给力了 醍醐灌顶

发表于 2021-09-13 16:25:00
0 0
博客园

深圳有好的UI培训班吗?

发表于 2021-09-13 14:45:00
0 0
公积金

在卷的地方,测试要比开发还要开发,又要懂业务又要懂测试,还要懂运维,我都搞不懂现在测试到底是个什么角色了

发表于 2021-09-12 23:55:00
0 0
灵魂火符

大三下,非重点二本,信息管理与信息系统专业,不打算考研考公啥的,上学期开始接触和学习前端,但总觉得混乱,每天都很焦虑,后悔大一大二为啥不好好规划,不好好学,现在一分钟巴不得掰成两分钟花,大一大二的学弟学妹们,真的要珍惜这两年,不要像我一样到了大三每天都焦虑,希望我有一天也能带着已完成的目标跟大家分享。

发表于 2021-09-12 12:30:00
0 0
我的艾迪不寻常

学的是计算机专业,虽有一些基础,可还是有难度

发表于 2021-09-10 13:30:00
0 0