目录
- 初识 Spring
- 总结
- DI(依赖注入)
- Spring 项目的创建
- 创建一个 Maven 项目
- 添加 Spring 框架支持
- 添加启动类
- 存储 bean 对象
- 创建 bean
- 将 bean 注册到容器中
- 获取并使用 bean 对象
- 获取 bean 的方法一
- 获取 bean 的方法二
- 获取 bean 的方法三
- ApplicationContext 和 BeanFactory 的区别 (重点)
- 总结
初识 Spring
Spring 是包含众多工具方法的 IoC 容器.
容器就是存储用的, 比如像以前学的 List / Map 就是存储数据的容器, 再像 Tomcat 就是 Web 容器.
容器最核心就是两点 : 存储和获取.
那 IoC 容器又是啥意思呢 ?
IoC = Inversion of Control 就是 “控制(权)反转” 的意思.
理解 :
以往我们获取对象都是通过 new 关键字来创建对象并获取的, 这样通过自己写代码控制类对象的生命周期, 我们是掌握对象控制权的, 而控制权反转就是指控制权不交由程序员控制了, 而是由 Spring(Spring容器 / IoC容器) 来控制.
IoC 容器就是存放 bean(对象) 的容器, 我们如果需要就去容器获取, 不需要自己 new 对象了.
这样有什么好处呢 ?
对代码进行解耦, 即使底层类发生改变, 整个调用链都不需要改动, 使程序设计更加通用, 灵活.
举个例字 :
我有两个类 :
public class B {private int b = 25;public B() {System.out.println("b : " + b);}
}
public class A {public A() {B b = new B(); // A 类依赖 B 类}
}
测试类 :
public class Test {public static void main(String[] args) {A a = new A(); //传统是直接 new 对象}
}
如果我要对 B 类的 b 进行修改, 那只能修改底层的 B 类代码 :
public class B {private int b = 25;public B(int m) {b = m;System.out.println("b : " + b);}
}
B 的构造方法变了, A 类的构造方法也要变 :
public class A {public A(int m) {B b = new B(m);}
}
测试类 :
public class Test {public static void main(String[] args) {A a = new A(66);}
}
我们只是改动底层代码一点点, 就牵一发而动全身了, 这显然很麻烦, 它们的耦合太强了, IoC 容器就解决了这一点, 让程序员修改底层代码而不动整个调用链.
总结
Spring 是⼀个 IoC 容器,对象的创建和销毁都交给 Spring 来管理了,它本身⼜具备了存储对象和获取对象的能⼒。
DI(依赖注入)
DI 是 Dependency Injection 的缩写, 翻译成中⽂是“依赖注⼊”的意思.
所谓依赖注⼊, 就是由 IoC 容器在运⾏期间, 动态地将某种依赖关系注⼊到对象之中.
DI 与 IoC 区别:
DI 和 IoC 是从不同角度描述同一件事情,IoC 是一种思想,它就是要实现对像解耦,不管用什么样的方法;DI 则是一种具体手段,来实现对象解耦.
Spring 项目的创建
创建一个 Maven 项目
添加 Spring 框架支持
在项⽬的 pom.xml 中添加 Spring 框架的⽀持,xml 配置如下 :
<dependencies><dependency><groupId>org.springframework</groupId><artifactId>spring-context</artifactId><version>5.2.3.RELEASE</version></dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-beans</artifactId><version>5.2.3.RELEASE</version></dependency>
</dependencies>
添加的框架有 spring-context:spring 上下⽂,还有 spring-beans:管理对象的模块。
注意 : 这里只是声明要这些依赖, 以及依赖所在地, 并不是添加完上述代码就添加完了依赖, 还得刷新一下, 让 idea 去下载这些依赖.
添加启动类
最后在创建好的项⽬ java ⽂件夹下创建⼀个启动类,包含 main ⽅法即可:
public class App {public static void main(String[] args) {}
}
存储 bean 对象
想存储 bean 对象, 首先得有 bean 才行, 因此首先得创建一个 bean, 然后将 bean 注册到 Spring 容器中.
创建 bean
bean 就是 Java 中 一个普通对象, 创建 bean 就是创建对象.
将 bean 注册到容器中
在创建好的项⽬中添加 Spring 配置⽂件 spring-config.xml,将此⽂件放到 resources 的根⽬录下,
如下图所示:
在 spring-config.xml 中添加 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: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">
</beans>
再将 Student 对象注册到 Spring 中就可以,具体操作如下:
注意 :
class 是对应你要注册的类的路径, 当我们获取 bean 的时候就会去这个路径中扫描, 如果扫描不到就会报错;
id 这里是可以随便取的, 只是给这个路径中注册的 bean 对象取个名字, 方便后续获取.
如果存在多个 bean 需注册, 则添加多个 < bean > 标签
获取并使用 bean 对象
获取并使⽤ Bean 对象,分为以下 3 步:
- 得到 Spring 上下⽂对象,因为对象都交给 Spring 管理了,所以获取对象要从 Spring 中获取,那
么就得先得到 Spring 的上下⽂。 - 通过 Spring 上下⽂,获取某⼀个指定的 Bean 对象。
- 使⽤ Bean 对象。
获取 bean 的方法一
public class App {public static void main(String[] args) {//1. 获取 spring 上下文对象, 注意后面需填写添加配置的文件名称ApplicationContext context = new ClassPathXmlApplicationContext("spring-config.xml");//2. 获取 bean 对象, 后面的字符串要与我们之前取的名字相匹配, // 获取到的 bean 是 object 类型的, 需强制类型转换Student student = (Student)context.getBean("student");//检验对象是否获取到System.out.println(student.sayHi("佩奇"));}
}
获取 bean 的方法二
public class App {public static void main(String[] args) {ApplicationContext context = new ClassPathXmlApplicationContext("spring-config.xml");//这里是直接通过类类型来获取 bean 对象, 所以返回的值不需要转换Student student = context.getBean(Student.class);//Student student = (Student)context.getBean("student");System.out.println(student.sayHi("佩奇"));}
}
当我们 Student 仅有一个 bean 对象时, 这样直接通过类名来获取 bean 对象显然没问题, 但若 Student 存在多个 bean 对象呢 ? 它会获取到哪个 bean 对象呢 ?
这里我们载注册一个 Student 类的 bean 对象, 并取名为 student2.
来看看获取效果 :
报错信息是 : 找到两个匹配结果, 但它只期望有一个结果.
如果是用 id 来获取就不会出现这种情况了, 因为每个 bean 都有唯一的 id.
获取 bean 的方法三
public class App {public static void main(String[] args) {ApplicationContext context = new ClassPathXmlApplicationContext("spring-config.xml");//通过 id 获取 bean, 并将所得 bean 转为 Student 类型, 无需类型转换了Student student = context.getBean("student", Student.class);//Student student = context.getBean(Student.class);//Student student = (Student)context.getBean("student");System.out.println(student.sayHi("佩奇"));}
}
ApplicationContext 和 BeanFactory 的区别 (重点)
其实 BeanFactory 也可以获取 Bean 对象.
public class App {public static void main(String[] args) {BeanFactory context = new XmlBeanFactory(new ClassPathResource("spring-config.xml"));//ApplicationContext context = new ClassPathXmlApplicationContext("spring-config.xml");//通过 id 获取 bean, 并将所得 bean 转为 Student 类型, 无需类型转换了Student student = context.getBean("student", Student.class);//Student student = context.getBean(Student.class);//Student student = (Student)context.getBean("student");System.out.println(student.sayHi("佩奇"));}
}
ApplicationContext 和 BeanFactory 效果是⼀样的, 那它们之间的区别是什么呢 ?
区别 :
- ApplicationContext 是 BeanFactory 的子类, ApplicationContext 不仅拥有父类的所有方法, 还扩展了很多父类没有的方法. (国际化支持、资源访问支持、事件传播支持等)
- ApplicationContext 是⼀次性加载并初始化所有的 Bean 对象, ⽽ BeanFactory 是懒加载(需要哪个才去加载哪个), 因此更加轻量.
总结
- 操作容器之前, 先要有容器, 所以先要得到容器.
- 存对象
a. 创建 Bean (普通类).
b. 将 Bean 注册(配置)到 spring-confing.xml 中. - 取对象
a. 得到 Spring 上下⽂, 并读取到 Spring 的配置⽂件.
b. 获取某⼀个 Bean 对象.
c. 使⽤ Bean 对象.