初识Spring
spring Framework 简称 spring,spring是学习Java人
最常使用的框架之一!对于spring的作用,我们主要以原理和使用两个方面进行讨论。
spring原理
首先是原理,spring Framework(开源框架)是一个包含了众多工具的Ioc
容器。
容器是什么?
可以用来存放物品的东西,比如我们的水杯,笔筒,麻袋和包包都是容器。
那么
Ioc
是什么?
Ioc
是控制反转,将原来程序创建Bean(核心)的权力反转给第三方,起到最大的作用就是解耦合。
比方有一个行李箱制造商需要制作一个行李箱时的顺序:
- 制定轮子
- 制定内部结构
- 制定外部封皮
- 制作拉杆
一共是四步,使用代码来解释时(读者最好分许多个文件声明其中类作为每个操作步骤):
public class Test {
public static void main(String[] args) {
System.out.println("开始制作一个行李箱");
Rod rod = new Rod();//创建一个行李箱对象
}
}
//制作拉杆完成就造出一个行李箱
class Rod {
public Rod() {
//需要调用一个制作封皮好了的行李箱
Wrapped wrapped = new Wrapped();
System.out.println("制作拉杆完成");
}
}
//封皮
class Wrapped {
public Wrapped() {
//需要得到一个内部已经做好的行李箱
Within within = new Within();
System.out.println("制作外部封皮完成");
}
}
//内部制作
class Within {
//需要得到一个安装好轮子的底部
public Within() {
Wheel wheel = new Wheel();
System.out.println("制作箱子内部结构完成");
}
}
//安装轮子
class Wheel {
public Wheel() {
System.out.println("制作轮子完成");
}
}
在市场上大部分的行李箱都有大小限制,而随着行李箱的改变轮子大小也会发生改变,这里使用轮子的大小来设定行李箱的大小,所以我们设置一个数值作为尺寸进行传递,。
//做一个20寸的箱子
public class Test {
public static void main(String[] args) {
System.out.println("开始制作一个行李箱");
Rod rod = new Rod(20);
}
}
//制作拉杆完成就造出一个行李箱
class Rod {
public Rod(int size) {
//需要调用一个制作封皮好了的行李箱
Wrapped wrapped = new Wrapped(size);
System.out.println("制作拉杆完成");
}
}
//封皮
class Wrapped {
public Wrapped(int size) {
//需要得到一个内部已经做好的行李箱
Within within = new Within(size);
System.out.println("制作外部封皮完成");
}
}
//内部制作
class Within {
//需要得到一个安装好轮子的底部
public Within(int size) {
Wheel wheel = new Wheel(size);
System.out.println("制作箱子内部结构完成");
}
}
//制作轮子
class Wheel {
public Wheel(int size) {
System.out.println("制作轮子完成,尺寸:"+size);
}
}
以上的代码可以发现,当我们传递一个数值之后,每个代码都需要改变。产生了一些不需要的工作量。我们需要如何改进这个代码,使得我们只需要改一次就能遍布全局,而其中的关键就在于将对象的生命周期进行反转!
//关键因素在于理解工具的传递,组装时只需要提供工具即可,而不需要更新工具的其他因素
public class Test {
public static void main(String[] args) {
System.out.println("开始制作一个行李箱");
Wheel wheel = new Wheel();
Within within = new Within(wheel);
Wrapped wrapped = new Wrapped(within);
Rod rod = new Rod(wrapped);
}
}
class Rod {
public Rod(Wrapped wrapped) {
System.out.println("制作拉杆完成");
}
}
class Wrapped {
public Wrapped(Within within) {
System.out.println("制作外部封皮完成");
}
}
class Within {
public Within(Wheel wheel) {
System.out.println("制作箱子内部结构完成");
}
}
class Wheel {
public Wheel() {
System.out.println("制作轮子完成,尺寸");
}
}
如果需要改变尺寸只需要修改Wheel
类的参数即可。
这就是Ioc
的特点,将一个对象的生命周期控制权进行传递。当制作一个行李箱时,原本的步骤是自己建造一个部分然后组装该部分再传递到下一个部分进行制作和组装,而现在只管制作,不管组装,大大提高的解耦和。
综上所述,
Spring Ioc
是一个对生命周期的托管器。
从功能角度来看,主要是分为两个:
- 把对象存入容器
- 把对象从容器中取出
DI依赖注入
在spring中除了Ioc
容器,还有一个是==DI(Dependency injection)
依赖注入==。
依赖注入指的是:在程序运行期间,动态地将对象引入当前类的行为机制。
比如在maven中的dependency就是这个效果,将我们需要使用的包引入到程序中。
Ioc与DI的比较
在广义的角度分析:Ioc
与DI
功能是一样的,从不同的角度解决同一个问题。
在狭义的角度分析: Ioc
的设计思想与DI
是不同的,而且他们的底层逻辑也是不同的。
Bean的使用
bean
是spring
存储对象的一种方式。Bean
是使用xml
文件和实体类进行关系加载使用的一种方法。
- 创建一个普通maven项目,添加以下依赖到
pom.xml
中
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.2.6.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
<version>5.2.6.RELEASE</version>
</dependency>
</dependencies>
- 相对于将maven对象变成spring框架
- 创建一个实体类User
public class User {
private String name;
private String password;
}
//添加geter,seter和toString方法
- 在resources中创建配置文件
spring-config.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:content="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd">
<content:component-scan base-package="com.component"></content:component-scan>
</beans>
- 创建bean对象语法格式
<bean class="类名" id="调用时的对象名"></bean>
- 创建一个main启动函数,创建对象调用bean对象,这里我们使用
ApplicationContext
对象来初始化配置文件
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("spring-config.xml");
}
- 接下来就可以使用
context
来获取spring-config.xml
中的对象
获取Bean的三种方法
从spring
获取bean
对象有三种方法:
当然在取出之前,应该先注入一个bean对象,根据以上的语法规则,我们可以写出如下代码将User
注入。
<bean class = "User" id = "user"></bean>
- 直接取出bean中id的名称
User user = (User)context.getBean("user");//使用bean名称来得到bean对象
- 使用bean类型来得到bean对象
User user1 = context.getBean(User.class);//使用bean类型来获取bean对象
- 使用bean名称加bean类型来得到bean对象
User user = context.getBean("user",User.class);//使用bean名称+bean类型获取bean对象,更安全
三种方法的比较
三种方法都可以取出bean对象,那么那种方法最合理呢?
第三种!
我们观察在第一种取出对象的方法中使用了强制转换,意味着当取出对象时会被直接转换为一个对象,试想一下,如果并没有取出bean对象时,返回null,null值将会被转换为一个对象,显然会出现异常。
第二种的不合理之处在于,当在bean中如果存在两个对象都引用了bean对象,会出现异常。
再添加一个对象注入
<bean class="User" id="user"></bean>
<bean class="User" id="user01"></bean>
当执行第二种获取对象方法时就会出现一下异常信息。
意思是,在文件中找到两个,不能确定是哪个对象。
而第三种方案规避了这两个风险的存在,所以一般我们使用bean都是使用第三种方法,也就是,bean名称+bean类型一起得到bean对象。