Spring 学习之bean的理解
前言:对于使用Spring框架的开发人员来说,我们主要做的主要有两件事情:①开发Bean;②配置Bean;而Spring帮我们做的就是根据配置文件来创建Bean实例,并调用Bean实例的方法来完成“依赖注入”,可以把Spring容器理解成一个大型工厂,Bean就是该工厂的产品,工厂(Spirng容器)里能生产出来什么样的产品(Bean),完全取决于我们在配置文件中的配置。我们那么今天我们就来说说关于Bean的故事。。。
容器中Bean的作用域
singleton | 在整个Spring IoC 容器中,使用 singleton 定义的Bean将只有一个实例 |
prototype | 原型模式,每次通过容器的getBean 方法获取prototype定义的Bean 时,都将产生一个新的Bean实例 |
request | 对于每次HTTP请求,使用request定义的Bean都将产生一个新的实例,每次HTTP请求都将产生不同的Bean实例,该作用域仅在给予web的Spring ApplicationContext情形下有效 |
session | 对于每次HTTP Session ,使用session定义的Bean都将产生一个新实例,该作用域仅在给予web的Spring ApplicationContext情形下有效 |
global session | 每个全局得HTTP Session对应一个Bean实例,该作用域仅在给予web的Spring ApplicationContext情形下有效 |
比较常用的是singleton 和 prototype 两种作用域,对于singleton作用域,每次请求该Bean都将获得相同的实例,Spring容器负责跟踪监视Bean实例的状态,负责维护Bean实例的生命周期行为,如果一个Bean被设置成prototype作用域,程序每次请求该id的Bean,Spring都会创建一个新的Bean实例,然后返回给程序,在这种情况下,Spring容器仅仅使用new 关键字创建Bean实例,一旦创建成功,容器Spring不再对Bean的生命周期负责,也不会维护Bean实例的状态。
如果不指定Bean的作用域,Spring默认使用singleton作用域。Java在常见Java实例时,需要进行内存申请,销毁实例是,需要完成垃圾回收,这些工作都会导致系统开销的增加。因此prototype作用域Bean 的创建销毁代价比较大。而singleton作用域的Bean 实例一旦创建成功,可以重复使用,因此,除非必要,否则避免将Bean作用域设置成prototype。
如果要使用 request,session,global session作用域的Bean,在配置Bean之前,还需要做少量的初始配置(将HTTP 请求banding到该提供服务的线程上,这使得具有request 和 session作用域的Bean实例能够在后面的调用链中被访问到),如果只是配置常规的作用域(singleton,prototype),则无须设置。如果Web 应用直接使用Spring MVC 作为MVC框架,即使用SpringDispatcherServlet 或DispatcherPorlet 来拦截所有用户请求,则无须设置,因为DispatcherServlet 和DispatcherPorlet已经处理了所有和请求有关的额状态处理。
当使用Spring's DispatcherServlet 以外的Servlet 2.4 及以上规范的Web 容器时需要在“web.xml”中增加如下配置:
<listener>
<listener-class>org.springframework.web.context.request.RequestContextListener</listener-class>
</listener>
如果使用的是早起版本的Web容器,则该容器不支持Listener 规范,故无法使用上述配置,只能改为Filter配置方式,配置代码如下:
<filter>
<filter-name>requestContextFilter</filter-name>
<filter-class>org.springframework.web.filter.RequestContextFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>requestContextFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
容器中Bean的生命周期
Spring可以管理singleton作用域Bean的生命周期,Spring可以精确地知道singleton域bean何时被创建,何时初始化完成,以及容器何时准备销毁Bean实例。因为,对于singleton作用域的Bean,客户端的每次请求都返回同一个Bean实例,客户端代码不能控制Bean的销毁,它的生命周期都在Spring的掌握之中。这么一来,容器就可以管理实例化结束后(某些资源的申请)和销毁之前(进行某些资源的回收)的行为。管理Bean的生命周期行为主要有两个时机:注入依赖关系后,销毁实例之前;具体的管理方法如下
Spring提供两种方式在Bean全部属性设置成功后执行特定行为
使用init-method 属性(代码污染小)
在类中编写一个方法,在属性中指定该方法在依赖关系设置完成后自动执行。
实现InitializingBean接口(耦合较高)
编写afterPropertiesSet()方法的具体实现
同理,若在Bean销毁之前,执行特定的方法,只需要①使用 destroy-method属性②实现DisposableBean接口(实现destroy()方法)
对于prototype作用域的Bean,Spring容器只负责Bean的创建,当容器创建实例完成后,Bean将完全交给客户端代码管理,容器不再负责其生命周期。每次客户端请求prototype作用域的Bean时,Spring容器都会产生一个全新的Bean实例交个客户端(prototype就是这么任性),Spring容器本省也不知道自己创建了多少个实例,更无从知道这些实例什么时候才会被销毁。
Spring 的 Bean 和 JavaBean比较
- 规范:Spring容器对Bean 没有特殊要求,不像JavaBean 一样遵循一些规范(为每个属性提供相应的setter 和 getter 方法),不过对于设值注入的Bean,一定要提供setter 方法。
- 作用:Spring 中的Bean 是 java 实例,java组件,它的作用几乎无所不包,任何应用组件都被称为Bean,而传统的Java应用中的JavaBean通常作为DTO(数据传输对象),来封装值对象,在各层之间传递数据。
- 生命周期:传统的JavaBean作为值对象传递,不接受任何容器管理其生命周期,Spring中的Bean有Spring管理其生命周期行为。
Spring 的Bean继承和java继承的区别
- Spring中子Bean和父Bean可以是不同的类型,而java中的继承子类只是父类的一种特殊类型。
- Spring中Bean的继承是实例之间的关系,主要表现为参数值的延续,而java终的继承是类之间的关系,主要表现为属性,方法的延续。
- Spring中子Bean不可做父Bean使用,不具备多态性,java中的子类实例完全可以做父类的实例使用
Bean 实例的创建方式及依赖配置
大多数情况下,BeanFactory 直接通过new 关键字调用构造器来创建Bean 实例,而class属性指定了Bean实例的实现类。但这并不是实例化Bean的唯一方法。
创建Bean通常有以下三种方式
- 调用构造器创建Bean 实例
- 调用静态工厂方法创建Bean
- 调用实例工厂方法创建Bean
- 调用构造器创建Bean 实例
调用构造器创建Bean实例是最常见的情况,,BeanFactory 将使用默认的构造器来创建Bean实例,该实例是个默认实例,Spring对Bean实例的所有属性执行默认初始化,即所有基本类型的值初始化为0或false,引用类型初始化为null,接下来BeanFactory会根据配置文件决定依赖关系,先实例化被依赖的Bean 实例,然后为Bean注入依赖关系,最后将一个完整的Bean实例返回给程序,该Bean实例化的所有属性,已经由Spring容器完成了初始化。
- 使用静态工厂方法创建Bean
使用静态工厂方法创建Bean实例时,class属性也必须指定,但此时class属性并不是指定Bean实例的实现类,而是静态工厂类,Spring需要根据工厂类的工厂方法来创建Bean实例,除此之外,还需要使用factory-method 属性来指定静态工厂方法名,Spring调用静态工厂方法(可能包含一组参数,若需要,使用<constructor-arg.../>元素传入)返回一个Bean实例,获得Bean实例后,Spring后面的处理步骤与采用普通方法创建Bean实例完全一样。
使用静态工厂方法创建Bean实例时,Spring将先解析配置文件,并根据配置文件指定的信息,通过反射调用静态工厂类的静态工厂方法,将该静态工厂方法的凡湖值作为Bean实例。在这个过程中,Spring不再负责创建Bean实例,Bean实例的创建是用户提供的静态工厂类负责创建的。但是Spring容器依然可以管理Bean实例的依赖关系,生命周期。
- 使用实例工厂方法
实例工厂方法与静态工厂方法不同:调用静态工厂方法只需使用工厂类,调用实例工厂方法则必须使用工厂实例。采用实例工厂方法时,配置Bean实例的<bean../>元素无需class属性,因为Spring容器不再直接实例化该Bean,Spring容器仅仅调用实例工厂的工厂方法,工厂方法负责创建Bean实例。采用实例工厂方法创建Bean时,需要为<bean../>元素指定如下两个属性:factory-bean:该属性的值为工厂Bean的id.factory-method:该属性指定实例工厂的工厂方法。与静态工厂方法相似,如果需要调用工厂方法时传入参数,使用<constructor-arg.../>元素确定参数值。
静态工厂方法创建实例和工厂方法创建实例的异同点:
调用实例工厂方法创建Bean,必须将实例工厂配置成Bean实例。而静态工厂方法创建Bean,则无需配置工厂Bean。
调用实例工厂方法创建Bean,必须使用factory-bean属性确定工厂Bean。而静态工厂方法创建Bean,则使用class 元素确定静态工厂类。
都需要factory-method 指定相应产生Bean实例的工厂方法。
工厂方法需要参数都可以使用<constructor-art.../>元素指定参数。
Spring 学习之bean的理解的更多相关文章
- spring 学习之 bean 的注入方式 property和constructor-arg的使用方式
spring 学习之 bean 的注入方式 property和constructor-arg的使用方式. bean的注入方式: property 注入是: 通过setxx方法注入. construct ...
- Spring学习七----------Bean的配置之自动装配
© 版权声明:本文为博主原创文章,转载请注明出处 Bean的自动装配(Autowiring) no:不启用自动装配,此时需要手动注入.参考:Spring学习三----------注入方式 defaul ...
- spring学习-ApplicationContext-spring上下文深入理解
4月份开始复习一遍spring相关知识.让自己巩固一下spring大法的深奥益处,所以就看了大佬的博客,转载留下来日后继续研读.认为重点的标记为红色 以下文章内容转载自:http://www.cnbl ...
- Spring 学习笔记---Bean的生命周期
生命周期图解 由于Bean的生命周期经历的阶段比较多,我们将通过一个图形化的方式进行描述.下图描述了BeanFactory中Bean生命周期的完整过程: Bean 的生命周期从Spring容器着手实例 ...
- Spring 学习笔记 Bean的作用域
在配置文件中定义Bean时,用户不但可以配置Bean的属性值以及相互之间的依赖关系,还可以定义Bean的作用域.作用域将对Bean的生命周期和创建方式产生影响.在低版本的Spring中,仅有两个作用域 ...
- Java Spring学习笔记----Bean的依赖注入(设值注入方式)1
Spring常用的两种依赖注入方式:一种是设值注入方式,利用Bean的setter方法设置Bean的属性值:另一种是构造注入,通过给Bean的构造方法传递参数来实现Bean的属性赋值: 1.设值注入方 ...
- Spring学习十一----------Bean的配置之基于Java的容器注解@Bean
© 版权声明:本文为博主原创文章,转载请注明出处 @Bean -@Bean标识一个用于配置和初始化一个由SpringIOC容器管理的新对象的方法,类似于XML配置文件的<bean/> -可 ...
- Spring学习十----------Bean的配置之Autowired注解实现
© 版权声明:本文为博主原创文章,转载请注明出处 @Required -@Required注解适用于bean属性的setter方法 -这个注解仅仅表示,受影响的bean属性必须在配置时被填充,通过在b ...
- Spring学习九----------Bean的配置之Bean的定义及作用域的注解实现
© 版权声明:本文为博主原创文章,转载请注明出处 Spring Bean常用注解 @Component:通常注解,可用于任何Bean @Repository:通常用于注解DAO层,即持久层 @Serv ...
随机推荐
- 数据库事务的四个特性(ACID)、事务的隔离级别
事务是一个不可分割的最小逻辑工作单元. 事务具有四个特征:原子性( Atomicity ).一致性( Consistency ).隔离性( Isolation )和持久性( Durability ). ...
- Appium自动化中截图的问题
在用Appium做UI自动化过程中,大家会发现测试报告很重要,而在测试报告中截图很重要. 因为很多公司都是用Jenkins作为持续集成工具,所以要让执行自动化测试的人看明白自动化在跑什么,哪里失败了, ...
- apache服务器启动出错
启动本地xampp的服务器时,报错如下所示: 错误提示很明确: 就是指我们希望使用的端口被占用,由于xampp默认使用的端口是80(http协议).443(https协议),也就是说这两个端口被其他的 ...
- 分布式任务框架elastic-job 学习笔记
官方资料:https://github.com/dangdangdotcom/elastic-job ------------------------------------------------- ...
- pat04-树5. File Transfer (25)
04-树5. File Transfer (25) 时间限制 150 ms 内存限制 65536 kB 代码长度限制 8000 B 判题程序 Standard 作者 CHEN, Yue We have ...
- java题目练手
大数阶乘 题目链接:http://acm.nyist.net/JudgeOnline/problem.php?pid=28 代码如下: import java.io.*; import java.ma ...
- 详细记录vue项目实战步骤(含vue-cli脚手架)
一.通过vue-cli创建了一个demo. (vue-cli是快速构建这个单页应用的脚手架,本身继承了多种项目模板:webpack(含eslit,unit)和webpack-simple(无eslin ...
- 2019.3.26判断是否回文(java实现)
我所有的文章都是对我总结学习的总结,那里不好或者冒犯了那里,我先对您说声对不起,请告知我进行改正. 今天java老师作业题目是判断是一个字符串否是回文: emmmm,我的思路是将字符串逆序,然后使用方 ...
- php socket简单使用
php的socket编程算是比较难以理解的东西吧,不过,我们只要理解socket几个函数之间的关系,以及它们所扮演的角色,那么理解起来应该不是很难了,在笔者看来,socket编程,其实就是建立一个网络 ...
- 栅格那点儿事(四D)
统计值与空值 在上一篇的内容里反复提到了一个统计值.那这个统计值是怎么来的,具体是干嘛用的呢? 统计值主要就是用于栅格数据的显示和重分类,顾名思义就是一个波段中所有像元值的一个统计信息,最大值,最小值 ...