Spring bean无法初始化

今天在开发的时候,想在Bean初始化的时候,将数据库中的数据加载到Redis中所以写了一个Bean,具体如下:
 
(1)加载Bean
package com.crm.application;

import java.sql.Connection;
import java.sql.Statement;

import javax.servlet.ServletContext;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.web.context.ServletContextAware;

import com.crm.application.load.RedisLoadThread;
import com.crm.h2.H2Manager;
import com.crm.h2.load.H2LoadThread;

public class CrmApplication implements InitializingBean, ServletContextAware{
 
 private Log log = LogFactory.getLog(CrmApplication.class);
 
 public void setServletContext(ServletContext arg0) {
  log.info("-------------------------【Crm系统初始化】开始-------------------------");
  try {
   
   log.info("----------【H2处理】----------");
   Connection conn = H2Manager.getConnection();
   Statement stmt = conn.createStatement();
   stmt.executeUpdate(H2Manager.getCreateCrmTranslateKindSql());
   stmt.executeUpdate(H2Manager.getCreateCrmTranslateMapSql());
   conn.close();
   new H2LoadThread().start();
   
   log.info("----------【Redis加载】----------");
   new RedisLoadThread().start();
   
  } catch (Exception e) {
   e.printStackTrace();
  }
 
  log.info("-------------------------【Crm系统初始化】结束-------------------------");
 }
 
 
 //InitializingBean
 public void afterPropertiesSet() throws Exception {
  log.info("afterPropertiesSet...");
 }
 
}
 
 
 
(2)Bean配置
<beans xmlns="http://www.springframework.org/schema/beans"

xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"

xmlns:jdbc="http://www.springframework.org/schema/jdbc" xmlns:jee="http://www.springframework.org/schema/jee"

xmlns:tx="http://www.springframework.org/schema/tx" xmlns:jpa="http://www.springframework.org/schema/data/jpa"

xsi:schemaLocation="  

        http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.1.xsd  

        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.1.xsd  

        http://www.springframework.org/schema/jdbc http://www.springframework.org/schema/jdbc/spring-jdbc-4.1.xsd  

        http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-4.1.xsd  

        http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.1.xsd  

        http://www.springframework.org/schema/data/jpa http://www.springframework.org/schema/data/jpa/spring-jpa.xsd"

default-lazy-init="true">


<context:component-scan base-package="com.crm.service" />

<context:component-scan base-package="com.crm.repository" />


<bean id="CrmContext" class="com.crm.application.CrmContext" ></bean>

<bean id="CrmApplication" class="com.crm.application.CrmApplication" ></bean>
 
(3)系统启动
可是系统启动的时候,死活不实例化CrmApplication这个Bean,令人费解
找了很久,竟然发现
default-lazy-init="true"

这句话导致的

 
(4)错误分析
 
 
(4.1)InitializingBean接口
为bean提供了初始化方法的方式,它只包括afterPropertiesSet方法,凡是继承该接口的类,在初始化bean的时候会执行该方法,可以获取spring的所有配置信息。但不是100%执行,就想我遇到的这种情况。
 

(4.2)实现ServletContextAware

可以获得servletcontext


 

(4.3)default-lazy-init="true":经常性的拷贝,也不理解这句话的含义


 
spring的容器是提供了lazy-load的,即默认的缺省设置是bean没有lazy-load,该属性处于false状态,这样导致spring在启动过程导致在启动时候,会默认加载整个对象实例图,从初始化ACTION配置、到service配置到dao配置、乃至到数据库连接、事务等等。 

这么庞大的规模,难怪spring的启动时间要花将近1分钟。尝试了一下,把beans的default-lazy-init改为true就,再次启动,速度从原来的55秒,降到8秒钟!!Great!虽然是非常小一个改动,但是影响确实非常大。 

详细内容参考:http://thinkerandthinker.iteye.com/blog/1337706

 
说白了,就是一旦在beans中配置了default-lazy-init="true",bean只有在用到的时候才进行实例化,并不会在启动的实例化
 
 
 
(5)扩展:控制Bean的初始化
 
(5.1)监听模式
implements ServletContextListener 
 
(5.2)配置init-method方式
<bean id="CrmApplication" class="com.crm.application.CrmApplication" init-method=""></bean>
 
(5.3)接口模式
implements InitializingBean
 
(5.2)VS(5.3):
 

在spring初始化bean的时候,如果该bean是实现了InitializingBean接口,并且同时在配置文件中指定了init-method,系统则是先调用afterPropertiesSet方法,然后在调用init-method中指定的方法。

 
 
 
 

猜你喜欢

转载自toknowme.iteye.com/blog/2236027