一 Spring 的概述:
1 概念:
学习 Spring 框架之前, 我们学习了 Hibernate 框架 (持久层的 ORM 框架) 和 Struts2(web 层的 MVC 框架),spring 框架叫做 EE/SE 开发的一站式框架, 每一层都为我们提供了解决方案.
2 学习 spring 框架有啥好处?
面向对象的设计比任何技术都重要
方便解耦, 简化开发.
代码测试更加简单
方便集成各种优秀的框架
声明式事务的支持
二 IoC
1 什么是 IoC
IoC,Inversion of Control, 控制反转, 是面向对象编程的一种设计思想.
1.2,IoC 是什么
IoC, 在 Java 开发中, IoC 意味着将你设计好的对象交给容器控制, 而不是传统的在你的对象内部直接控制. 如何理解好 IoC 呢? 理解好 IoC 的关键是要明确 "谁控制谁, 控制什么, 为何是反转(有反转就应该有正转了), 哪些方面反转了", 那我们来深入分析一下:
●谁控制谁, 控制什么: 传统 Java SE 程序设计, 我们直接在对象内部通过 new 进行创建对象, 是程序主动去创建依赖对象; 而 IoC 是有专门一个容器来创建这些对象, 即由 IoC 容器来控制对 象的创建; 谁控制谁? 当然是 IoC 容器控制了对象; 控制什么? 那就是主要控制了外部资源获取(不只是对象包括比如文件等).
●为何是反转, 哪些方面反转了: 有反转就有正转, 传统应用程序是由我们自己在对象中主动控制去直接获取依赖对象, 也就是正转; 而反转则是由容器来帮忙创建及注入依赖对象; 为何是反转? 因为由容器帮我们查找及注入依赖对象, 对象只是被动的接受依赖对象, 所以是反转; 哪些方面反转了? 依赖对象的获取被反转了.
图 1-2 有 IoC/DI 容器后程序结构示意图
1.2,IoC 能做什么
IoC 不是一种技术, 只是一种思想, 一个重要的面向对象编程的法则, 它能指导我们如何设计出松耦合, 更优良的程序. 传统应用程序都是由我们在类内部主动创建依赖对象, 从而导致类与类之间高耦合, 难于测试; 有了 IoC 容器后, 把创建和查找依赖对象的控制权交给了容器, 由容器进行注入组合对象, 所以对象与对象之间是 松散耦合, 这样也方便测试, 利于功能复用, 更重要的是使得程序的整个体系结构变得非常灵活.
其实 IoC 对编程带来的最大改变不是从代码上, 而是从思想上, 发生了 "主从换位" 的变化. 应用程序原本是老大, 要获取什么资源都是主动出击, 但是在 IoC/DI 思想中, 应用程序就变成被动的了, 被动的等待 IoC 容器来创建并注入它所需要的资源了.
IoC 很好的体现了面向对象设计法则之一 -- 好莱坞法则:"别找我们, 我们找你"; 即由 IoC 容器帮对象找相应的依赖对象并注入, 而不是由对象主动去找.
1.3,IoC 和 DI
DI-Dependency Injection, 即 "依赖注入": 组件之间依赖关系由容器在运行期决定, 形象的说, 即由容器动态的将某个依赖关系注入到组件之中. 依赖注入的目的并非为软件系统带来更多功能, 而是为了提升组件重用的频率, 并为系统搭建一个灵活, 可扩展的平台. 通过依赖注入机制, 我们只需要通过简单的配置, 而无需任何代码就可指定目标需要的资源, 完成自身的业务逻辑, 而不需要关心具体的资源来自何处, 由谁实现.
理解 DI 的关键是:"谁依赖谁, 为什么需要依赖, 谁注入谁, 注入了什么", 那我们来深入分析一下:
●谁依赖于谁: 当然是应用程序依赖于 IoC 容器;
●为什么需要依赖: 应用程序需要 IoC 容器来提供对象需要的外部资源;
●谁注入谁: 很明显是 IoC 容器注入应用程序某个对象, 应用程序依赖的对象;
●注入了什么: 就是注入某个对象所需要的外部资源(包括对象, 资源, 常量数据).
IoC 和 DI 由什么关系呢? 其实它们是同一个概念的不同角度描述, 由于控制反转概念比较含糊(可能只是理解为容器控制对象这一个层面, 很难让人想到谁来维护对象关系), 所以 2004 年大师级人物 Martin Fowler 又给出了一个新的名字:"依赖注入", 相对 IoC 而言,"依赖注入" 明确描述了 "被注入对象依赖 IoC 容器配置依赖对象".
看过很多对 Spring 的 IoC 理解的文章, 好多人对 IoC 和 DI 的解释都晦涩难懂, 反正就是一种说不清, 道不明的感觉, 读完之后依然是一头雾水, 感觉就是开涛这位技术牛人写得特别通俗易懂, 他清楚地解释了 IoC(控制反转) 和 DI(依赖注入)中的每一个字, 读完之后给人一种豁然开朗的感觉. 我相信对于初学 Spring 框架的人对 IoC 的理解应该是有很大帮助的.
2 Spring Framework Runtime
3 实现的代码如下:
面向接口编程的好处: 方便程序的扩展(比如集合), 多态
好的程序设计满足 OCP 原则, 在尽量不修改程序源代码的基础上进行扩展,
工厂模式: 工厂 + 反射 + 配置文件实现解耦和
1 将实现类交给 Spring 管理
- <?xml version="1.0" encoding="UTF-8"?>
- <beans xmlns="http://www.springframework.org/schema/beans"
- xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"
- xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
- <bean id="UserService" class="com.itheima.demo1.UserServiceImpl">
- <property name="name" value="花花" />
- </bean>
- </beans>
2 编写测试类
- /**
- * src 目录下的
- */
- @Test
- public void demo2(){
- ApplicationContext applicationContext=new ClassPathXmlApplicationContext("applicationContext.xml");
- UserService userService = (UserService) applicationContext.getBean("UserService");
- userService.save();
- }
配置文件可以放在任意盘符下
- /**
- * 配置文件放在 D 盘目录下
- */
- @Test
- public void demo3(){
- ApplicationContext applicationContext=new FileSystemXmlApplicationContext("D:\\applicationContext.xml");
- UserService userService = (UserService) applicationContext.getBean("UserService");
- userService.save();
- }
4 IoC 和 DI(面试经常会问到)
IoC: 控制反转, 将创建对象权交给 spring 管理
DI: 依赖注入, 前提必须有 IoC 的环境, Spring 管理的这个类的时候将类的属性注入进来
面向对象的三种关系
(1)依赖
class A(){}
Class B(){public void xxx(A a){}}我们这时候说 B 依赖 A
(2)继承
(3)聚合
Spring 工厂类
ApplicationCotext 类的 UML 类图
四 Bean 的相关配置
1 <bean > 标签中的 id 和 name
id : 使用了约束中的唯一约束
name : 没有使用约束中的唯一约束(理论上可以出现重复, 但是在实际的开发中不能重复)
2 Bean 的作用范围的配置(重点)
scope :Bean 的作用范围
singleton: 默认的, Spring 会采用单例模式创建这个对象.
prototype: 多例模式.(Struts2 和 Spring 整合一定会用到)
request : 应用在 Web 项目中, Spring 创建这个类以后, 将这个类存入到 request 范围中.
session : 应用在 Web 项目中, Spring 创建这个类以后, 将这个类存入到 session 范围中.
globalsession : 应用在 Web 项目中, 必须在 porlet 环境下使用. 但是如果没有这种环境, 相对于 session.
3 属性注入的方式
(1)使用构造方法注入
- <!--spring 属性注入的方式 -->
- <!-- 使用构造方法 -->
- <bean id="car" class="com.itheima.demo3.Car">
- <constructor-arg name="name" value="玛莎拉蒂"/>
- <constructor-arg name="price" value="2000000"/>
- </bean>
(2)使用 set 方法注入普通类型
- <!-- 使用 set 方法注入普通类型 -->
- <bean id="car2" class="com.itheima.demo3.Car2">
- <property name="name" value="一汽大众"/>
- <property name="price" value="200000"/>
- </bean>
使用 set 方法注入对象
- <!-- 使用 set 方法注入对象 -->
- <bean name="employee" class="com.itheima.demo3.Employee">
- <property name="name" value="花花"/>
- <!--ref 写对象的 id 或者 name-->
- <property name="car2" ref="car2"/>
- </bean>
(3)使用 p 名称空间的方式(这点 IDEA 做的就比较好, 不用去其他文件去找, 直接快速修复)
- <bean id="car2" class="com.itheima.demo3.Car2" p:name="奔驰" p:price="500000"/>
- <bean id="employee" class="com.itheima.demo3.Employee" p:name="大花花" p:car2-ref="car2"> </bean>
(4)使用 SPEL 表达式注入
- <!-- 改用 spel 表达式注入 -->
- <bean id="car2" class="com.itheima.demo3.Car2">
- <property name="name" value="#{carInfo.name}"/>
- <property name="price" value="#{carInfo.jisuanprice()}"/>
- </bean>
- <bean id="employee" class="com.itheima.demo3.Employee">
- <property name="name" value="#{'大花'}"/>
- <property name="car2" value="#{car2}" /><!-- 用 spel 不用 ref, 都用 value-->
- </bean>
- <import resource="applicationContext2.xml"/>
扩展: 集合类型属性的注入
- <?xml version="1.0" encoding="UTF-8"?>
- <beans xmlns="http://www.springframework.org/schema/beans"
- xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"
- xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
- <!-- 注入数组 -->
- <bean id="Collection" class="com.itheima.demo4.Collection">
- <property name="arrs">
- <list>
- <value > 杨幂</value>
- <value > 杨紫</value>
- <value > 花花</value>
- <value > 李四</value>
- </list>
- </property>
- <!-- 注入 list 集合 -->
- <property name="list">
- <list>
- <value > 张三</value>
- <value > 李四</value>
- <value > 王五</value>
- </list>
- </property>
- <!-- 注入 set 集合 -->
- <property name="set">
- <set>
- <value>aaa</value>
- <value>bbb</value>
- <value>xxx</value>
- </set>
- </property>
- <!-- 注入 Map 集合 -->
- <property name="map">
- <map>
- <entry key="aa" value="11"/>
- <entry key="bb" value="22"/>
- <entry key="cc" value="33"/>
- </map>
- </property>
- </bean>
- </beans>
养成良好的代码注释习惯, 方便后期的查看.
往期内容:
Struts2 的 API & 数据封装
来源: https://www.cnblogs.com/bao6/p/10388760.html