需求:在系统启动的时候把数据库的数据进行重置(或者插入数据,或者取出一系列的数据缓存起来)
摸索: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" />