Spring概述 IOC容器和bean的配置
1、Spring概述
1.1、什么是Spring?
-
Spring 是一个开源框架.
-
Spring 为简化企业级应用开发而生. 使用 Spring 可以使简单的 JavaBean 实现以前只有 EJB 才能实现的功能.
-
Spring 是一个 IOC(DI) 和 AOP 容器框架.
-
Spring优良的特性
- 轻量:Spring 是非侵入性的 基于Spring开发的应用中的对象可以不依赖于Spring的API
- 依赖注入:DI——Dependency Injection,反转控制(IOC)最经典的实现。
- 面向切面编程:Aspect Oriented Programming——AOP
- 容器:Spring是一个容器,因为它包含并且管理应用对象的生命周期
- 框架:Spring实现了使用简单的组件配置组合成一个复杂的应用。在 Spring 中可以使用XML和Java注解组合这些对象。
- 一站式:在IOC和AOP的基础上可以整合各种企业应用的开源框架和优秀的第三方类库(实际上Spring 自身也提供了表述层的SpringMVC和持久层的Spring JDBC)。
-
Spring模块
1.2、Spring的第一个HelloWorld程序
这里是用maven建的项目导入Spring相关的依赖 maven帮我们自动下载(若不是用maven建的则自己导入Spring相关的jar包)
<dependencies> <!-- https://mvnrepository.com/artifact/org.springframework/spring-webmvc --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-webmvc</artifactId> <version>5.2.6.RELEASE</version> </dependency> </dependencies>
创建一个User实体类
public class User { private String name; public User() { } public User(String name) { this.name = name; } public String getName() { return name; } public void setName(String name) { this.name = name; } public void show(){ System.out.println("我的名字叫:"+name); } @Override public String toString() { return "User{" + "name='" + name + '\'' + '}'; } }
注意每次写这种实体类时 最好把无参构造方法写上
Spring配置文件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
https://www.springframework.org/schema/beans/spring-beans.xsd"> <!-- 使用bean元素定义一个由IOC容器创建的对象 --> <!--id:指定用于引用bean实例的标识--> <!--class:指定用于创建bean的全类名 --> <bean id="User" class="com.song.pojo.User"> <property name="name" value="王五"></property> </bean> </beans>
测试
public static void main(String[] args) { //创建IOC容器对象 ApplicationContext Context = new ClassPathXmlApplicationContext("ApplicationContext.xml"); //根据id值获取bean实例对象 User user = (User) Context.getBean("User"); user.show(); }
2、IOC容器和Bean配置
2.1、IOC和DI
-
IOC(Inversion of Control):反转控制。
其思想是反转资源获取的方向. 传统的资源查找方式要求组件向容器发起请求查找资源. 作为回应, 容器适时的返回资源. 而应用了 IOC 之后, 则是容器主动地将资源推送给它所管理的组件, 组件所要做的仅是选择一种合适的方式来接受资源. 这种行为也被称为查找的被动形式
-
DI(Dependency Injection):依赖注入。
IOC 的另一种表述方式:即组件以一些预先定义好的方式(例如: setter 方法)接受来自如容器的资源注入.相对于 IOC 而言,这种表述更直接
2.2、在 Spring 的 IOC 容器里配置 Bean
- 在 Spring IOC 容器读取 Bean 配置创建 Bean 实例之前, 必须对它进行实例化. 只有在容器实例化后, 才可以从 IOC 容器里获取 Bean 实例并使用.
- Spring 提供了两种类型的 IOC 容器实现.
–BeanFactory: IOC 容器的基本实现.
–ApplicationContext: 提供了更多的高级特性. 是 BeanFactory 的子接口.
–BeanFactory 是 Spring 框架的基础设施,面向 Spring 本身;ApplicationContext 面向使用 Spring 框架的开发者,几乎所有的 应用场合都直接使用 ApplicationContext 而非底层的 BeanFactory
–无论使用何种方式, 配置文件时相同的.
2.2.1、ApplicationContext
-
ApplicationContext 的主要实现类:
–ClassPathXmlApplicationContext:从 类路径下加载配置文件
–FileSystemXmlApplicationContext: 从文件系统中加载配置文件
-
ConfigurableApplicationContext 扩展于 ApplicationContext,新增加两个主要方法:refresh() 和 close(), 让 ApplicationContext 具有启动、刷新和关闭上下文的能力
-
ApplicationContext 在初始化上下文时就实例化所有单例的 Bean。
-
WebApplicationContext 是专门为 WEB 应用而准备的,它允许从相对于 WEB 根目录的路径中完成初始化工作
2.2.1、环境搭配置测试
建一个学生基本信息实体类
public class Student { private String name;//姓名 private Integer age;//年龄 private String books[];//上课的书籍 一个数组 private CourseTeacher courseTeacher; //每门课老师的姓名 private List<String> hobbys;//爱好 private Map<String,String> card;//每个学生的所在地邮政编号 private Set<String> games;//喜欢的游戏 private String girlfriend;//是否有女朋友 private Properties info; public String getName() { return name; } //等下用来测试构造方法注入的 public Student(String name) { this.name = name; } public void setName(String name) { this.name = name; } public Integer getAge() { return age; } public void setAge(Integer age) { this.age = age; } public String[] getBooks() { return books; } public void setBooks(String[] books) { this.books = books; } public CourseTeacher getCourseTeacher() { return courseTeacher; } public void setCourseTeacher(CourseTeacher courseTeacher) { this.courseTeacher = courseTeacher; } public List<String> getHobbys() { return hobbys; } public void setHobbys(List<String> hobbys) { this.hobbys = hobbys; } public Map<String, String> getCard() { return card; } public void setCard(Map<String, String> card) { this.card = card; } public Set<String> getGames() { return games; } public void setGames(Set<String> games) { this.games = games; } public String getGirlfriend() { return girlfriend; } public void setGirlfriend(String girlfriend) { this.girlfriend = girlfriend; } public Properties getInfo() { return info; } public void setInfo(Properties info) { this.info = info; } public Student() { } //若写courseTeacher.toString()则要把CourseTeacher中属性值写上 不然会出现空指针异常 @Override public String toString() { return "Student{" + "姓名='" + name + '\'' + ", 年龄=" + age + ", books=" + Arrays.toString(books) + ", courseTeacher=" + courseTeacher + ", 爱好=" + hobbys + ", card=" + card + ", games=" + games + ", girlfriend='" + girlfriend + '\'' + ", info=" + info + '}'; } }
//每门课程老师的名字 public class CourseTeacher { private String math; private String chinese; private String english; public CourseTeacher() { } public CourseTeacher(String math, String chinese, String english) { this.math = math; this.chinese = chinese; this.english = english; } public String getMath() { return math; } public void setMath(String math) { this.math = math; } public String getChinese() { return chinese; } public void setChinese(String chinese) { this.chinese = chinese; } public String getEnglish() { return english; } public void setEnglish(String english) { this.english = english; } @Override public String toString() { return "CourseTeacher{" + "math='" + math + '\'' + ", chinese='" + chinese + '\'' + ", english='" + english + '\'' + '}'; } }
基本注入
<!--常量注入--> <bean id="User" class="com.song.pojo.User"> <property name="name" value="李四"></property> </bean>
测试
@Test public void test01(){ ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml"); User user = (User) context.getBean("User"); System.out.println(user); }
引用其它 Bean注入
<!--引用其他bean 使用ref--> <bean id="CourseTeacher" class="com.song.pojo.CourseTeacher"> <property name="chinese" value="语文老师"></property> <property name="math" value="数学老师"></property> <property name="english" value="英语老师"></property> </bean> <bean id="student2" class="com.song.pojo.Student"> <property name="name" value="小黄"></property> <property name="courseTeacher" ref="CourseTeacher"></property> </bean>
测试
@Test public void test02(){ ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml"); Student student = (Student) context.getBean("student2"); System.out.println(student); }
数组注入
<!--数组注入--> <bean id="student3" class="com.song.pojo.Student"> <property name="books"> <array> <value>Java入门到精通</value> <value>go入门到精通</value> <value>C++入门到精通</value> <value>数据结构与算法</value> </array> </property> </bean>
List注入
<!--List注入--> <bean id="student4" class="com.song.pojo.Student"> <property name="hobbys"> <list> <value>打篮球</value> <value>看动漫</value> <value>听歌</value> </list> </property> </bean>
map注入
<!--Map注入--> <bean id="student5" class="com.song.pojo.Student"> <property name="card"> <map> <entry key="广州" value="1334"></entry> <entry key="湖北" value="43346"></entry> </map> </property> </bean>
set注入
<bean id="student6" class="com.song.pojo.Student"> <property name="games"> <set> <value>王者荣耀</value> <value>CF</value> <value>吃鸡</value> </set> </property> </bean>
null注入
<property name="girlfriend"><null/></property>
Propertise注入
<bean id="student7" class="com.song.pojo.Student"> <property name="info"> <props> <prop key="学号">20190604</prop> <prop key="系别">信息工程系</prop> <prop key="专业">软件工程</prop> </props> </property> </bean>
构造方法注入
<bean id="student7" class="com.song.pojo.Student"> <constructor-arg index="0" value="小张" ></constructor-arg> </bean>
索引值指定参数位置
综合使用
<bean id="student8" class="com.song.pojo.Student"> <constructor-arg value="小张" index="0"></constructor-arg> <property name="age" value="18"></property> <property name="books"> <array> <value>Java入门到精通</value> <value>go入门到精通</value> <value>C++入门到精通</value> <value>数据结构与算法</value> </array> </property> <property name="courseTeacher" ref="CourseTeacher"></property> <property name="hobbys"> <list> <value>打篮球</value> <value>看动漫</value> <value>听歌</value> </list> </property> <property name="card"> <map> <entry key="广州" value="1334"></entry> <entry key="湖北" value="43346"></entry> </map> </property> <property name="games"> <set> <value>王者荣耀</value> <value>CF</value> <value>吃鸡</value> </set> </property> <property name="info"> <props> <prop key="学号">20190604</prop> <prop key="系别">信息工程系</prop> <prop key="专业">软件工程</prop> </props> </property> <property name="girlfriend"><null/></property> </bean>
//测试结果
Student{
姓名='小张',
年龄=18,
books=[Java入门到精通, go入门到精通, C++入门到精通, 数据结构与算法],
courseTeacher=CourseTeacher{math='数学老师', chinese='语文老师', english='英语老师'},
爱好=[打篮球, 看动漫, 听歌],
card={广州=1334, 湖北=43346},
games=[王者荣耀, CF, 吃鸡],
girlfriend='null',
info={学号=20190604, 专业=软件工程, 系别=信息工程系}
}
还有一种工厂方法注入 用得少
2.3、bean的高级配置
-
配置信息的继承
-
配置信息的继承
Spring允许继承bean的配置,被继承的bean称为父bean。继承这个父bean的bean称为子bean
子bean从父bean中继承配置,包括bean的属性配置
子bean也可以覆盖从父bean继承过来的配置
-
父bean可以作为配置模板,也可以作为bean实例。若只想把父bean作为模板,可以设置的abstract 属性为true,这样Spring将不会实例化这个bean
如果一个bean的class属性没有指定,则必须是抽象bean
并不是元素里的所有属性都会被继承。比如:autowire,abstract等。
也可以忽略父bean的class属性,让子bean指定自己的类,而共享相同的属性配置。但此时abstract必须设为true
2.3.1、bean之间的依赖
有的时候创建一个bean的时候需要保证另外一个bean也被创建,这时我们称前面的bean对后面的bean有依赖
依赖关系不等于引用关系
2.3.2、bean的作用域
在Spring中,可以在元素的scope属性里设置bean的作用域,以决定这个bean是单实例的还是多实例的。
默认情况下,Spring只为每个在IOC容器里声明的bean创建唯一一个实例,整个IOC容器范围内都能共享该实例:所有后续的getBean()调用和bean引用都将返回这个唯一的bean实例。该作用域被称为singleton,它是所有bean的默认作用域。
当bean的作用域为单例时,Spring会在IOC容器对象创建时就创建bean的对象实例。而当bean的作用域为prototype时,IOC容器在获取bean的实例时创建bean的实例对象。
2.3.3、bean的生命周期
-
Spring IOC容器可以管理bean的生命周期,Spring允许在bean生命周期内特定的时间点执行指定的任务。
-
Spring IOC容器对bean的生命周期进行管理的过程:
-
在配置bean时,通过init-method和destroy-method 属性为bean指定初始化和销毁方法
- 通过构造器或工厂方法创建bean实例
- 为bean的属性设置值和对其他bean的引用
- 调用bean的初始化方法
- bean可以使用了
- 当容器关闭时,调用bean的销毁方法
-
bean的后置处理器
- bean后置处理器允许在调用初始化方法前后对bean进行额外的处理
- bean后置处理器对IOC容器里的所有bean实例逐一处理,而非单一实例。其典型应用是:检查bean属性的正确性或根据特定的标准更改bean的属性。
-
bean后置处理器时需要实现接口:org.springframework.beans.factory.config.BeanPostProcessor。在初始化方法被调用前后,Spring将把每个bean实例分别传递给上述接口的以下两个方法:
- postProcessBeforeInitialization(Object, String)
- postProcessAfterInitialization(Object, String)
5.添加bean后置处理器后bean的生命周期
- 通过构造器或工厂方法**创建****bean实例
- 为bean的属性设置值和对其他bean的引用
- 将bean实例传递给bean后置处理器的postProcessBeforeInitialization()方法
- 调用bean的初始化方法
- 将bean实例传递给bean后置处理器的postProcessAfterInitialization()**方法
- bean可以使用了
- 当容器关闭时调用bean的销毁方法
若想了解更多的Spring建议查看 Spring官网
本文地址:https://blog.csdn.net/qq_44763720/article/details/107678073
推荐阅读
-
02Spring基于xml的IOC配置--实例化Bean的三种方式
-
Spring—IOC容器中Bean的生命周期方法
-
Spring 框架的概述以及Spring中基于XML的IOC配置
-
Spring IOC DI依赖注入 IOC容器 Spring Bean的声明周期
-
spring bean 的生命周期和配置源信息
-
Spring在IOC容器中,使用配置文件创建对象,基本思路是什么样的?
-
Spring IOC容器装配Bean_基于注解配置方式
-
Spring概述 IOC容器和bean的配置
-
Spring IOC容器装配Bean_基于XML配置方式
-
Spring源码分析-从@ComponentScan注解配置包扫描路径到IoC容器中的BeanDefinition,经历了什么(一)?