cuiyi's blog(崔毅 crazycy)

          記錄點(diǎn)滴 鑒往事之得失 以資于發(fā)展
          數(shù)據(jù)加載中……

          Spring-系統(tǒng)啟動(dòng)時(shí)初始化數(shù)據(jù)庫的數(shù)據(jù)/系統(tǒng)啟動(dòng)時(shí)操作數(shù)據(jù)庫

          需求:在系統(tǒng)啟動(dòng)的時(shí)候把數(shù)據(jù)庫的數(shù)據(jù)進(jìn)行重置(或者插入數(shù)據(jù),或者取出一系列的數(shù)據(jù)緩存起來)

          摸索: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;
              }
          }

          結(jié)果:程序啟動(dòng)的時(shí)候會(huì)拋出NullPointException,因?yàn)?span style="font-size: 13px; background-color: #eeeeee;">datasource并沒有初始化好。

          摸索:Spring的事件機(jī)制:實(shí)現(xiàn)ApplicationListener,在onApplicationEvent的方法進(jìn)行數(shù)據(jù)初始化操作,只要容器啟動(dòng),就會(huì)執(zhí)行這里的代碼。

          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
          }

          成功。

          然后的然后呢?會(huì)發(fā)現(xiàn)程序中這個(gè)初始化被多次調(diào)用。
          為什么呢? 原因是Listener定義不到位。
          為什么呢? 只要是ApplicationEvent都會(huì)觸發(fā),默認(rèn)的事件是org.springframework.security.access.event.PublicInvocationEvent,肯定觸發(fā)的。

          怎么辦呢?
          好吧,既然是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拋出點(diǎn)

          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" />

          posted on 2013-03-17 19:55 crazycy 閱讀(5780) 評(píng)論(0)  編輯  收藏 所屬分類: JavaEE技術(shù)

          主站蜘蛛池模板: 中方县| 宣城市| 昭苏县| 塘沽区| 彭阳县| 高阳县| 红安县| 榆林市| 晋江市| 县级市| 双鸭山市| 项城市| 衡阳市| 新兴县| 乐业县| 巴楚县| 裕民县| 开平市| 天全县| 秭归县| 邵阳市| 凤阳县| 绥中县| 延边| 昌都县| 武宁县| 富顺县| 南昌市| 开江县| 靖宇县| 安塞县| 大庆市| 广安市| 伊宁县| 望都县| 宁都县| 开平市| 鹤峰县| 邵东县| 罗江县| 临湘市|