转眼九月半


看到单位要发中秋福利,我一看日历,9/7,是啊,九月都过一小半了。

九月,天气清爽,但是人们好像都很浮躁,是在“伏”完之后,现在要“动一动”了吗?

九月,我不管身边的环境是否嘈杂,我只会心神安定。

九月,座右铭,不以物喜,不以己悲。


Spring向父类属性注入问题


众所周知,Spring最大的特点就是IOC容器以及它的依赖注入机制,它将原本主动调用的模式,改为“被动”调用,大大减轻了类之间的耦合度。

最近在开发项目的时候,遇到了一个小问题,项目是采用比较老式的配置文件注册方式,原来学spring的时候,都是用注解,所以很明确可以解决父类注入问题,但是配置文件一下就有点头大了。

一开始是配置成了这样:

<bean id="adjustSourceDAO" class="heb.bf.dao.Adjust.imp.AdjustSourceDAOImpl">
    <property name="dataSource" ref="dataSource"/>
</bean> 

<bean id="sourceBOBase" class="heb.bf.bo.Base.BFSourceBOBase">
     <property name="adjustSourceDAO" ref="adjustSourceDAO"/>   
</bean>     

<bean id="adjustSourceBO" class="heb.bf.bo.Adjust.imp.AdjustSourceBOImpl" parent="sourceBOBase">
    <property name="adjustSourceDAO" ref="adjustSourceDAO"/>   
    <property name="budgetDAO" ref="budgetDAO"/>
</bean> 

我自己觉得一点问题都没有啊,很明确的子类父类关系,用到了parent属性,但是启动之后,跟踪到sourceBOBase中,sourceBOBase自己的adjustSourceDAO属性始终是null的状态。

后来经常查看spring的官方文档中关于bean的注入机制部分,发现它的机制是子类的属性会覆盖父类属性的bean,所以在子类adjustSourceBO中,不应该声明和注册adjustSourceDAO,于是,我将程序调整成以下内容:

<bean id="adjustSourceDAO" class="heb.bf.dao.Adjust.imp.AdjustSourceDAOImpl">
    <property name="dataSource" ref="dataSource"/>
</bean> 

<bean id="sourceBOBase" class="heb.bf.bo.Base.BFSourceBOBase">
     <property name="adjustSourceDAO" ref="adjustSourceDAO"/>   
</bean>     

<bean id="adjustSourceBO" class="heb.bf.bo.Adjust.imp.AdjustSourceBOImpl" parent="sourceBOBase">
    <!-- <property name="adjustSourceDAO" ref="adjustSourceDAO"/>  -->
    <property name="budgetDAO" ref="budgetDAO"/>
</bean> 

注释掉了子类adjustSourceDAO和子类中的adjustSourceDAO属性。再次启动,果然,跟踪到父类的时候,adjustSourceDAO属性赋上了值,而且因为adjustSourceDAO的SETTER/GETTER方法都是public修饰的,所以也可以正常被子类访问。

问题解决!

总结:spring的依赖注入中,如果子类和父类都声明和注册了同一属性,则子类会覆盖父类中的属性,所以,如果业务需要子类和父类去调用同一个类,请删除子类中的属性声明和注册注入。

插曲:在调试过程中,我依靠面向对象的特性,想出了一个特殊的方法来解决这个问题,当然,这属于偏方,不能用在正式的项目上,但是用来开拓思路还是不错的!首先,我在父类中声明属性,并用protected修饰符修饰,然后把SETTER/GETTER方法写在子类中,然后在子类的bean中注册这个注入依赖,OK,依然可以达到相同的效果。


关于GenericObjectPool连接池释放的问题


周末加班,没什么政治任务,就打算解决一下上个星期困扰了开发团队一周的问题 —————— Hession服务接口连接不释放。

现象就是比如maxActive设置为10,则调用10次此接口,连接数就会满,无法继续调用,只能重启服务器。幸亏是这个远程接口不经常调用,所以开发团队就这么纠结着用了一星期。

正文:

监控NumActive的值,每次递增,直到增加到maxActive的值,再调用接口就调用不到了,所以推测是因为没有释放掉用完的Active连接数,下一步查看GenericObjectPool (Apache Commons Pool 2.4.2 API),看到有关于释放连接的东西,是returnObject这个方法,传参是一个泛型,我猜测是被调用服务的接口,所以尝试着封装了一个方法。

    public <T> void releaseService(T t,String serviceName) throws Exception{
    GenericObjectPool pool = poolFacotryMaps.get(serviceName);
    pool.returnObject(t);
}

然后在所有调用方法结束之前,调用这个方法,来释放连接,果不其然,再次监控NumActive的时候,一直保持在2-10之间,可以正常释放掉连接。

问题解决!

总结:到此其实还没有彻底解决我的疑虑,为什么Spring的IOC容器没有帮我很好的管理bean的生命周期?我想这是我下一步要研究的东西。还有就是以后要多注意这方面的问题,因为今天已经确定,Spring也不是万能啊,哈哈。


数据库设计之复选框


最近在设计项目数据库的时候,遇到了关于复选框的字段设计,正好有这么一个个人博客,所以分享一下。

下面给出一个示例,然后通过不同的方法,来分析其利弊。

兴趣爱好:□足球 □篮球 □乒乓球 □游泳 □羽毛球 □跑步


当下比较流行的设计:

1、字符分割:
    利用下划线或者类似符号,将多个选项拼接。比如上例按顺序把checkbox的value设置为:zq、lq、ppq、yy、ymq、pb。
    然后比如我选择了足球、乒乓球、羽毛球,则把【zq_ppq_ymq】存入数据库字段中,下次在做展现的时候,则把该字段用下
    划线split一下,再去循环匹配。

2、置位符:
    利用类似二进制的数组,记录个选项的勾选状态,比如我依然选择了足球、乒乓球、羽毛球,则把【101010】放入数据库字  
    段中,下次在做展现的时候,则把该字段转为byte数组,然后循环判断,如果为1则为勾选,为0则为未勾选。

3、与运算:
    利用了与运算的特性,完成判断勾选。首先分别将示例中复选框的value依次设置为:
    □足球(2) □篮球(4) □乒乓球(8) □游泳(16) □羽毛球(32) □跑步(64)
    规律为依次使用2的N次幂,然后比如我依然选择了足球、乒乓球、羽毛球,则把勾选的选项value之和 2+8+32=【42】存入
    数据库字段中,下次在做展现的时候,则把复选框的DOM对象循环,用value和数据库字段中的值做与运算(&),如果结果大于
    0则为勾选,等于0为未勾选。
    比如 42&2=2 >0 则足球为勾选; 42&16=0 =0 则游泳为未勾选。

总结三种比较流行的方法,
法1在处理选项较多的时候,略显吃力,如果想要见名知意,估计20个选项,就可以达到100多个字符,不管是split还是去equals都会很影响程序速度。
法2的弊端在于拓展性很低,每次增加新的选项,都要去通表update,这本身是违反维护原则的。
法3相比至下,弥补了以上两个弊端,但是也有不足之处,因为需要遍历所有选项,所以在选项多的时候,可能会造成程序的缓慢,但是好在只是执行的都是计算机最喜欢的循环运算和数学运算,相比法1的split和equals这些字符串操作来说,效率高了不少。


游泳


昨天去游泳,今天胳膊累的一点劲儿都没有,太久不运动了,突然想起来那首歌的歌词。


第二 就是身体一定要健康
因为身体要是不舒服
什么都是白给
所以我一周三次跑步加上一次游泳
在运动中想事儿是越想越起劲儿


以后多运动。。。