Enterprise-level Spring-探索Spring-从入门到入厂
Posted man_one
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Enterprise-level Spring-探索Spring-从入门到入厂相关的知识,希望对你有一定的参考价值。
目录
3.1.5 BeanFactory 和 ApplicationContext 的区别:
3.2 依赖注入(Dependency Injection,DI)
一、Spring简介
Spring 使创建 Java 企业应用程序变得容易。它提供了在企业环境中使用 Java 语言所需的一切,并支持 Groovy 和 Kotlin 作为 JVM 上的替代语言,并且可以根据应用程序的需求灵活地创建多种体系结构。从 Spring Framework 5.0 开始,Spring 需要 JDK 8(Java SE 8),并且已经为 JDK 9 提供了现成的支持。如图1-1
图1-1 Spring发展史
Spring 支持广泛的应用场景。在大型企业中,应用程序通常存在很长时间,并且必须在升级周期不受开发人员控制的 JDK 和应用程序服务器上运行。其他服务器则可以作为单个 jar 运行,并且服务器可以嵌入云环境中。还有一些可能是不需要服务器的独立应用程序(例如批处理或集成工作负载)。
Spring 是开源的。它拥有一个庞大而活跃的社区,可以根据各种实际用例提供持续的反馈。这帮助 Spring 在很长一段时间内成功地 Developing 了。
GitHub社区:https://github.com/spring-projects
Spring 中文 文档:Spring Framework 中文文档 - Spring 框架概述 | Docs4devSpring 是一个开放源代码的设计层面框架,它解决的是业务逻辑层和其他各层的松耦合问题,因此它将面向接口的编程思想贯穿整个系统应用。Spring是于2003 年兴起的一个轻量级的Java 开发框架,由Rod Johnson创建。简单来说,Spring是一个分层的JavaSE/EE full-stack(一站式) 轻量级开源框架。https://www.docs4dev.com/docs/zh/spring-framework/5.1.3.RELEASE/reference/overview.html#overview-spring
官网 : Spring | Home
官方下载地址 : JFrog
Spring优势
| ------------------------ | -------- |
| 方便解耦,简化开发 | |
| 方便集成各种优秀框架 | |
| 方便程序的测试 | |
| AOP编程的支持 | |
| 声明式事务的支持 | |
| 降低JavaEE API的使用难度 | |
| Java源码是经典学习范例 | |
图 1-2 Spring的优势作用
二、Spring体系结构
图 2-1 Spring体系结构
三、Core contaainer(核心容器)
-
核心容器:核心容器提供 Spring 框架的基本功能。核心容器的主要组件是 BeanFactory,它是工厂模式的实现。BeanFactory 使用控制反转(IOC) 模式将应用程序的配置和依赖性规范与实际的应用程序代码分开。
-
Spring 上下文:Spring 上下文是一个配置文件,向 Spring 框架提供上下文信息。Spring 上下文包括企业服务,例如 JNDI、EJB、电子邮件、国际化、校验和调度功能。
-
Spring AOP:通过配置管理特性,Spring AOP 模块直接将面向切面的编程功能 , 集成到了 Spring 框架中。所以,可以很容易地使 Spring 框架管理任何支持 AOP的对象。Spring AOP 模块为基于 Spring 的应用程序中的对象提供了事务管理服务。通过使用 Spring AOP,不用依赖组件,就可以将声明性事务管理集成到应用程序中。
-
Spring DAO:JDBC DAO 抽象层提供了有意义的异常层次结构,可用该结构来管理异常处理和不同数据库供应商抛出的错误消息。异常层次结构简化了错误处理,并且极大地降低了需要编写的异常代码数量(例如打开和关闭连接)。Spring DAO 的面向 JDBC 的异常遵从通用的 DAO 异常层次结构。
-
Spring ORM:Spring 框架插入了若干个 ORM 框架,从而提供了 ORM 的对象关系工具,其中包括 JDO、Hibernate 和 iBatis SQL Map。所有这些都遵从 Spring 的通用事务和 DAO 异常层次结构。
-
Spring Web 模块:Web 上下文模块建立在应用程序上下文模块之上,为基于 Web 的应用程序提供了上下文。所以,Spring 框架支持与 Jakarta Struts 的集成。Web 模块还简化了处理多部分请求以及将请求参数绑定到域对象的工作。
-
Spring MVC 框架:MVC 框架是一个全功能的构建 Web 应用程序的 MVC 实现。通过策略接口,MVC 框架变成为高度可配置的,MVC 容纳了大量视图技术,其中包括 JSP、Velocity、Tiles、iText 和 POI。
3.1 IoC 容器
3.1.1IoC容器概述
- IoC(Inversion Of Control)控制反转,Spring反向控制应用程序所需要使用的外部资源
- Spring控制的资源全部放置在Spring容器中,该容器称为IoC容器
IoC是Spring框架的核心内容,使用多种方式完美的实现了IoC,可以使用XML配置,也可以使用注解,新版本的Spring也可以零配置实现IoC。
Spring容器在初始化时先读取配置文件,根据配置文件或元数据创建与组织对象存入容器中,程序使用时再从Ioc容器中取出需要的对象。
控制反转IoC(Inversion of Control),是一种设计思想,DI(依赖注入)是实现IoC的一种方法,也有人认为DI只是IoC的另一种说法。没有IoC的程序中 , 我们使用面向对象编程 , 对象的创建与对象间的依赖关系完全硬编码在程序中,对象的创建由程序自己控制,控制反转后将对象的创建转移给第三方,个人认为所谓控制反转就是:获得依赖对象的方式反转了。(狂神说java)
图3-1 IOC容器
IoC是Spring框架的核心内容,使用多种方式完美的实现了IoC,可以使用XML配置,也可以使用注解,新版本的Spring也可以零配置实现IoC。
Spring容器在初始化时先读取配置文件,根据配置文件或元数据创建与组织对象存入容器中,程序使用时再从Ioc容器中取出需要的对象。
ctrl+V了这么多废话,终于可以说重点了!
3.1.2 Spring IOC的两个容器
对于 IoC 来说,最重要的就是容器。容器管理着 Bean 的生命周期,控制着 Bean 的依赖注入。
那么, Spring 如何设计容器的呢?
Spring 作者 Rod Johnson 设计了两个接口用以表示容器。
-
BeanFactory
-
ApplicationContext
BeanFactory
E西好用!,是就是个 HashMap,Key 是 BeanName,Value 是 Bean 实例。
ApplicationContext
可以称之为 “高级容器”。因为他比 BeanFactory 多了更多的功能。他继承了多个接口。因此具备了更多的功能。例如资源的获取,支持多种消息(例如 JSP tag 的支持),对 BeanFactory 多了工具级别的支持等待。所以你看他的名字,已经不是 BeanFactory 之类的工厂了,而是 “应用上下文”, 代表着整个大容器的所有功能。该接口定义了一个 refresh 方法,此方法是所有阅读 Spring 源码的人的最熟悉的方法,用于刷新整个容器,即重新加载/刷新所有的 bean。
图 3-2 ApplicationContext
的接口类
其实还有其他接口....
3.1.3 BeanFactory
BeanFactory 位于设计的最底层,它提供了 Spring IoC 最底层的设计,其方法如下:
图3-3 BeanFactory的方法体
- getBean 对应了多个方法来获取配置给 Spring IoC 容器的 Bean。
1.按照类型拿 bean:bean = (Bean) factory.getBean(Bean.class);
注意:要在 Spring 中只配置了一个这种类型的实例,不然报错。(如果有多个那 Spring 就懵了,不知道该获取哪一个)
2. 按照 bean 的名字拿 bean:bean = (Bean) factory.getBean("beanName");
注意:这种方法不太安全,IDE 不会检查其安全性(关联性)
3. 按照名字和类型拿 bean:(推荐)bean = (Bean) factory.getBean("beanName", Bean.class);
- isSingleton 用于判断是否单例,如果判断为真,其意思是该 Bean 在容器中是作为一个唯一单例存在的。而【isPrototype】则相反,如果判断为真,意思是当你从容器中获取 Bean,容器就为你生成一个新的实例。
注意:在默认情况下,【isSingleton】为 ture,而【isPrototype】为 false - 关于 type 的匹配,这是一个按 Java 类型匹配的方式
- getAliases 方法是获取别名的方法
3.1.4 ApplicationContext
创建一个Service接口
写入方法
public class UserServiceImpl implements UserService
public void save()
System.out.println("user service running...");
配置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">
<!-- 1.创建spring控制的资源-->
<bean id="userService" class="impl.service.impl.UserServiceImpl"/>
</beans>
Test
public static void main(String[] args)
//2.加载配置文件
ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
//3.获取资源
UserService userService = (UserService) ctx.getBean("userService");
userService.save();
ApplicationContext 常见实现类:
1.ClassPathXmlApplicationContext:
读取classpath中的资源
ApplicationContext c = new ClassPathXmlApplicationContext("applicationContext.xml");
2:FileSystemXmlApplicationContext:-
读取指定路径的资源
ApplicationContext a = new FileSystemXmlApplicationContext("c:/applicationContext.xml");
3.XmlWebApplicationContext:
需要在Web的环境才可运行
XmlWebApplicationContext ac = new XmlWebApplicationContext(); // 这时并没有初始化容器 ac.setServletContext(servletContext); // 需要指定ServletContext对象 ac.setConfigLocation("/WEB-INF/applicationContext.xml"); // 指定配置文件路径,开头的斜线表示Web应用的根目录 ac.refresh(); // 初始化容器
3.1.5 BeanFactory 和 ApplicationContext 的区别:
- BeanFactory:是Spring中最底层的接口,只提供了最简单的IoC功能,负责配置,创建和管理bean。
在应用中,一般不使用 BeanFactory,而推荐使用ApplicationContext(应用上下文),原因如下。 - ApplicationContext:
1.继承了 BeanFactory,拥有了基本的 IoC 功能;
2.除此之外,ApplicationContext 还提供了以下功能:
① 支持国际化;
② 支持消息机制;
③ 支持统一的资源加载;
④ 支持AOP功能;
3.2 依赖注入(Dependency Injection,DI)
3.2.1 什么是DI依赖注入?
spring动态的向某个对象提供它所需要的其他对象。这一点是通过DI(Dependency Injection,依赖注入)来实现的。比如对象A需要操作数据库,以前我们总是要在A中自己编写代码来获得一个Connection对象,有了 spring我们就只需要告诉spring,A中需要一个Connection,至于这个Connection怎么构造,何时构造,A不需要知道。在系统运行时,spring会在适当的时候制造一个Connection,然后像打针一样,注射到A当中,这样就完成了对各个对象之间关系的控制。A需要依赖 Connection才能正常运行,而这个Connection是由spring注入到A中的,依赖注入的名字就这么来的。那么DI是如何实现的呢? Java 1.3之后一个重要特征是反射(reflection),它允许程序在运行的时候动态的生成对象、执行对象的方法、改变对象的属性,spring就是通过反射来实现注入的。
简单来说什么是依赖注入,就是给属性赋值(包括基本数据类型和引用数据类型)
java面向对象的方式,需要调用另一个java对象,采用"new 被调用者"的方式创建对象,缺点是调用与被调用者的耦合增强,不利于后期维护。
使用Spring框架后,对象不在由调用者创建,而是由Spring容器创建,容器会负责控制程序间的关系,而不是由调用者直接控制,我们称控制权转移的这种情况为Spring控制反转!
3.3 依赖注入的实现方式
3.3.1 set注入(主流)
- 名称:property
- 类型:**标签**
- 归属:bean标签
- 作用:使用set方法的形式为bean提供资源
- 格式:
```java
<bean>
<property />
</bean>
```
- 基本属性:
```xml
<property name="propertyName" value="propertyValue" ref="beanId"/>
```
name:对应bean中的属性名,要求该属性必须提供可访问的set方法(严格规范为此名称是set方法对应名称)
value:设定非引用类型属性对应的值,不能与ref同时使用
ref:设定引用类型属性对应bean的id ,不能与value同时使用
- 注意:一个bean可以有多个property标签
3.3.2 构造器注入(了解)
- 名称:constructor-arg
- 类型:**标签**
- 归属:bean标签
- 作用:使用构造方法的形式为bean提供资源,兼容早期遗留系统的升级工作
- 格式:
```xml
<bean>
<constructor-arg />
</bean>
```
- 基本属性:
```xml
<constructor-arg name="argsName" value="argsValue />
```
name:对应bean中的构造方法所携带的参数名
value:设定非引用类型构造方法参数对应的值,不能与ref同时使用
其他属性:
```xml
<constructor-arg index="arg-index" type="arg-type" ref="beanId"/>
```
ref:设定引用类型构造方法参数对应bean的id ,不能与value同时使用
type :设定构造方法参数的类型,用于按类型匹配参数或进行类型校验
index :设定构造方法参数的位置,用于按位置匹配参数,参数index值从0开始计数
- 注意:一个bean可以有多个constructor-arg标签
3.3.3 集合类型数据注入
- 名称:array,list,set,map,props
- 类型:**标签**
- 归属:property标签 或 constructor-arg标签
- 作用:注入集合数据类型属性
- 格式:
```xml
<property>
<list></list>
</property>
```
(1)集合类型数据注入——list
```xml
<property name="al">
<list>
<value>itheima</value>
<value>66666</value>
</list>
</property>
```
(2)集合类型数据注入——props
```xml
<property name="properties">
<props>
<prop key="name">zhangsan666</prop>
<prop key="value">666666</prop>
</props>
</property>
```
(3)集合类型数据注入——array (了解)
```xml
<property name="arr">
<array>
<value>123456</value>
<value>66666</value>
</array>
</property>
```
(4)集合类型数据注入——set(了解)
```xml
<property name="hs">
<set>
<value>Test</value>
<value>66666</value>
</set>
</property>
```
(5)集合类型数据注入——map(了解)
```xml
<property name="hm">
<map>
<entry key="name" value="Test66666"/>
<entry key="value" value="6666666666"/>
</map>
</property>
3.3.4 使用p命名空间简化配置(了解)
- 名称:p:propertyName,p:propertyName-ref
- 类型:**属性**
- 归属:bean标签
- 作用:为bean注入属性值
- 格式:
```xml
<bean p:propertyName="propertyValue" p:propertyName-ref="beanId"/>
```
- 注意:使用p命令空间需要先开启spring对p命令空间的的支持,在beans标签中添加对应空间支持
```xml
<bean
id="userService"
class="com.itheima.service.impl.UserServiceImpl"
p:userDao-ref="userDao"
p:bookDao-ref="bookDao"
/>
```
3.3.5 SpEL (了解)
- Spring提供了对EL表达式的支持,统一属性注入格式
- 类型:**属性值**
- 归属:value属性值
- 作用:为bean注入属性值
- 格式:
```xml
<property value="EL"></bean>
```
- 注意:所有属性值不区分是否引用类型,统一使用value赋值
- 所有格式统一使用 value=“********”
- 常量 #10 #3.14 #2e5 #‘itcast’
- 引用bean #beanId
- 引用bean属性 #beanId.propertyName
- 引用bean方法 beanId.methodName().method2()
- 引用静态方法 T(java.lang.Math).PI
- 运算符支持 #3 lt 4 == 4 ge 3
- 正则表达式支持 #user.name matches‘[a-z]6,’
- 集合支持 #likes[3]
3.3.6 properties文件
- Spring提供了读取外部properties文件的机制,使用读取到的数据为bean的属性赋值
- 操作步骤
1.准备外部properties文件
2.开启context命名空间支持
```xml
xmlns:context="http://www.springframework.org/schema/context"
```
3.加载指定的properties文件
```xml
<context:property-placeholder location="classpath:filename.properties">
```
4.使用加载的数据
```xml
<property name="propertyName" value="$propertiesName"/>
```
- 注意:如果需要加载所有的properties文件,可以使用`*.properties`表示加载所有的properties文件
- 注意:读取数据使用**$propertiesName**格式进行,其中**propertiesName**指properties文件中的属性名
3.3.7 import(团队开发)
- 名称:import
- 类型:**标签**
- 归属:beans标签
- 作用:在当前配置文件中导入其他配置文件中的项
- 格式:
```xml
<beans>
<import />
</beans>
```
- 基本属性:
```xml
<import resource=“config.xml"/>
```
resource:加载的配置文件名
- Spring容器加载多个配置文件
```java
new ClassPathXmlApplicationContext("config1.xml","config2.xml");
```
- Spring容器中的bean定义冲突问题
- 同id的bean,后定义的覆盖先定义的
- 导入配置文件可以理解为将导入的配置文件复制粘贴到对应位置
- 导入配置文件的顺序与位置不同可能会导致最终程序运行结果不同
想要测试详情请参考:狂神说Spring03:依赖注入(DI)
四、Spring中的 Bean
4.1 bean的配置
Spring中,XML配置文件的根元素是<beans>,<beans>中包含了多个<bean>子元素,每一个<bean>中定义了一个Bean
属性名称 | 描述 |
---|---|
id | 是一个 Bean 的唯一标识符,Spring 容器对 Bean 的配置和管理都通过该属性完成 |
name | Spring 容器同样可以通过此属性对容器中的 Bean 进行配置和管理,name 属性中可以为 Bean 指定多个名称,每个名称之间用逗号或分号隔开 |
class | 该属性指定了 Bean 的具体实现类,它必须是一个完整的类名,使用类的全限定名 |
scope | 用于设定 Bean 实例的作用域,其属性值有 singleton(单例)、prototype(原型)、request、session 和 global Session。其默认值是 singleton |
constructor-arg | <bean>元素的子元素,可以使用此元素传入构造参数进行实例化。该元素的 index 属性指定构造参数的序号(从 0 开始),type 属性指定构造参数的类型 |
property | <bean>元素的子元素,用于调用 Bean 实例中的 Set 方法完成属性赋值,从而完成依赖注入。该元素的 name 属性指定 Bean 实例中的相应属性名 |
ref | <property> 和 <constructor-arg> 等元素的子元索,该元素中的 bean 属性用于指定对 Bean 工厂中某个 Bean 实例的引用 |
value | <property> 和 <constractor-arg> 等元素的子元素,用于直接指定一个常量值 |
list | 用于封装 List 或数组类型的依赖注入 |
set | 用于封装 Set 类型属性的依赖注入 |
map | 用于封装 Map 类型属性的依赖注入 |
entry | <map> 元素的子元素,用于设置一个键值对。其 key 属性指定字符串类型的键值,ref 或 value 子元素指定其值 |
4.2 bean的实例化
- 名称:bean
- 类型:**标签**
- 归属:beans标签
- 作用:定义spring中的资源,受此标签定义的资源将受到spring控制
- 格式:
```xml
<beans>
<bean />
</beans>
```
- 基本属性:
```xml
<bean id="beanId" name="beanName1,beanName2" class="ClassName"></bean>
```
id:bean的名称,通过id值获取bean
class:bean的类型
name:bean的名称,可以通过name值获取bean,用于多人配合时给bean起别名
测试一下
创建一个接口以及实现类:
public interface UserService
public void save();
public class UserServiceImpl implements UserService
public void save()
System.out.println("Hello world");
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">
<!-- 1.创建spring控制的资源-->
<bean id="userService" class="com.service.impl.UserServiceImpl"/>
</beans>
注意:在Bean中为指定id和name,spring会将class当id值
创建测试类:
public static void main(String[] args)
//2.加载配置文件
ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
//3.获取资源
UserService userService = (UserService) ctx.getBean("userService");
userService.save();
输出了Hello world
4.3 Bean的三种实例化方式
BeanFactory作用
-
配置、创建以及管理Bean对象
-
维持Bean对象之间的依赖关系
-
负责Bean对象的生命周期
上面我们通过小案例了解了bean的大致概念,下面我们来学习Bean的实例化方式
①构造器实例化
指Spring容器通过Bean对应类中的默认无参构造方法实例化。
②静态工厂实例化
创建静态工厂的方法来创建Bean实例,其中Bean的class属性所指定的不是Bean实现类而是静态工厂类,需要使用factory-merhod属性来指定创建的静态工厂。
文件 MyBean2Facory
public class MyBean2Facory
//使用自己创建的Bean2工厂
public static Bean2 createBean()
return new Bean2();
applicationContest.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:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/beans
https://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
https://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/aop
https://www.springframework.org/schema/aop/spring-aop.xsd">
<bean id="Bean2" class="instance.MyBean2Facory"
factory-method="createBean"/>
</beans>
③实例工厂实例化
创建实例工厂MyBean3Factory
public class MyBean3Facory
public MyBean3Facory()
System.out.println("bean3工厂实例化中....");
//使用自己创建的Bean2工厂
public Bean3 createBean()
return new Bean3();
创建beans3.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:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/beans
https://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
https://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/aop
https://www.springframework.org/schema/aop/spring-aop.xsd">
<bean id="MyBean3Facory" class="instance.MyBean3Facory"/>
<!--使用factory-bean属性执行实例工厂-->
<!--使用factory-method属性确定使用的方法-->
<bean id="bean3" factory-bean="MyBean3Facory" factory-method="createBean"/>
</beans>
<!--使用factory-bean属性执行实例工厂-->
<!--使用factory-method属性确定使用的方法-->
测试输出
4.4 bean属性scope(作用域)
作用域的类型;
作用域名称 | 说明 |
singleton | 默认值,单例模式,表示在 Spring 容器中只有一个 Bean 实例,Bean 以单例的方式存在。 |
prototype | 原型模式,表示每次通过 Spring 容器获取 Bean 时,容器都会创建一个 Bean 实例。 |
request | 每次 HTTP 请求,容器都会创建一个 Bean 实例。该作用域只在当前 HTTP Request 内有效。 |
session | 同一个 HTTP Session 共享一个 Bean 实例,不同的 Session 使用不同的 Bean 实例。该作用域仅在当前 HTTP Session 内有效。 |
application | 同一个 Web 应用共享一个 Bean 实例,该作用域在当前 ServletContext 内有效。类似于 singleton,不同的是,singleton 表示每个 IoC 容器中仅有一个 Bean 实例,而同一个 Web 应用中可能会有多个 IoC 容器,但一个 Web 应用只会有一个 ServletContext,也可以说 application 才是 Web 应用中货真价实的单例模式。 |
websocket | websocket 的作用域是 WebSocket ,即在整个 WebSocket 中有效。 |
4.4.1 singleton
名称:scope
- 类型:**作用域**
- 归属:bean标签
- 作用:定义bean的作用范围
- 格式:
- <bean id="..." class="..." scope="singleton"/>
HelloWorld 类代码如下。
public class HelloWorld
private String message;
public void setMessage(String message)
this.message = message;
public void getMessage()
System.out.println("message : " + message);
MainApp 类如下。
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class MainApp
public static void main(String[] args)
ApplicationContext context = new ClassPathXmlApplicationContext("Beans.xml");
HelloWorld objA = (HelloWorld) context.getBean("helloWorld");
objA.setMessage("对象A");
objA.getMessage();
HelloWorld objB = (HelloWorld) context.getBean("helloWorld");
objB.getMessage();
Beans.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-3.0.xsd">
<bean id="helloWorld" class="HelloWorld" scope="singleton"/>
</beans>
运行结果如下。
message : 对象A
message : 对象A
从运行结果可以看出,两次输出内容相同,这说明 Spring 容器只创建了一个 HelloWorld 类的实例。由于 Spring 容器默认作用域是 singleton,所以如果省略 scope 属性,其输出结果也会是一个实例。
4.4.2 prototype
名称:scope
- 类型:**作用域**
- 归属:bean标签
- 作用:定义bean的作用范围
- 格式:
- <bean id="..." class="..." scope="prototype"/>
在上面例子 的基础上,修改配置文件 Beans.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-3.0.xsd">
<bean id="helloWorld" class="HelloWorld" scope="prototype"/>
</beans>
运行结果如下。
message : 对象A
message : null
4.5 Bean的生命周期
Spring 根据 Bean 的作用域来选择管理方式。对于 singleton 作用域的 Bean,Spring 能够精确地知道该 Bean 何时被创建,何时初始化完成,以及何时被销毁;而对于 prototype 作用域的 Bean,Spring 只负责创建,当容器创建了 Bean 的实例后,Bean 的实例就交给客户端代码管理,Spring 容器将不再跟踪其生命周期。
了解 Spring 生命周期的意义就在于,可以利用 Bean 在其存活期间的指定时刻完成一些相关操作。一般情况下,会在 Bean 被初始化后和被销毁前执行一些相关操作。
Spring 官方提供了 3 种方法实现初始化回调和销毁回调:
- 实现 InitializingBean 和 DisposableBean 接口;
- 在 XML 中配置 init-method 和 destory-method;
- 使用 @PostConstruct 和 @PreDestory 注解。
在一个 Bean 中有多种生命周期回调方法时,优先级为:注解 > 接口 > XML。
不建议使用接口和注解,这会让 pojo 类和 Spring 框架紧耦合。
以上是关于Enterprise-level Spring-探索Spring-从入门到入厂的主要内容,如果未能解决你的问题,请参考以下文章