项目准备交付了,却出现了一个致命的问题:
项目场景:有一个核心业务类--根据个人编号,调用各种数据进行运算。
出现问题:A用户和B用户同时访问出现乱码错误,并且偶尔出现,A提出请求的时候返回B的结果。
重现错误:因为没有测试用例,项目几乎裸奔。所以用js模拟用户频繁请求,一下是html测试代码:
<html>
<head><title> New Document </title>
</head>
<body>
<form id="form1" name="form1" method="post" action="PreCompe.action">
<label>个人编号:
<input name="perscode" type="text" id="perscode" value="" size="50" style="height:25px; width:250px"/>
</label>
</form>
<form action="#" id="form2" name="form2">
<input type="button" value="开始" name="btnStart"/>
<input type="button" value="重置" name="btnReset"/>
<input name="txt1" type="text" value="0" size="12"/>
</form>
</body>
</html>
<script language="JavaScript" type="text/javascript">
<!--
//获取表单中的表单域
var txt=document.form2.elements["txt1"];
var btnStart=document.form2.elements["btnStart"];
var btnReset=document.form2.elements["btnReset"]
//定义定时器的id
var id;
//每10毫秒该值增加1
var seed=0;
btnStart.onclick=function(){
//根据按钮文本来判断当前操作
if(this.value=="开始"){
//使按钮文本变为停止
this.value="停止";
//使重置按钮不可用
btnReset.disabled=true;
//设置定时器,每0.01s跳一次
id=window.setInterval(tip,10);
}else{
//使按钮文本变为开始
this.value="开始";
//使重置按钮可用
btnReset.disabled=false;
//取消定时
window.clearInterval(id);
}
}
//重置按钮
btnReset.onclick=function(){
seed=0;
}
//让秒表跳一格
function tip(){
seed++;
txt.value=seed/100;
openWin(seed);
}
//-->
function openWin(number){
var perscode = document.form1.perscode.value;
window.open ("PreCompe.action?&compeopera=1&treattype=2&perscode="+perscode,"newwindow"+number,"height=600,width=800,top=400,left=400,toolbar=no,menubar=no,scrollbars=no, resizable=no,location=no, status=no");
}
</script>
原理很简单,测试用例复杂,所以干脆就直接模拟很多用户每一秒钟请求一次,肯定会有并发发生。然后是多台机器同时访问。
结果:控制台显示,一个业务类实例没有完成,另外一个实例已经开始。
BUG分析:业务类一开始实例化后,存在于内存,多个请求调用产生交叉。
解决方法:
<bean id="builder" class="com.medical.domain.medcompe.impl.ConcreateBuilder" singleton="false">
附上引自:http://blog.163.com/tangyang_personal/blog/static/46229613200832235353419/的一个教程。
Spring中Bean的生命周期 在spring中,从BeanFactory或ApplicationContext取得的实例为Singleton,也就是预设为每一个Bean的别名只能维持一个实例,而不是每次都产生
一个新的对象
使用Singleton模式产生单一实例,对单线程的程序说并不会有什么问题,但对于多线程的程序,就必须注意安全(Thread-safe)的议题,防止多个线程
同时存取共享资源所引发的数据不同步问题。
然而在spring中 可以设定每次从BeanFactory或ApplicationContext指定别名并取得Bean时都产生一个新的实例:例如:
<bean singleton="false">
在spring中,singleton属性默认是true,只有设定为false,则每次指定别名取得的Bean时都会产生一个新的实例
一个Bean从创建到销毁,如果是用BeanFactory来生成,管理Bean的话,会经历几个执行阶段:
1:Bean的建立:
有BeanFactory读取Bean定义文件,并生成各个Bean实例
2:属性注入:
执行相关的Bean属性依赖注入
3:BeanNameAware的setBeanName():
如果Bean类有实现org.springframework.beans.BeanNameAware接口,则执行它的setBeanName()方法
4:BeanFactoryAware的setBeanFactory():
如果Bean类有实现org.springframework.beans.factory.BeanFactoryAware接口,则执行它的setBeanFactory()方法
5:BeanPostProcessors的ProcessBeforeInitialization()
如果任何的org.springframework.beans.factory.config.BeanPostProcessors实例与Bean实例相关。则执行BeanPostProcessors实例
的processBeforeInitialization()方法
6:initializingBean的afterPropertiesSet():
如果Bean类已实现org.springframework.beans.factory.InitializingBean接口,则执行他的afterProPertiesSet()方法
7:Bean定义文件中定义init-method:
可以在Bean定义文件中使用"init-method"属性设定方法名称例如:
<bean calss="onlyfun.caterpillar.HelloBean" init-method="initBean">
如果有以上设置的话,则执行到这个阶段,就会执行initBean()方法
8:BeanPostProcessors的ProcessaAfterInitialization()
如果有任何的BeanPostProcessors实例与Bean实例关联,则执行BeanPostProcessors实例的ProcessaAfterInitialization()方法
9:DisposableBean的destroy()
在容器关闭时,如果Bean类有实现org.springframework.beans.factory.DisposableBean接口,则执行他的destroy()方法
10:Bean定义文件中定义destroy-method
在容器关闭时,可以在Bean定义文件中使用"destroy-method"属性设定方法名称,例如:
<bean destroy-method="destroyBean">
如果有以上设定的话,则进行至这个阶段时,就会执行destroyBean()方法,如果是使用ApplicationContext来生成并管理Bean的话
则稍有不同,使用ApplicationContext来生成及管理Bean实例的话,在执行BeanFactoryAware的setBeanFactory()阶段后,若Bean
类上有实现org.springframework.context.ApplicationContextAware接口,则执行其setApplicationContext()方法,接着才执行
BeanPostProcessors的ProcessBeforeInitialization()及之后的流程
分享到:
相关推荐
单例Bean在容器启动时被创建,并在整个容器生命周期中保持唯一。 2. **原型(Prototype)作用域**:与单例相反,原型作用域的Bean每次请求都会创建一个新的实例。这适用于需要多个实例的情况,如用户会话中的对象,...
这个实例在整个应用程序生命周期中被共享,无论何时请求该Bean,Spring都会返回相同的对象。例如,在提供的XML配置文件中,Bean `p1` 指定了`class="org.crazyit.app.service.Person"`,它就是一个`singleton` Bean...
2. **Spring管理Job的生命周期**:将Job类定义为Spring的Bean,这样Job实例的创建、初始化、销毁等生命周期管理就交给了Spring,而不是Quartz。这样做的好处是,Job可以轻松地利用Spring的其他服务,如数据库连接池...
在Spring MVC中,Controller被设计为单例模式,这是为了提高性能和减少内存消耗,因为每个请求...合理的架构设计、避免实例变量、使用线程安全的数据结构以及合理配置bean的生命周期,都能帮助我们构建更健壮的系统。
这意味着无论有多少次请求获取同一个Bean,Spring容器只会创建一个实例,并且在整个应用生命周期中重复使用这个实例。这种设计决策基于性能和资源管理的考虑。 首先,让我们深入理解Spring Bean的单例模式。当一个...
在这个主题下,我们将深入探讨Spring如何通过IOC管理Bean的生命周期,并且理解Bean在不同Scope下的行为差异。 首先,控制反转(IOC)是Spring框架的核心设计理念,它将对象的创建和管理的职责从应用代码中解耦出来...
在容器和依赖注入方面,Spring 5对Bean生命周期管理进行了改进,增强了对AOP(面向切面编程)的支持。它引入了更强大的注解,如`@Profile`,使得在不同环境配置Bean变得更加容易。此外,Spring 5还加强了对JSR-330...
Spring5的Bean容器有了改进,包括更强大的生命周期管理和事件传播机制,使得管理Bean的生命周期更加灵活。 10. **Java 8及更高版本支持** Spring5全面支持Java 8及以后的版本,充分利用了Lambda表达式、Stream ...
8. **Bean的作用域**:Spring中的bean可以有多种作用域,包括单例(singleton)、原型(prototype)、请求(request)、会话(session)和全局会话(global session),每种作用域对应不同的生命周期和并发处理策略...
每个模块都有相应的jar包,例如`spring-context.jar`提供了上下文支持,`spring-beans.jar`处理bean的生命周期,而`spring-webmvc.jar`则用于构建Web应用程序。5.3.9版本的库可能包含了对Java 8及更高版本的支持,...
24. Spring框架中bean的生命周期:包括实例化、初始化、销毁等。 25. Spring是如何解决Bean的循环依赖?:通过使用依赖注入和 setter方法来解决循环依赖问题。 26. Spring如何避免在并发下获取不完整的Bean?:...
Spring框架中的Bean生命周期主要包括以下几个阶段: 1. **实例化**:创建Bean实例。 2. **依赖注入**:注入依赖关系。 3. **初始化**:调用初始化方法。 4. **销毁**:调用销毁方法。 **3.8 重要的Bean生命周期...
在Spring框架中,Bean的作用域是管理对象生命周期和作用范围的关键概念。Bean的定义通常包含在XML配置文件中,通过`<bean>`标签进行配置。当我们谈论"SSH笔记-bean的作用域"时,这里SSH指的是Spring、Struts和...
选择合适的作用域有助于管理bean的生命周期和并发访问。 5. **使用外部属性文件**:Spring允许将配置信息存储在外部的properties文件中,这样可以提高代码的可维护性和灵活性。通过`@PropertySource`注解可以加载...
2. **更好的控制反转**:通过Spring,我们可以更好地控制服务的生命周期,例如何时创建、初始化和销毁服务实例。 3. **简化事务管理**:Spring的事务管理支持可以帮助我们轻松地处理Web服务中的事务边界,确保数据...
在本项目中,Spring作为核心容器,管理着应用对象的生命周期和依赖关系。 Spring MVC是Spring框架的一部分,专门用于构建Web应用程序。它采用模型-视图-控制器(Model-View-Controller,MVC)设计模式,使得业务...
1. **Core Container**:核心容器包含Bean工厂(BeanFactory)和应用上下文(ApplicationContext),它们负责管理对象的生命周期和依赖注入。 2. **Data Access/Integration**:数据访问模块包括JDBC、ORM(Object-...
2. **spring-beans-5.0.2.RELEASE-javadoc.jar**:此模块专注于Bean的定义和管理,包括XML配置和Java配置的处理,以及Bean的生命周期管理和属性注入。 3. **spring-context-5.0.2.RELEASE-javadoc.jar**:上下文...
1. **Spring Core**:提供基础的DI容器,管理对象的生命周期和依赖关系。 2. **Spring Beans**:定义了Bean的配置方式,支持XML、注解及Java配置。 3. **Spring AOP**:实现了面向切面编程,允许定义方法拦截器和...
在IT行业中,尤其是在Java开发领域,使用Spring框架与Hibernate整合是常见的做法,它们可以提供高效的数据访问和持久化服务。当面临多数据库的场景时,如何实现读写分离或者不同的业务逻辑对应不同的数据库,就显得...