Spring
简介
行业春天
解决企业级开发的复杂性,使现有的技术更容易使用,本身是个大杂烩,整合了现有的技术框架
不要重复造轮子
- SSH:Struct2+Spring+Hibernate
- SSM:SpringMVC+Spring+Mybatis
官网:https://spring.io/projects/spring-framework#overiew
官方下载地址:https://repo.spring.io/release/org/springframework/spring/
可以下载到所有的版本
GitHub:https://github.com/spring-projects/spring-framework
<!-- https://mvnrepository.com/artifact/org.springframework/spring-webmvc -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.2.7.RELEASE</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.springframework/spring-jdbc -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>5.2.7.RELEASE</version>
</dependency>
两个包:
- springWebMVC
- springJDBC
Spring优点
- Spring是一个开源的免费的框架(容器)
- Spring是一个轻量级,非入侵式框架!
- 不会对原来项目有影响
- 控制反转(IOC),面向切面编程(AOP)
- 支持事务处理,对框架整合的支持
Spring是一个轻量级的控制反转(IOC)和面向切面编程(AOP)的框架
Spring组成
spring组成的七大模块
- 核心容器(SpringCore)
- 核心容器提供Spring框架的基本功能。spring以bean的方式组织和管理Java应用的各个组件及其关系,spring使用BeanFactory来产生和管理Bean,是工厂模式的实现,BeanFactory使用控制反转(IoC)模式将应用的配置和依赖性规范与实际的应用程序代码分开
- 应用上下文(Spring Context)
- Spring上下文是一个配置文件,向spring提供上下文信息,spring上下文包括企业服务、、、、
- Spring面向切面编程(Spring AOP)
- AOP(Aspect Oriented Programming)
- 通过配置管理特性,SpringAOP模块直接将面向方法的编程功能集成在了Spring框架中,Spring管理的任何对象都支持AOP,SpringAOP模块基于Spring的应用程序中的对象提供了事务管理服务,通过使用SpringAOP,不用依赖EJB组件,就可以将声明性事务管理集成在应用程序中
- JDBC和DAO模块(Spring DAO)
- Dao(Data Access Object)
- JDBC、DAO的抽象层,提供了有意义的异常层次结构实现,可用该结构来管理异常处理,和不同数据库提供商抛出的错误信息,异常层次结构简化了错误处理,并且极大的降低了需要编写的代码数量,比如打开和关闭链接。
- 对象实体映射(Spring ORM)
- ORM(Object Relational Mapping)
- Spring插入了若干个ORM框架,提供了ORM对象的关系工具,其中包括Hibernate,JDO和IBatisSQL Map等,所有这些都遵从Spring的通用事务和DAO异常层次结构
- Web模块(Spring Web)
- web上下文模块建立应用程序上下文模块之上,基于web的应用程序提供了上下文,所以spring框架支持与Struts集成,web模块还简化了处理多部分请求以及将请求参数绑定到域对象的工作
- MVC模块(SpringWebMVC)
- MVC(Model View Controller)
- MVC框架是一个全功能的构建Web应用程序的MVC实现,通过策略接口,MVC框架编程高度可配置的,MVC容纳了大量视图技术,其中包括JSP,POI等,模型由JavaBean来构成,存放于m当中,而视图是一个接口,负责实现模型,控制器表示逻辑代码,由c的事情。spring框架的功能可以用在任何J2EE服务器当中,大多数功能也适用于不受管理的环境,spring的核心要点就是支持不绑定到特定J2EE服务的可重用业务和数据的访问对象,毫无疑问这样的对象可以在不同的J2EE环境,独立应用程序和测试环境之间重用
Spring介绍
- SpringBoot
- 快速开发脚手架
- 可以快速开发单个微服务,把一个功能单独提取出来就是一个微服务
- 约定大于配置,主要学习他的配置
- 学习SpringBoot的前提是要掌握Spring和SpringMVC
- SpringCloud
- SpringCloud基于SpringBoot实现的
IOC理论推导
之前使用的流程:
- UserDao接口
- UserDaoImpl实现类
- UserService业务接口
- UserServiceImpl业务实现类
在之前的业务中,用户的需求会影响到我们原来的代码,需要根据用户需求去修改源代码,如果程序代码量巨大,修改一次的成本十分昂贵
使用set接口来实现也是一种动态实现 值的注入
- 之前,程序是主动创建对象,控制权在程序员手上
- 使用了set注入后,程序不再具有主动性,而是变成了被动的接受对象
这种思想,本质上解决了问题,程序员不用再去管理对象的创建,系统的耦合性大大的降低,可以更加专注的在业务的实现上,这是IOC的原型
以前的架构
现在的架构
IOC本质
- 是一种设计思想,DI(依赖注入)是实现IOC的一种方法,原先创建对象由程序自己控制,控制反转后,创建转移给第三方,获得依赖对象的方式反转了
- IoC是Spring框架的核心内容
- 可以使用XML配置
- 可以使用注解
- 不配置也行,自动装填
- 控制反转时一种通过描述(XML或注解)并通过第三方生产或获取特定对象的方式,在Spring中实现控制反转的时IoC容器,其实现方法是依赖注入(Dependency Injection ,DI)
HelloSpring
制作一个简单演示,如何将new对象交给第三方来做,用户可以通过修改xml文件来实现IoC操作
- 导入包
- 配置类加载路径应用上下文xml文件
- 编写JavaBean
- 测试,通过上下文获取bean来new对象
-
导入包
-
<dependency> <groupId>org.springframework</groupId> <artifactId>spring-webmvc</artifactId> <version>5.2.7.RELEASE</version> </dependency>
-
主要是这个,其他随意
-
-
配置类加载路径应用上下文xml文件
-
文件名,spring官方文档是有说的,官方推荐起名为ApplicationContext
-
官方有给初始模板
-
<?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 https://www.springframework.org/schema/beans/spring-beans.xsd"> <bean id="..." class="..."> <!-- collaborators and configuration for this bean go here --> </bean> <bean id="..." class="..."> <!-- collaborators and configuration for this bean go here --> </bean> <!-- more bean definitions go here --> </beans>
-
-
编写Bean
-
@Data public class Hello { private String str; }
-
写好bean之后要写入ApplicationContext
-
<?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 https://www.springframework.org/schema/beans/spring-beans.xsd"> <bean id="Hello" class="com.haoyun.POJO.Hello"> <property name="str" value="haoyun"/> </bean> </beans>
-
设置一个id,对里面的成员变量可以进行设置
-
设置好的Bean会有一个小标志
-
-
-
测试
-
public class MyTest { @Test public void BeanTest(){ ApplicationContext classPathXmlApplicationContext = new ClassPathXmlApplicationContext("Beans.xml"); Hello hello = (Hello) classPathXmlApplicationContext.getBean("Hello"); System.out.println(hello.toString()); } }
-
填应用上下文的位置,产生出了ApplicationContext对象就能获取里面的Bean了,产生Bean对象
-
IOC创建对象的方式
-
使用无参构造创建对象,默认
-
使用有参构造,通过构造器创建
-
@Data public class Hello { private String name; public Hello(String name){ } }
-
添加了一个有参构造函数
-
<bean id="Hello" class="com.haoyun.POJO.Hello"> <property name="name" value="sdafsdf"/> </bean>
-
配置没变
-
爆出错误提示
-
-
没有找到默认的构造函数
-
这时就要看官方文档了,这里找到一篇中文的官方文档
-
https://www.docs4dev.com/docs/zh/spring-framework/5.1.3.RELEASE/reference/core.html#beans
-
-
里面讲到一个有参构造器的依赖注入问题
-
依赖注入的两种变体
DI依赖注入存在两种主要变体:Constructor 和Setter 的两种依赖注入
Constructor
-
-
<beans> <bean id="thingOne" class="x.y.ThingOne"> <constructor-arg ref="thingTwo"/> <constructor-arg ref="thingThree"/> </bean> <bean id="thingTwo" class="x.y.ThingTwo"/> <bean id="thingThree" class="x.y.ThingThree"/> </beans>
-
有参构造函数以这种形式注册,然后包括了下列三种形式
-
<bean id="exampleBean" class="examples.ExampleBean"> <constructor-arg type="int" value="7500000"/> <constructor-arg type="java.lang.String" value="42"/> </bean>
-
如果参数是简单类型就添加type和value,(根据类型的)
-
<bean id="exampleBean" class="examples.ExampleBean"> <constructor-arg index="0" value="7500000"/> <constructor-arg index="1" value="42"/> </bean>
-
还可以使用索引,从0开始(根据索引的)
-
<bean id="exampleBean" class="examples.ExampleBean"> <constructor-arg name="years" value="7500000"/> <constructor-arg name="ultimateAnswer" value="42"/> </bean>
-
消除歧义,加入name,直接规定argument 的name(根据参数名的)
Setter
调用no-argument构造函数,或static工厂方法来实例化Bean
ApplicationContext管理Beans的Constructor和setter的DI,
可以使用properties的格式,但是一般使用XML,或者注解@Controller等
Constructor和Setter是可以混合使用的
Setter注入应该要有合理的默认值,否则,应该添加not-null检查
- 可以由xml、JavaCode、annotations指定
- 每个property(属性)或构造函数参数都要设置value的实际定义,或是容器的另一个引用,如参数不是基本类型,就要找到容器中对应bean的reference(引用)
循环依赖
- classA通过构造函数实注入实现classB,classB又通过构造函数注入实现classA,这种配置bean的相互注入,会被SpringIoC判定为循环reference,并抛出BeanCurrentlyInCreationException
- 要求beanA和beanB之间必须有一个被完全初始化,再注入另一个,典型的先有鸡还是先有蛋的问题
Setter-Based example
-
public class ExampleBean { private AnotherBean beanOne; private YetAnotherBean beanTwo; private int i; public void setBeanOne(AnotherBean beanOne) { this.beanOne = beanOne; } public void setBeanTwo(YetAnotherBean beanTwo) { this.beanTwo = beanTwo; } public void setIntegerProperty(int i) { this.i = i; } }
-
<bean id="exampleBean" class="examples.ExampleBean"> <!-- setter injection using the nested ref element --> <property name="beanOne"> <ref bean="anotherExampleBean"/> </property> <!-- setter injection using the neater ref attribute --> <property name="beanTwo" ref="yetAnotherBean"/> <property name="integerProperty" value="1"/> </bean> <bean id="anotherExampleBean" class="examples.AnotherBean"/> <bean id="yetAnotherBean" class="examples.YetAnotherBean"/>
-
和constructor-based的差距真不大,只是多了一点环节而已
-
<bean id="exampleBean" class="examples.ExampleBean"> <!-- constructor injection using the nested ref element --> <constructor-arg> <ref bean="anotherExampleBean"/> </constructor-arg> <!-- constructor injection using the neater ref attribute --> <constructor-arg ref="yetAnotherBean"/> <constructor-arg type="int" value="1"/> </bean> <bean id="anotherExampleBean" class="examples.AnotherBean"/> <bean id="yetAnotherBean" class="examples.YetAnotherBean"/>
-
wc,东西太多了,根本翻不完,形式太多,表达的又是相近的意思
最简单就直接
<bean id="Hello" class="com.haoyun.POJO.Hello">
<constructor-arg name="name" value="haoyun"/>
</bean>
真是没事找事
别名alias
<bean id="Hello" class="com.haoyun.POJO.Hello">
<constructor-arg name="name" value="haoyun"/>
</bean>
<alias name="Hello" alias="safsdf"/>
原来的名字也能用,别名也能用
这个又是没用的,直接再bean标签使用name也能起别名,里面的内容,用逗号或分号或空格都能起别名
<bean id="Hello" class="com.haoyun.POJO.Hello" name="hello afsdfaf,sadfasdf">
import配置文件
之前官网说一个正规的beans命名为applicationContext.xml,这是一个总的配置文件,项目中可以有多个配置文件,这样的好处是,可以由多个人编写,最后汇总,汇总到主配置文件applicationContext.xml
ApplicationContext classPathXmlApplicationContext = new ClassPathXmlApplicationContext("applicationContext.xml","Beans.xml");
创建ApplicationContext实例的时候可以选用多个配置文件