首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > JAVA > Java Web开发 >

提问: web中singleton的范围,spring中singleton的范围,该如何处理

2011-12-30 
提问: web中singleton的范围,spring中singleton的范围自从学java开始就会知道singleton是虚拟机范围的,也

提问: web中singleton的范围,spring中singleton的范围
自从学java开始就会知道singleton是虚拟机范围的,也就是说一个singleton的对象被创建后虚拟机内是唯一的.
但是 web应用中用户很多.大家都在访问应有服务器.如果一个类被写成singleton的,服务器的jvm中也就只有一个对象了(所以应用服务器下也就只有一个了).大家同时操作这个对象.所以要求这个对象中不要有别的数据对象.
---- 以上是我对singleton的理解.
但是在用spring的时候.我疑惑了.
我用spring和ibatis集成.配置文件很简单如下:

XML code
<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd"><beans>    <!--1. 配置数据源 -->    <bean id="myDataSource"        class="org.apache.commons.dbcp.BasicDataSource" singleton="false">        <property name="driverClassName"            value="net.sourceforge.jtds.jdbc.Driver"/>        <property name="url"            value="jdbc:jtds:sqlserver://localhost:1433/EE"/>        <property name="username" value="sa"/>        <property name="password" value="1234"/>    </bean>    <!--2. 配置sqlMapClient 相当于hibernate的sessionFactory -->    <bean id="mySqlMapClient"        class="org.springframework.orm.ibatis.SqlMapClientFactoryBean">        <property name="configLocation"            value="ibatisConfig/ibatisConfig.xml"/>        <property name="dataSource" ref="myDataSource"/>    </bean>    <!--3. 配置DAO -->    <bean id="userDaoAtXml" class="cn.luyu.ssi.dao.Impl.UserDaoImpl">        <property name="dataSource" ref="myDataSource"/>        <property name="sqlMapClient" ref="mySqlMapClient"/>    </bean>    <!--4. 配置服务类 -->    <bean id="userServiceTarget"        class="cn.luyu.ssi.service.Impl.UserServiceImpl">        <property name="userDao" ref="userDaoAtXml"/>    </bean>    <!--5. 配置事务管理器TransactionManager -->    <bean id="myTransactionManager"        class="org.springframework.jdbc.datasource.DataSourceTransactionManager">        <property name="dataSource" ref="myDataSource"/>    </bean>    <!--6. 配置事务代理 -->    <bean id="abstrac"        class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean"        abstract="true">        <property name="transactionManager" ref="myTransactionManager"/>        <property name="transactionAttributes">            <props>                <!--把CustomBuyException减去.说明它即使不是runtimeException,也会rollback-->                <!--把CustomBuyException加上.说明它即使是runtimeException,也不会rollback-->                <prop key="*">-DataAccessException</prop>            </props>        </property>    </bean>    <!-- 继承abstrac 方便多个service来映射 -->    <bean id="userService" parent="abstrac">        <property name="target" ref="userServiceTarget"/>    </bean></beans>


这里面bean后面的 singleton 属性我都没有写,所以说默认的就是单例的.我log4j打印日志片段如下:
 Creating shared instance of singleton bean 'myDataSource'
 Creating shared instance of singleton bean 'mySqlMapClient'
 Creating shared instance of singleton bean 'userDaoAtXml'
 Creating shared instance of singleton bean 'userServiceTarget'
 Creating shared instance of singleton bean 'myTransactionManager'
 Creating shared instance of singleton bean 'userService'

日志说明spring把所有的类都变成单例的了.我想知道这样会有问题吗???如果发布.会导致并发问题吗?
另外我觉的dataSource和SqlMapClient好像都是重量级的.应该写成singleton.但是dao和service应该写成prototype的.


但是userServiceTarget和TransactionManager 要写成什么范围的呢?
网上查了资料说spring中singleton的是指在beanfactory范围呢的.这句话也让我疑惑.
请大侠给点指点.或推荐点书籍!!感谢



[解决办法]
此单实例非彼单实例。
Spring的singleton是容器级的,我们一般说的singleton模式是JVM级的。所以singleton模式中,singleton的class在整个JVM中只有一个instance,Spring的Bean,你可以一个class配置多个Bean,这个class就有了多个instance。这个singleton是指在spring容器中,这个Bean是单实例的,是线程共享的。所以要求这些类都是线程安全的。也就是说,不能出现修改Bean属性的方法,当然除了设值得那些setter。只要满足线程安全,这些bean都可以用singleton。而且我们在绝大多数使用上,也是这样用的,包括dao,service。
[解决办法]
singleton 单例的,整个过程都是一个实例,如果你的service,dao里面仅仅是一些方法,没有表示状态的东西的话,就没有问题,而且还会提高性能。


[解决办法]
Beanfactory是Spring初始以静态方式载入的,Spring的单例IOC是基于容器级的,所以这你都不用担心与考虑.
[解决办法]
给你写个例子:

Java code
public class XxxBean {        private int size;    public void setSize(int size) {        this.size = size;  //虽然改变了属性值,但是这是个setter    }        public void someOper1(){        int t = size*100; //读取属性值,没问题    }        public void someOper2(){        this.size = 100; //错误!修改了属性的值!!    }}
[解决办法]
开发的时候尽量少定义类的变量,把变量放在方法里,只定义dao,log等变量在类里边就可以了
[解决办法]
要用spring就要遵守spring的规则。而且,spring管理的Bean都是一些服务性的对象,本身也不应该有状态的修改。
没你想象的可怕,spring出来这么多年了,用的项目那么多,哪个项目不都是团队开发的,挺正常的。

热点排行