目录前言1. 了解Spring2. IoC3. 注解4. Bean5. 了解DI总结前言通过本篇文章你将了解到Spring IoC的思想、五大类注解、方法注解,DI。1. 了解SpringSpring被称为一个框架有着庞大的社区支持很多应用场景。简单来说就是一个包含了众多对象的容器。不过这里的容器有一个前缀叫做IoC。也就是IoC容器。容器这个词没那么高深我们日常生活中经常能看见。容器嘛就是装东西的。比如一瓶矿泉水里面的水是溶剂空瓶子就是容器。化学实验室里的烧杯也是一个容器。我们说Spring是一个容器只不过是把这个词语稍微抽象了一点。以前我们需要自己去new一个对象现在Spring将一个个的对象Object当作溶剂。Spring把它们装在一起帮我们统一管理。再比如我们使用的HashMap用来存储数据它也是一个容器。2. IoCSpring IoC是Spring中一个比较重要的思想其中另一个重要的思想是AOP。这里我们先了解IoC是什么。首先IoC全称叫做Inversion of Control。翻译过来就是控制反转。这里的控制可以理解为对象的控制权。反转也就是白的变成黑的主动变成被动。所以控制反转就是掌握对象创建与销毁的人改变了。再举出一个例子一个小公司。产品研发人员招聘…这些事情都可以由老板一个人做。等到公司规模扩大老板就会把招聘这个事情分出去让HR来做。把产品研发交给技术团队去做。看掌管人员招聘这个事情的人就变了由最初的老板控制变为现在的HR控制。所以Spring IoC就是将对象的控制权转移到Spring上由Spring来决定对象的创建与销毁。我们再通过代码来体会这个反转思想。publicclassNewCarExample{publicstaticvoidmain(String[]args){CarcarnewCar();car.run();}/** * 汽车对象 */staticclassCar{privateFrameworkframework;publicCar(){// 直接在构造函数中 new 下层依赖导致高耦合frameworknewFramework();System.out.println(Car init....);}publicvoidrun(){System.out.println(Car run...);}}/** * 车身类 */staticclassFramework{privateBottombottom;publicFramework(){bottomnewBottom();System.out.println(Framework init...);}}/** * 底盘类 */staticclassBottom{privateTiretire;publicBottom(){tirenewTire();System.out.println(Bottom init...);}}/** * 轮胎类 */staticclassTire{publicTire(){System.out.println(Tire init...);}}}造车之前我们得将车身造出来建造车身又得建造底盘…这样就形成了这样的一个关系车-车身-底盘-轮胎。这种写法的耦合度是非常高的。我们从中选择一个类来具体研究staticclassBottom{privateTiretire;publicBottom(){tirenewTire();System.out.println(Bottom init...);}}这个Bottom的建造依赖于Tire这个对象我们就说Tire是Bottom的一个依赖。这个Tire是在Bottom的构造方法里面创建出来的也就是说Tire这个对象的存活什么时候创建、销毁完全由Bottom这个对象决定。我们再来看另一种写法。publicclassNewCarExample{publicstaticvoidmain(String[]args){// --- Main 方法作为容器负责“控制”对象的生命周期和依赖关系 ---// 1. 先生产最底层的零件TiretirenewTire(18);// 假设现在轮胎可以指定尺寸了// 2. 将零件注入到上一层组件中 (构造方法注入)BottombottomnewBottom(tire);// 3. 继续向上注入FrameworkframeworknewFramework(bottom);// 4. 最后组装成汽车CarcarnewCar(framework);// 5. 运行car.run();}/** * 汽车对象 */staticclassCar{privateFrameworkframework;// IoC通过构造函数注入依赖不再自己 newpublicCar(Frameworkframework){this.frameworkframework;System.out.println(Car init....);}publicvoidrun(){System.out.println(Car run...);}}/** * 车身类 */staticclassFramework{privateBottombottom;publicFramework(Bottombottom){this.bottombottom;System.out.println(Framework init...);}}/** * 底盘类 */staticclassBottom{privateTiretire;publicBottom(Tiretire){this.tiretire;System.out.println(Bottom init...);}}/** * 轮胎类 */staticclassTire{privateintsize;publicTire(intsize){this.sizesize;System.out.println(Tire init, size: size);}}}这个写法就是利用了IoC思想对象的控制权属于main这个方法所有对象都在main里面创建。3. 注解好了IoC思想我们已经体会到了接下来看看如何在Spring中用上。这是一个类注解当你将这个注解添加到类上方时Spring就会管理这个类并创建一个对象出来。Controller// 将对象存储到 Spring 中publicclassUserController{publicvoidsayHi(){System.out.println(hi,UserController...);}}当Spring运行的时候这个UserController对象就已经被创建出来了。既然对象已经被创建出来了那我们该怎么验证或者获取它呢毕竟眼见为实对吧。SpringBootApplicationpublicclassIoCDemoApplication{//测试Beanpublicstaticvoidmain(String[]args){ApplicationContextcontextSpringApplication.run(IoCDemoApplication.class,args);UserControllerbean1context.getBean(UserController.class);bean1.sayHi();//控制台输出hi,UserController...}其中这一段代码你就理解为获取Spring中的应用程序上下文即可。这里的上下文也可以理解为拿到Spring这个容器。ApplicationContextcontextSpringApplication.run(IoCDemoApplication.class,args);这一段代码就是从上下文容器中获取一个类型为UserController的对象。UserControllerbean1context.getBean(UserController.class);除了Controller这一个类注解还有其他四个Configuration, Component, Service, Repository。这四个类注解的使用方式几乎可以说是一样的这里就不演示了。但是我们要来看看这些注解之间的区别。在三层架构中Controller 代表控制层负责接收前端的请求Service 是业务层负责对业务逻辑和数据进行处理Repository 是数据层主要面向数据库层面的操作Configuration 是配置层先按下不表。为什么有这么多功能相似的注解呢这就和每个省市都有自己的车牌号前缀是一样的道理。车牌号都是唯一的用来标识一辆车。但为什么还要设置不同的车牌开头呢比如陕西的车牌号是【陕A/B/C…】北京的车牌号是【京A/B/C…】。通过车牌开头我们一眼就能知道这辆车是哪个地区的。注解也是一样它们都能把对象存进Spring但不同的注解能让我们一眼看清这个类是属于哪一层控制层/业务层/数据层的。比较重要的区别是Controller不能够和其他注解混用不然当你输入URL时浏览器页面会报404。RequestMapping(/UserController)Controller//ConfigurationResponseBodypublicclassUserController{RequestMapping(/print)publicStringprint(){return使用 UserController;}}正常结果错误代码RequestMapping(/UserController)ControllerConfigurationpublicclassUserController{RequestMapping(/print)publicStringprint(){return使用 UserController;}}错误结果4. Bean在前面的内容里我们一直用“对象”这个词。但在 Spring 的世界里被 Spring 容器管理的对象有一个专属的高级名字——BeanJava Bean。你可以这么理解如果在外面它就是一个普普通通的 Java 对象Object一旦它被贴上Controller或Service等注解被招进了 Spring 容器它就摇身一变成为了Spring Bean。就像一个普通人入职了公司就成了公司的“打工人”一样。我们前面讲的Controller等五大类注解是贴在类上面的。但如果你不想把整个类都交给 Spring只想把类里面的某个方法的返回值交给 Spring 管理呢这时候就要用到我们前言里提到的方法注解Bean了。Configuration// 通常 Bean 要配合 Configuration 一起使用publicclassAppConfig{// 使用 Bean 注解告诉 Spring把这个方法的返回值当成一个 Bean 存起来BeanpublicUseruser(){UserusernewUser();user.setName(张三);user.setAge(18);returnuser;}}这样一个名字叫张三的 User 对象Bean就被存进 Spring 容器里了随时待命5. 了解DI现在我们的 Spring 容器里已经装满了各种各样的 Bean对象了。但程序要跑起来对象和对象之间是需要互相配合的。比如控制层的UserController想要调用业务层的UserService。如果是以前我们要在UserController里面自己去new UserService()。有了 Spring 之后呢既然它们都在容器里难道每次都要写一串context.getBean(UserService.class)吗那也太麻烦了。这时候就轮到DIDependency Injection依赖注入了。很多人容易把 IoC 和 DI 搞混。其实很简单IoC 是一种思想把控制权交出去。DI 是这种思想的具体实现手段怎么把需要的对象拿过来用。Spring 提供了一个超级好用的注解Autowired。只要贴上它Spring 就会自动把你要的对象给你“注入”进来。我们来看看代码有多简洁ControllerpublicclassUserController{// 划重点贴上 AutowiredSpring 就会自动从容器里找 UserService 塞给你AutowiredprivateUserServiceuserService;publicvoidsayHi(){System.out.println(hi, UserController...);// 直接用 userService完全不需要 new// userService.doService();}}总结理解 IoC 思想创建和销毁对象的“控制权”交给了 Spring 容器让 Spring 来帮我们统一管理这就是控制反转存入 Bean 对象通过注解我们可以轻松地把对象装进 Spring 容器里。使用 DI 依赖注入对象存进去了还得互相配合。通过Autowired注解自动把我们需要依赖的 Bean “注入”到我们的代码中。