Spring-系统启动时初始化数据库的数据/系统启动时操作数据库
需求:在系统启动的时候把数据库的数据进行重置(或者插入数据,或者取出一系列的数据缓存起来)
摸索:SBean可以IoC注入需要的资源比如DataSource;
Spring Bean Config
Spring Bean Code
结果:程序启动的时候会抛出NullPointException,因为 datasource并没有初始化好。
摸索:Spring的事件机制:实现ApplicationListener,在onApplicationEvent的方法进行数据初始化操作,只要容器启动,就会执行这里的代码。
成功。
然后的然后呢?会发现程序中这个初始化被多次调用。
为什么呢? 原因是Listener定义不到位。
为什么呢? 只要是ApplicationEvent都会触发,默认的事件是org.springframework.security.access.event.PublicInvocationEvent,肯定触发的。
怎么办呢?
好吧,既然是Listener,总得告诉它Listen什么Event吧。
第一 定义Listener
第二 定义Event
第三 定义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);
}
}
第四 定义配置文件
摸索:SBean可以IoC注入需要的资源比如DataSource;
Spring Bean Config
<
bean
id
="idPoolsInitilizedProcessor"
class
="utils.IDPoolsInitilizedListener"
scope
="singleton"
>
< property name ="datasource" ref ="dataDS" />
</ bean >
< 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;
}
}
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
}
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
}
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);
}
}
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" />
scope ="singleton" >
< property name ="datasource" ref ="dataDS" />
</ bean >
< bean id ="idPoolsInitilizedProcessor" class ="utils.IDPoolsInitilizedBean"
scope ="singleton" />