1.Spring概述
1.1 spring是什么?
Spring是分层的java应用jull-stack轻量级框架,以**Ioc和AOP**为核心,提供了展现层 Spring MVC 和持久层 Spring JDBC 以及业务层事务管理等众多的企业级应用技术,还能整合众多第三方框架和类库。
1.2 spring优势
1. 方法解耦,简化开发
通过Ioc容器,可以将对象间的依赖关系交给Spring控制,避免硬编码造成的程序耦合。用户也不必为单例模式、属性文件解析等低层代码今昔编写。
2. AOP编程支持
通过AOP的工厂,方便进行面向切面编程,许多功能可以轻易通过AOP实现。
3. 声明式事务的支持
可以从事务管理代码中解脱出来,通过声明式事务的管理,提高开发效率和质量。
4. 方便程序的测试
可以用非容器依赖的编程方式进行几乎所有的测试工作,测试不再是昂贵的操作,而是随手可做的事情。
5. 方便集成各种优秀框架
Spring可以降低各种框架的使用难度,提供了对各种优秀框架(Struts、Hibernate、Hessian、Quartz 等)的直接支持
6. 降低java ee API使用难度
Spring对JavaEE API(如 JDBC、JavaMail、远程调用等)进行了薄薄的封装层,使这些API的使用难度大为降低
7. 源码高大上 值得学习
Spring的源代码设计精妙、结构清晰、匠心独用,处处体现着大师对Java设计模式灵活运用以及对Java技术的高深造诣。它的源代码无意是 Java 技术的最佳实践的范例。
1.3 spring 体系结构
![](https://img2018.cnblogs.com/blog/1882316/202002/1882316-20200211194758395-1508272279.png)
2 IOC的概念和作用
2.1 什么是程序的耦合
耦合度:模块之间的关联度。
模块间的耦合度值模块之间的依赖关系,包括控制关系、调用关系、传递数据关系。模块间联系越多,耦合性越强,维护成本越高。
开发中,有些依赖关系是必需的,有些依赖关系可以通过代码优化解除。
如下:编译期的依赖关系应该解决。
![](https://img2018.cnblogs.com/blog/1882316/202002/1882316-20200212133847808-492214337.png)
2.2 工厂模式解耦
实际开发中我们可以把三层的对象都使用配置文件配置起来,当启动服务器应用加载的时候,让一个类中的方法通过读取配置文件,把这些对象创建出来并存起来。在接下来的使用的时候,直接拿过来用就好了。
2.2.1 控制反转 IOC
IOC的作用:消除代码中的依赖关系。
利用工厂创建对象存入容器中。
3 spring的ioc解决程序耦合
3.0 Bean的概念
Bean:在计算机英语中,有可重用组件的含义。
JavaBean:用java语言编写的可重用实体类。 范围:javabean > 实体类
3.1 基于XML配置的基本使用
1.导入相关jar包 或 坐标
2.在类的根路径虾创建一个**任意名称**的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" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"> </beans>
3.让spring管理资源 配置要存入ioc容器的对象
<bean>标签:用于配置spring创建对象,并存入ioc容器中
id属性:对象的唯一表示
class属性:要创建对象的全限定类名
如:<bean id="user" class="com.sweetbetter.domain.User"></bean>
4.测试
4.1 获取spring容器 详细的后面讲到
ApplicationContext ac= new ClassPathXmlApplicationContext("bean.xml");
4.2 根据id获取对象
User u=ac.getBean("user",User.class);
3.2 基于XML配置的细节
3.2.1 spring中工厂类的结构
3.2.2 获取容器的三种
ApplilcationContext接口的三个实现类
1.ClassPathXmlApplicationContext:从类的根路径下加载配置文件 **推荐使用**
2.FileSystemXmlApplicationContext:使用的是系统的路径
3.AnnotationConfigApplicationContext:使用注解配置容器对象时,使用此类来创建spring容器
3.2.3 BeanFactory和ApplicationContext的区别
BeanFactory(顶层接口):采用的策略时延迟加载的。什么时候根据id获取对象,什么时候才真正的创建对象。(多例对象适用)
ApplicationContext :是BeanFactory的子接口。在构建核心容器时,创建对象采取的策略时默认立即加载的方式。即读取完配置文件就以将配置文件中配置的对象创建了。(单例对象适用) 实际开发更多使用这个接口。当然Spring是强大的,可以配置是立即还是延迟加载。
3.2.4 bean标签细节
bean标签:
作用:配置对象让spring读取并创建
**默认情况:**它调用的是无参的构造方法创建,如果没有无参的构造方法且没配置其他创建方式,就不能创建成功。
属性:
id:给对象在容器提供一个唯一标识。
class:指定类的全限定类名。用于反射创建对象,默认使用无参构造函数。
scope:指定对象的作用范围
* **singleton:** 默认值 单例的 一个应用只有一个对象的实例
* **prototype:** 多例的 每次访问对象时,都会重新创建对象实例
* request:WEB项目中,Spring 创建一个 Bean 的对象,将对象存入到 request 域中
* session:WEB项目中,Spring 创建一个 Bean 的对象,将对象存入到 session 域中
* global session:WEB项目中,应用在 Portlet 环境.如果没有 Portlet 环境那么 globalSession 相当于 session,应用场景如:实现负载均衡的服务器中,第一次请求返回了验证码,第二次提交验证码,是另一台服务器接收的请求,此在服务器没有验证码如何比对?这就用到了golbal session。
init-method:指定类中初始化方法名称
destory-method:指定类中销毁方法名称
factory-method:指定创建bean的方法名称
factory-bean:指定工厂的bean id
3.2.5 实例化bean的三种方法
第一种:
<!--默认情况下:
它会默认无参构造函数创建对象。如果bean中没有默认午餐构造函数,将会创建失败。-->
<bean id="exmaple" class="com.sweetbetter.user"/>
第二种:
<!--spring管理静态工厂,使用静态工厂的方法创建对象
如StaticFactory中有一个静态方法createInstance创建对象,无需先有工厂实例
-->
<bean id="exmaple" class="com.sweetbetter.StaticFactory"
factory-method="createInstance"></bean>
第三种:
<!--spring管理实例工厂,使用实例工厂的方法创建对象
此方法:先把工厂的创建交给spring管理,然后再由工厂的bean来调用里面的方法。如工厂类名:InstanceFactory 创建实例的方法:createUser
-->
<bean id="instanceFactory" class="com.sweetbetter.InstanceFactory"></bean>
<bean id="user" factory-bean="instanceFactory" factory-method="createUser"></bean>
3.2.6 bean的作用范围和生命周期
单例对象:
一个应用只有一个对象的实例。它的作用范围就是整个引用。
出生:当容器创建时
活着:容器还在就在
死亡:容器销毁,对象消亡
总结:和容器同生共死
多例对象:
每次访问对象时,都会重新创建对象实例。
出生:当使用时创建
活着:使用的过程中就一直活着
死亡:java的垃圾回收器回收
4 Spring的依赖注入
依赖注入:DI(Dependency Injection),他是Spring框架核心ioc的具体体现。
上面讲的是通过反转控制把对象创建交给了spring,但代码中不可能没有依赖的情况,如业务层还要调用持久层的方法,即要 new 持久层的类。
依赖注入DI要解决的就是这种情况。简单的说,就是等框架把持久层的对象传入业务层。
4.1 使用依赖注入
4.1.1 使用构造函数注入
第一种:使用构造函数注入
<!--使用构造函数:
要求:类中需要提供一个对应参数列表的构造函数
涉及标签:constructor-arg
属性:index type name:用来找给谁赋值的
value:赋值基本类型和String
ref:赋值其他bean类型
下面的value是字符串,类中age的类型是Interge,spring会自动转换
-->
<bean id="user" class="com.sweetbetter.user">
<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>
4.1.2 使用set方法注入
第二种:使用set方法注入(更常用)
<!--要求:要在类中提供set方法
标签:property
属性:name:找的是类中set方法后面的部分
ref:给属性赋值是其他 bean 类型的
value:给属性赋值是基本数据类型和string类型的
-->
<bean id="User" class="xxxx">
<property name="name" value="xxx"></property>
<property name="age" value="21"></property>
<property name="birthday" ref="now"></property>
</bean>
<bean id="now" class="java.util.Date"></bean>
4.1.3 注入集合属性(array,list,set,map,props,entry)
注入集合属性:是给类中的集合成员传值,它用的也是set方法注入的方式,只不过变量的数据类型都是集合。
<!-- 注入集合数据
List 结构的: array,list,set
Map 结构的 map,entry,props,prop
-->
<bean id="accountService" class="com.itheima.service.impl.AccountServiceImpl">
<!-- 在注入集合数据时,只要结构相同,标签可以互换 -->
<!-- 给数组注入数据 -->
<property name="myStrs">
<set>
<value>AAA</value>
<value>BBB</value>
<value>CCC</value>
</set>
</property>
<!-- 注入 list 集合数据 -->
<property name="myList">
<array>
<value>AAA</value>
<value>BBB</value>
<value>CCC</value>
</array>
</property>
<!-- 注入 set 集合数据 -->
<property name="mySet">
<list>
<value>AAA</value>
<value>BBB</value>
<value>CCC</value>
</list>
</property>
<!-- 注入 Map 数据 -->
<property name="myMap">
<props>
<prop key="testA">aaa</prop>
<prop key="testB">bbb</prop>
</props>
</property>
<!-- 注入 properties 数据 -->
<property name="myProps">
<map>
<entry key="testA" value="aaa"></entry>
<entry key="testB">
<value>bbb</value>
</entry>
</map>
</property>
</bean>