2011年6月11日 星期六

spring IoC 使用factoryBean

最近才開使接觸spring IoC ,一般在XML 中設定 的 property 都是使用
......
<bean id="someBean" class="xxx.ooo.ClassName">
 "property name="someField" ref="anotherObject">  
</bean>
......
時都是指定到另一個bean 的,做為參考。換言之一定會存在著
......
<bean id="anotherObject" class="xx.oo.ClassName2">
  ......
</bean>
......

但有時候需要的是用factory的方式產生出來才塞給像上述的 someField的話要怎麼做呢?
上網路上查詢,發現有三個方式。 我自行理解後,筆記如下:
1.用static method 產生物件
2.用一般method產生物件
3.用透過 實作 FactoryBean interface

方法1說明:
以上述的例子來說,假設我們要注入xxx.ooo.ClassName 類別的 someField 欄位,原本是指到anotherObject 這個bean;現在有另一個類別提供一個static method 會產生出someField 需要的物件。

public class StaticFactoryBeanTest {

 public static SomeFieldClass createObject()
 {
               ......
       return someFieldInstance;
 }
}

在XML 中的使用方式為:
<bean id="xx" class="oo.xx.StaticFactoryBeanTest" factory-method="createObject" />


這時候,bean xx 指的就不是 oo.xx.StaticFactoryBeanTest的物件而是 它的static method :createObject 所產生的物件,注意在XML 中要這樣使用,此方法必需為static method

方法2說明:
在XML 中使用方式為:
<bean id="instanceFactoryBean" class="oo.xx.InstanceFactoryBean">
......
</bean>
<bean id="product" factory-bean="instanceFactoryBean" factory-method="createProduct" />
instanceFactoryBean 是一般的bean ,它的類別是oo.xx.InstanceFactoryBean
但 product 它是靠 instanceFactoryBean 的 createProduct 方法產生的物件,所以它的class不是oo.xx.InstanceFactoryBean,而是看createProduct 產生了什麼。

方法3說明:
在XML 中使用方式為:
<bean id="product" class="oo.xx.MyFactoryBean" />
oo.xx.MyFactoryBean 是implements org.springframework.beans.factory.FactoryBean 這個interface
而FactoryBean 有三個method 分別是:
public Object getObject();
public Class getObjectType();
public boolean isSingleton();

而這個product 注入的是 oo.xx.MyFactoryBean 的getObject()方法產生的物件,並非是oo.xx.MyFactoryBean這個類別的instance

2011年6月3日 星期五

spring 使用 application 中定義的 properties

問題:
在applicationContext 中常會設定一個properties 來載入一些設定檔
通常是
<bean id="propertyConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
.....
</bean>

但發現 這個 PropertyPlaceholderConfigurer 類別不提供它的 java.util.Properties 讓我們用。
但是它的父類別org.springframework.core.io.support.PropertiesLoaderSupport 有提供一個protected method
protected Properties mergeProperties() throws IOException

所以這邊提供一種做法是,自己寫一個Class 繼承 PropertiesLoaderSupport ,然後裡面提供一個method

public class MyPropertyPlaceholderConfigurer extends
  PropertyPlaceholderConfigurer {

  Properties mergedProperties;

   public Properties getMergedProperties() throws IOException {
     if (mergedProperties == null) {

       mergedProperties = mergeProperties();

     }
     return mergedProperties;

   }
}

然後 applicationContext 裡的 propertyConfigurer設定改成
<bean id="propertyConfigurer" class="MyPropertyPlaceholderConfigurer">

......
這樣就可以在之後使用這個bean 取得 properties

由Spring 取得 Jboss JNDI datasource

問題:非一般由web container 取得JDNI 的方式。而是一隻獨立程式需要存取DB,要從JBoss取得JNDI datasource 。
解決方式:

在 applicationContext中
原本會有


...
 <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate" >
<property name="dataSource" ref="jdbcDataSource"/>
</bean>
<bean id="jdbcDataSource" class="org.springframework.jdbc.datasource.SingleConnectionDataSource"
...>
...
這是使用jdbc的方式連的

加上
<bean id="jndidataSource"  class="org.springframework.jndi.JndiObjectFactoryBean">
<property name="jndiName" value="your_JNDI_name"/>
<property name="resourceRef" value="false"/>
<property name="jndiTemplate" ref="jndiTemplate" />
</bean>
<bean id="jndiTemplate" class="org.springframework.jndi.JndiTemplate">
<property name="environment">
<props>
<prop key="java.naming.factory.initial">org.jnp.interfaces.NamingContextFactory</prop>
<prop key="java.naming.provider.url">jnp://your_JBoss_IP:1099</prop>
<prop key="java.naming.factory.url.pkgs">org.jboss.naming:org.jnp.interfaces</prop>
<prop key="jnp.disableDiscovery">true</prop>
</props>
</property>


然後在執行這隻獨立的jar 檔時,加上jboss 的jar 檔到 classpath中

for example:
java  -cp /...[jboss home].../jboss-as/client/jbossall-client.jar:yourJarFile.jar your.main.class
不過這個方式要JDNI,好久啊~久到爆炸,在自己的localhost 跑都要超過兩分鐘 orz

Cron Job 出現亂碼問題

問題: java file 丟到 linux 下執行有遇到io處理都好好的。但同一隻程式用 cron job 跑,有io 的部份就出現亂碼。

解決方法:
example.sh 範例
LC_ALL=zh_TW.UTF-8
LANG=zh_TW.UTF-8
/....[java path]..../java -Dfile.encoding=UTF-8 -jar yourJava.jar


這樣就能解決IO出現亂碼的問題了。