需求:在系統啟動的時候把數據庫的數據進行重置(或者插入數據,或者取出一系列的數據緩存起來)
摸索:SBean可以IoC注入需要的資源比如DataSource;
Spring Bean Config
<bean id="idPoolsInitilizedProcessor" class="utils.IDPoolsInitilizedListener" scope="singleton" >
<property name="datasource" ref="dataDS"/>
</bean>
Spring Bean Code
public class JcIDPoolsInitilizedListener {
private DataSource datasource = null;
public JcIDPoolsInitilizedBean() {
System.out.println("%%%%%%%%%%%%%%");
try {
//initilize msgid
String refName = CxcConstants.REFCOUNTER_MSGID;
String sql = "update refcounter set nextnumber=(select max(msgid)+1 from msg) where refcounterid=?";
update(sql, new Object[]{refName});
} catch (Exception ex) {
ex.printStackTrace();
}
}
private int update(String anSql, Object[] args) throws Exception {
int affactRows = 0;
Connection con = null;
PreparedStatement stmt = null;
try {
con = datasource.getConnection();
stmt = con.prepareStatement(anSql);
setSQLParams(stmt, args);
affactRows = stmt.executeUpdate();
return affactRows;
} finally {
try{
if (null != stmt) {
stmt.close();
}
if (null != con) {
con.close();
}
} catch (Exception ex) {
ex.printStackTrace();
}
}
}
private void setSQLParams(PreparedStatement stmt, Object[] args) throws Exception {
if (null != args && 0 < args.length) {
for (int i = 0, n = args.length; i < n; i++) {
stmt.setObject(i + 1, args[i]);
}
}
}
public DataSource getDatasource() {
return datasource;
}
public void setDatasource(DataSource datasource) {
this.datasource = datasource;
}
}
結果:程序啟動的時候會拋出NullPointException,因為
datasource并沒有初始化好。
摸索:Spring的事件機制:實現ApplicationListener,在onApplicationEvent的方法進行數據初始化操作,只要容器啟動,就會執行這里的代碼。
public class JcIDPoolsInitilizedListener implements ApplicationListener {
private DataSource datasource = null;
public void onApplicationEvent(ApplicationEvent argo) {
//todo: code is same as previous
}
//todo: all the other part is same as previous
}
成功。
然后的然后呢?會發現程序中這個初始化被多次調用。
為什么呢? 原因是Listener定義不到位。
為什么呢? 只要是ApplicationEvent都會觸發,默認的事件是org.springframework.security.access.event.PublicInvocationEvent,肯定觸發的。
怎么辦呢?
好吧,既然是Listener,總得告訴它Listen什么Event吧。
第一 定義Listener
public class JcIDPoolsInitilizedListener implements ApplicationListener {
private DataSource datasource = null;
public void onApplicationEvent(ApplicationEvent argo) {
if (argo instanceof IDPoolsInitilizedEvent) {
//todo: code is same as previous
}
//todo: all the other part is same as previous
}
第二 定義Event
public class IDPoolsInitilizedEvent extends ApplicationEvent{
private static final long serialVersionUID = 646140097162842368L;
public IDPoolsInitilizedEvent(Object source){
super(source);
}
}
第三 定義Event拋出點
public class IDPoolsInitilizedBean implements ApplicationContextAware{
private ApplicationContext applicationContext;
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
this.applicationContext = applicationContext;
IDPoolsInitilizedEvent event = new IDPoolsInitilizedEvent("IDPoolsInitilized");
this.applicationContext.publishEvent(event);
}
}
第四 定義配置文件
<bean id="idPoolsInitilizedListenerProcessor" class="utils.IDPoolsInitilizedListenerBean"
scope="singleton" >
<property name="datasource" ref="dataDS"/>
</bean>
<bean id="idPoolsInitilizedProcessor" class="utils.IDPoolsInitilizedBean"
scope="singleton" />