Spring
1. Spring简介
1.1 什么是Spring
-
Spring框架是一个开源、非入侵式、轻量级应用程序框架, 由Rod Johnson发起,是针对bean的生命周期进行管理的轻量级容器(lightweight container)。
-
Spring框架主要由七部分组成,分别是 Spring Core、 Spring AOP、 Spring ORM、 Spring DAO、Spring Context、 Spring Web和 Spring Web MVC。
-
设计理念:解决企业级开发的复杂性。拥有强大的向后兼容性。
-
2002年,首次推出了Spring框架的雏形:interface21.
-
Spring框架以interface21为基础,不断丰富于2004年3月24日发布了1.0正式版本。
-
Rod Johnson, Spring Framework创始人,著名作者。 在尼大学不仅获得了计算机学位,同时还获得了音乐学位。更令人吃惊的是在回到软件开发领域之前,他还获得了音乐学的博士学位。很难想象Rod Johnson的学历,真的让好多人大吃一惊,他是悉尼大学的博士,然而他的专业不是计算机,而是音乐学。
-
SSM:SpringMVC + Spring + Mybatis
1.2 如何获取Spring
官网: https://spring.io/projects/spring-framework
gitHub: https://github.com/spring-projects/spring-framework
1.3 Spring组成
-
Spring Core:是框架的最基础部分,并提供依赖注入(Dependency Injection)管理Bean容器功能。
-
Spring Context:构建于Core包上,提供了一种框架式访问对象的方式,有些像JNDI注册。Context封装包继承了beans包的功能,还增加了国际化(I18N),事件传播,资源装载,以及透明创建上下文,例如通过servlet容器。
-
Spring DAO:提供了JDBC的抽象层,它可消除冗长的JDBC编码和解析数据库厂商特有的错误代码。并且,JDBC封装包还提供了一种比编程性更好的声明性事务管理方法,不仅仅是实现了特定接口,而且对所有的POJOs都适用。
-
Spring ORM:流行的“关系/对象”映射APIs提供了集成层,包括JDO,hibernate和iBatis。通过ORM包,可以混合使用所有Spring提供的特性进行“对象/关系”映射,如前边提到的简单声明性事务管理。
-
Spring AOP:提供了符合AOP Alliance规范的面向方面的编程实现,例如方法拦截器(method-interceptors)和切点(pointcuts),从逻辑上讲,从而减弱代码的功能耦合,清晰的被分离开。
-
Spring Web:提供了基本的面向Web的综合特性,例如多方文件上传,利用Servlet listeners进行IoC容器初始化和针对Web的applicationcontext。当与WebWork或Struts一起使用Spring时,这个包使Spring可与其他框架结合。
-
Spring Web MVC:提供了面向Web应用的Model-View-Controller实现。Spring的MVC框架并不是仅仅提供一种传统的实现,它提供了一种清晰的分离模型,在领域模型代码和web form之间。并且,还可以借助Spring框架的其他特性。
1.4 Spring插件的安装
1.4.1 下载插件包
先确定eclipse的版本号,下载对应的插件包。
1.4.2 安装插件包
-
Help --> install new software
-
window --> preferences 下面能看到Spring模块说明安装成功。
2. IOC
2.1 IOC概述
IOC( Inverse of Control )翻译为控制反转。不是什么技术,而是一种设计思想,就是将原本在程序中手动创建对象的控制权,交由Spring框架来管理。
2.2 举个栗子
控制反转显然是一个抽象的概念,我们举一个鲜明的例子来说明。
在现实生活中,人们要用到一样东西的时候,第一反应就是去找到这件东西,比如想喝新鲜橙汁,在没有饮品店的日子里,最直观的做法就是:买果汁机、买橙子,然后准备开水。值得注意的是:这些都是你自己“主动”创造的过程,也就是说一杯橙汁需要你自己创造。
然而到了今时今日,由于饮品店的盛行,当我们想喝橙汁时,第一想法就转换成了找到饮品店的联系方式,通过电话等渠道描述你的需要、地址、联系方式等,下订单等待,过一会儿就会有人送来橙汁了。
请注意你并没有“主动”去创造橙汁,橙汁是由饮品店创造的,而不是你,然而也完全达到了你的要求,甚至比你创造的要好上那么一些。
这就是一种控制反转的理念,上述的例子已经很好的说明了问题,我们再来描述一下控制反转的概念:控制反转是一种通过描述(在 Java 中可以是 XML 或者注解)并通过第三方(Spring)去产生或获取特定对象的方式。
2.3 Spring IoC容器
Spring 会提供 IoC 容器来管理和容纳我们所开发的各种各样的 Bean,并且我们可以从中获取各种发布在 Spring IoC 容器里的 Bean,并且通过描述可以得到它。
2.4 优点
解耦!解耦!!解耦!!!解耦!!!!
案例参考:Spring-ioc-demo
3. 第一个Spring程序
3.1 引入依赖
需要什么模块加什么模块
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.2.4.RELEASE</version>
</dependency>
3.2 定义Java类
public class Student {
private String name ;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public void study(){
System.out.println("好好学习,天天向上。");
}
@Override
public String toString() {
return "Student [name=" + name + "]";
}
}
3.3 配置bean
resources目录下新建配置文件applicationContext.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">
<bean id="student" class="com.blb.spring.Student">
<property name="name" value="seven" />
</bean>
</beans>
3.4 测试
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
Student student = (Student) context.getBean("student");
System.out.println(student.getName());
student.study();
思考:
- 步骤3.2中定义的Student类中可以定义一个带参构造方法吗?为什么?
- 自己写个IOC容器?
4. IOC创建对象的方式
-
通过无参构造方法(默认),属性通过setter方法(默认)
-
有参构造方法
-
第1种:下标匹配
<bean id="student" class="com.blb.spring.Student"> <!-- index表示下标,0:第一个参数。value要传入的参数值 --> <constructor-arg index="0" value="seven"></constructor-arg> </bean>
-
第2种:类型匹配
<bean id="student" class="com.blb.spring.Student"> <!-- type表示根据参数类型来查找参数;value要传入的参数值 --> <constructor-arg type="java.lang.String" value="seven"></constructor-arg> </bean>
如果参数列表有多个相同类型的话就无法匹配上了,故不推荐此种方式。
-
第3种:参数名匹配
<bean id="student" class="com.blb.spring.Student"> <!-- name表示根据参数名称来查找参数;value要传入的参数值 --> <constructor-arg name="name" value="seven"></constructor-arg> </bean>
总结:
- applicationContext.xml中定义的bean是在容器启动的时候就已经实例化好里面的对象了,而不是在
context.getBean用的时候才实例化。
- 容器默认实例化是一个对象,多次context.getBean获取到的对象都是同一个。
5. Spring配置
5.1 别名
- 我们可以给实例添加别名,在getBean的时候也可以用别名来获取了.
<alias name="student" alias="user" />
5.2 bean的配置
<bean id="student" class="com.blb.spring.Student" name="s1,s2 s3;s4" >
<constructor-arg name="name" value="seven"></constructor-arg>
</bean>
- id:bean的唯一标识符,相当于我们取的对象名
- class:bean对应的全限定名: 包名+类名
- name:也是别名,而且可以取多个别名,多个别名之间可以用空格、逗号、封号隔开。
5.3 import
import用于协同开发中,将多个配置文件合并到一个中。比如applicationContext.xml中
<import resource="bean1.xml"/>
<import resource="bean2.xml"/>
-
表示把bean1.xml跟bean2.xml中的配置都引入到当前文件中。
-
当有冲突的时候按照顺序后面覆盖前面的原则。
5.4 scope(作用域)
5.4.1 单例模式(默认)
- 单例模式下容器只会创建一个实例,每次从容器中获取的都是同一个对象
<bean id="student" class="com.blb.spring.Student" scope="singleton" >
<property name="name" value="seven" />
</bean>
5.4.2 原型模式
- 原型模式下每次从容器中获取的都是一个新的对象
<bean id="student" class="com.blb.spring.Student" scope="prototype" >
<property name="name" value="seven" />
</bean>
5.4.3 其它
- request、session、application只会在web项目中才能使用。
6. 依赖注入
-
依赖注入(DI): Dependency Injection
-
把有依赖关系的类放到容器中,解析出这些类的实例,就是依赖注入。
-
依赖注入是实现IOC的一种方式。
-
IoC可以认为是一种全新的设计模式,但是理论和时间成熟相对较晚,并没有包含在GoF中。
6.1 构造器注入
已经讲过
6.2 Set注入
-
bean定义
public class Student { private String name ; private String wife ; private int age ; private Course course ; private String [] hobby ; private List<String> game ; private Map<String,String> address ; private Set<String> girlFriends ; private Properties info ; // getter/setter/toString }
public class Course { private String name ; private String teacherName ; // getter/setter/toString }
-
bean.xml
<!-- 定义Sourse实例 --> <bean id="course" class="com.blb.spring.Course"> <property name="courseName" value="百里半JAVA"/> <property name="teacherName" value="seven" /> </bean> <!-- 定义Student实例 --> <bean id="student" class="com.blb.spring.Student" > <!-- 普通值注入 --> <property name="name" value="张三"/> <!-- null值注入 --> <property name="wife"> <null/> </property> <!-- 普通值注入 --> <property name="age" value="18"/> <!-- 引用类型注入 --> <property name="course" ref="course" /> <!-- 数组值注入 --> <property name="hobby"> <array> <value>打球</value> <value>打游戏</value> <value>看电影</value> </array> </property> <!-- List值注入 --> <property name="game"> <list> <value>王者荣耀</value> <value>地下城勇士</value> <value>吃鸡</value> </list> </property> <!-- Map值注入 --> <property name="address"> <map> <entry key="addr1" value="武汉" /> <entry key="addr2" value="随州" /> <entry key="addr3" value="深圳" /> </map> </property> <!-- Set值注入 --> <property name="girlFriends"> <set > <value>小红</value> <value>小丽</value> <value>小王</value> </set> </property> <!-- prop值注入 --> <property name="info"> <props> <prop key="age">18</prop> <prop key="height">180</prop> <prop key="weight" >180</prop> </props> </property> </bean>
-
测试
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml"); Student student = context.getBean("student",Student.class); System.out.println(student);
6.3 拓展方式注入
-
P命名空间注入:使用setter方式
-
bean:
public class Student { private String name ; private int age ; private Course course ; // getter/setter/toString }
-
导入P命名空间
xmlns:p="http://www.springframework.org/schema/p"
-
bean.xml
<bean id="course" class="com.blb.spring.Course"> <property name="courseName" value="百里半JAVA"/> <property name="teacherName" value
-