spring默认存在线程安全问题 !!!
1.struts1的action是单例的,所以存在线程安全问题,但是struts2的action不是单例所以是线程安全的
2.spring默认的注入也是单例的,所以存在线程安全问题
先理解为何会有线程不安全的问题,比如有一个类Person有个属性是name,线程1修改了这个属性的name,要进行存入数据库操作的时候,线程2又修改了这个name,这样线程1就存入了一个线程2修改过的数据了。(web环境是很容易出现多用户同时访问产生多线程的)
有一个类User,你每次使用这个类的时候都是new出来的,那么这个类一定是线程安全的吗?也不一定。
publicclassUser{privatestaticStringname=null;publicUser(Stringname){User.name=name;}}
对于这个User类,即使你每次都是new一个新的,它也不是线程安全的。
避免的方法很简单
spring管理bean,设置成scope为protype,如果是web运用设置成request这样就不是单例了,而是为每个线程都创建一个;
线程安全是可以避免的,就是禁止用可变动的成员变量,如果都是局部变量的话,即使是单例的也不存在任何问题
privateJdbcTemplatejdbcTemplate;
privateLobHandlerlobHandler;
里面没什么可变成员变量,说以他们是单例的,但是不会有线程问题
spring的生命周期范围:
singleton:SpringIoc容器只会创建该Bean的唯一实例,所有的请求和引用都只使用这个实例
Property:每次请求都创建一个实例
request:在一次Http请求中,容器会返回该Bean的同一个实例,而对于不同的用户请求,会返回不同的实例。需要注意的是,该作用域仅在基于Web的SpringApplicationContext情形下有效,以下的session和globalSession也是如此
session:同上,唯一的区别是请求的作用域变为了session
globalsession:全局的HttpSession中,容器会返回该bean的同一个实例,典型为在是使用portletcontext的时候有效(这个概念本人也不懂)
注意:如果要用到request,session,globalsession时需要配置
servlet2.4及以上:
在web.xml中添加:
<listener>
<listener-class>org.springframework.web.context.scope.RequestContextListener/>
</listener>
servlet2.4以下:
需要配置一个过滤器
<filter>
<filter-name>XXXX</filter-name>
<filter-class>org.springframework.web.filter.RequestContextFilter</filter-class>
<filter-mapping>
<filter-name>XXXX</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
另外,从2.0开始,可以自己定义作用域,但需要实现scope,并重写get和remove方法
特别要引起注意的是:
一般情况下前面两种作用域是够用的,但如果有这样一种情况:singleton类型的bean引用一个prototype的bean时会出现问题,因为singleton只初始化一次,但prototype每请求一次都会有一个新的对象,但prototype类型的bean是singleton类型bean的一个属性,理所当然不可能有新prototpye的bean产生,与我们的要求不符
解决方法:
1.放弃Ioc,这与设计初衷不符,并代码间会有耦合
2,Lookup方法注入,推荐