Code Bye

Junit测试时ContextLoader.getCurrentWebApplicationContext()返回空值

 

Junit测试时,test类调用manage类,manage类调用dao类
dao类的代码中有如下语句:ContextLoader.getCurrentWebApplicationContext()
执行这条语句时返回空值,程序代码如下:




下面给出junit测试时的错误语句

下面给出Junit运行时控制台输出的语句:

九月 26, 2014 9:31:33 上午 org.springframework.context.support.ClassPathXmlApplicationContext prepareRefresh
INFO: Refreshing org.springframework.context.support.ClassPathXmlApplicationContext@5cba16: startup date [Fri Sep 26 09:31:33 CST 2014]; root of context hierarchy
九月 26, 2014 9:31:33 上午 org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions
INFO: Loading XML bean definitions from class path resource [applicationContext.xml]
九月 26, 2014 9:31:34 上午 org.springframework.context.support.PropertySourcesPlaceholderConfigurer loadProperties
INFO: Loading properties file from class path resource [jdbc.properties]
九月 26, 2014 9:31:34 上午 org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor <init>
INFO: JSR-330 ""javax.inject.Inject"" annotation found and supported for autowiring
九月 26, 2014 9:31:34 上午 com.mchange.v2.log.slf4j.Slf4jMLog$Slf4jMLogger$InfoLogger log
INFO: MLog clients using slf4j logging.
九月 26, 2014 9:31:34 上午 com.mchange.v2.log.slf4j.Slf4jMLog$Slf4jMLogger$InfoLogger log
INFO: Initializing c3p0-0.9.5-pre8 [built 04-April-2014 04:20:15 -0700; debug? true; trace: 10]
九月 26, 2014 9:31:34 上午 org.hibernate.annotations.common.reflection.java.JavaReflectionManager <clinit>
INFO: HCANN000001: Hibernate Commons Annotations {4.0.4.Final}
九月 26, 2014 9:31:34 上午 org.hibernate.Version logVersion
INFO: HHH000412: Hibernate Core {4.3.5.Final}
九月 26, 2014 9:31:34 上午 org.hibernate.cfg.Environment <clinit>
INFO: HHH000206: hibernate.properties not found
九月 26, 2014 9:31:34 上午 org.hibernate.cfg.Environment buildBytecodeProvider
INFO: HHH000021: Bytecode provider name : javassist
九月 26, 2014 9:31:34 上午 com.mchange.v2.log.slf4j.Slf4jMLog$Slf4jMLogger$InfoLogger log
INFO: Initializing c3p0 pool... com.mchange.v2.c3p0.ComboPooledDataSource [ acquireIncrement -> 3, acquireRetryAttempts -> 30, acquireRetryDelay -> 1000, autoCommitOnClose -> false, automaticTestTable -> null, breakAfterAcquireFailure -> false, checkoutTimeout -> 0, connectionCustomizerClassName -> null, connectionTesterClassName -> com.mchange.v2.c3p0.impl.DefaultConnectionTester, contextClassLoaderSource -> caller, dataSourceName -> 1hge137941cpv65mc0oevj|15fcabc, debugUnreturnedConnectionStackTraces -> false, description -> null, driverClass -> com.microsoft.sqlserver.jdbc.SQLServerDriver, extensions -> {}, factoryClassLocation -> null, forceIgnoreUnresolvedTransactions -> false, forceUseNamedDriverClass -> false, identityToken -> 1hge137941cpv65mc0oevj|15fcabc, idleConnectionTestPeriod -> 60, initialPoolSize -> 10, jdbcUrl -> jdbc:sqlserver://localhost:1433;DatabaseName=zl, maxAdministrativeTaskTime -> 0, maxConnectionAge -> 0, maxIdleTime -> 60, maxIdleTimeExcessConnections -> 0, maxPoolSize -> 30, maxStatements -> 200, maxStatementsPerConnection -> 30, minPoolSize -> 5, numHelperThreads -> 3, preferredTestQuery -> null, privilegeSpawnedThreads -> false, properties -> {user=******, password=******}, propertyCycle -> 0, statementCacheNumDeferredCloseThreads -> 0, testConnectionOnCheckin -> false, testConnectionOnCheckout -> false, unreturnedConnectionTimeout -> 0, userOverrides -> {}, usesTraditionalReflectiveProxies -> false ]
九月 26, 2014 9:31:35 上午 org.hibernate.dialect.Dialect <init>
INFO: HHH000400: Using dialect: org.hibernate.dialect.SQLServer2008Dialect
九月 26, 2014 9:31:35 上午 org.hibernate.engine.transaction.internal.TransactionFactoryInitiator initiateService
INFO: HHH000399: Using default transaction strategy (direct JDBC transactions)
九月 26, 2014 9:31:35 上午 org.hibernate.hql.internal.ast.ASTQueryTranslatorFactory <init>
INFO: HHH000397: Using ASTQueryTranslatorFactory
九月 26, 2014 9:31:35 上午 org.hibernate.validator.util.Version <clinit>
INFO: Hibernate Validator bean-validator-3.0-JBoss-4.0.2
九月 26, 2014 9:31:35 上午 org.hibernate.tool.hbm2ddl.SchemaUpdate execute
INFO: HHH000228: Running hbm2ddl schema update
九月 26, 2014 9:31:35 上午 org.hibernate.tool.hbm2ddl.SchemaUpdate execute
INFO: HHH000102: Fetching database metadata
九月 26, 2014 9:31:35 上午 org.hibernate.tool.hbm2ddl.SchemaUpdate execute
INFO: HHH000396: Updating schema
九月 26, 2014 9:31:35 上午 org.hibernate.tool.hbm2ddl.TableMetadata <init>
INFO: HHH000261: Table found: zl.dbo.t_user
九月 26, 2014 9:31:35 上午 org.hibernate.tool.hbm2ddl.TableMetadata <init>
INFO: HHH000037: Columns: [id, username, allowance, name, basepay, salary, realname, duties, branchname, password, indexs]
九月 26, 2014 9:31:35 上午 org.hibernate.tool.hbm2ddl.TableMetadata <init>
INFO: HHH000108: Foreign keys: []
九月 26, 2014 9:31:35 上午 org.hibernate.tool.hbm2ddl.TableMetadata <init>
INFO: HHH000126: Indexes: [pk__t_user__3213e83f060deae8, uk_g8gqk4e142wekcb1t6d3v2mwx]
九月 26, 2014 9:31:35 上午 org.hibernate.tool.hbm2ddl.SchemaUpdate execute
INFO: HHH000232: Schema update complete
九月 26, 2014 9:31:36 上午 org.springframework.orm.hibernate4.HibernateTransactionManager afterPropertiesSet
INFO: Using DataSource [com.mchange.v2.c3p0.ComboPooledDataSource [ acquireIncrement -> 3, acquireRetryAttempts -> 30, acquireRetryDelay -> 1000, autoCommitOnClose -> false, automaticTestTable -> null, breakAfterAcquireFailure -> false, checkoutTimeout -> 0, connectionCustomizerClassName -> null, connectionTesterClassName -> com.mchange.v2.c3p0.impl.DefaultConnectionTester, contextClassLoaderSource -> caller, dataSourceName -> 1hge137941cpv65mc0oevj|15fcabc, debugUnreturnedConnectionStackTraces -> false, description -> null, driverClass -> com.microsoft.sqlserver.jdbc.SQLServerDriver, extensions -> {}, factoryClassLocation -> null, forceIgnoreUnresolvedTransactions -> false, forceUseNamedDriverClass -> false, identityToken -> 1hge137941cpv65mc0oevj|15fcabc, idleConnectionTestPeriod -> 60, initialPoolSize -> 10, jdbcUrl -> jdbc:sqlserver://localhost:1433;DatabaseName=zl, maxAdministrativeTaskTime -> 0, maxConnectionAge -> 0, maxIdleTime -> 60, maxIdleTimeExcessConnections -> 0, maxPoolSize -> 30, maxStatements -> 200, maxStatementsPerConnection -> 30, minPoolSize -> 5, numHelperThreads -> 3, preferredTestQuery -> null, privilegeSpawnedThreads -> false, properties -> {user=******, password=******}, propertyCycle -> 0, statementCacheNumDeferredCloseThreads -> 0, testConnectionOnCheckin -> false, testConnectionOnCheckout -> false, unreturnedConnectionTimeout -> 0, userOverrides -> {}, usesTraditionalReflectiveProxies -> false ]] of Hibernate SessionFactory for HibernateTransactionManager

但是,按照下面的逻辑顺序来执行时却没有发生错误:
action类调用manage类,manage类调用dao类,manage类和dao类的代码不变。
下面给出action类的代码:

我想请问一下,这是为什么?如何解决?请给出具体的代码,先谢了!

Service层哪来的WebApplicationContext? 只有类装载器在装载MVC层时才加载WebApplicationContext。

一个最简单的解决办法是:
Service层写一个类,定义一个静态的ApplicationContext属性,并将该类实现ApplicationListener监听接口,在监听到的容器事件中将ApplicationContext引用赋给类属性。最后将该类装配到Spring容器。
代码如下:

@Service
public class SystemManageServiceImpl implements SystemManageService,ApplicationListener<ContextRefreshedEvent>{
    private static ApplicationContext applicationContext = null;

    public void onApplicationEvent(ContextRefreshedEvent event){
        if(this.applicationContext == null){
            this.applicationContext = event.getApplicationContext();
        }
    }

    public Boolean checkUnique(){
        //this.applicationContext.getBean(...);
    }
}

另外楼主用了内省和反射,效率低啊。既然所有Manage类都有checkUnique方法,为什么不用接口或抽象类?这样this.applicationContext.getBean(…)赋给接口或抽象类,就可以直接执行checkUnique方法啊。

引用 1 楼 zhangjihao 的回复:

Service层哪来的WebApplicationContext? 只有类装载器在装载MVC层时才加载WebApplicationContext。

一个最简单的解决办法是:
Service层写一个类,定义一个静态的ApplicationContext属性,并将该类实现ApplicationListener监听接口,在监听到的容器事件中将ApplicationContext引用赋给类属性。最后将该类装配到Spring容器。
代码如下:

@Service
public class SystemManageServiceImpl implements SystemManageService,ApplicationListener<ContextRefreshedEvent>{
    private static ApplicationContext applicationContext = null;

    public void onApplicationEvent(ContextRefreshedEvent event){
        if(this.applicationContext == null){
            this.applicationContext = event.getApplicationContext();
        }
    }

    public Boolean checkUnique(){
        //this.applicationContext.getBean(...);
    }
}

另外楼主用了内省和反射,效率低啊。既然所有Manage类都有checkUnique方法,为什么不用接口或抽象类?这样this.applicationContext.getBean(…)赋给接口或抽象类,就可以直接执行checkUnique方法啊。

按照你的方法,我的问题已经解决了!
不过关于你所的checkUnique采用反射机制来调用,效率会很低,现在我给出我的想法,请您在多多指教!
设计checkUnique的目的:
在jsp页面中,设置input标签的checkUnique属性为true,表示对这个输入框中输入的值,他保存到数据库中对应的字段后,在这个字段中,他的值是不是唯一的。服务器后台的checkUnique方法就是用来实现这个功能的。
设计checkUnique的设计思路:
当jsp页面的input输入框失去焦点后,jsp开始向服务器提交请求,开始检查这个输入的数据是不是唯一的。
我现在提交数据的地址是同一个地址,都是dataAction.action中的checkUnique,然后在dataManage类中反射调用每个Manage类的checkUnique方法。
如果不用反射调用,那么,jsp页面提交数据到服务器的时候,每个jsp页面提交数据的地址是不同的,这样每个实体类所对应的action类都必须要有checkUnique。


60分
public interface CheckUnique{
    public Boolean checkUnique(String name, String value);
}

public class UserManageServiceImpl implements?UserManageService, CheckUnique{
    public Boolean checkUnique(String name, String value){
        //todo
    }
}

public class SystemDataManageServiceImpl implements SystemDataManageService, CheckUnique{
    public Boolean checkUnique(String name, String value){
        //todo
    }
}

//调用
CheckUnique checkUnique = (CheckUnique)this.applicationContext.getBean(u2eMapping.getBeanName);//保证u2eMapping缓存里放的bean都是CheckUnique的实现类
return checkUnique.checkUnique(...,...);


CodeBye 版权所有丨如未注明 , 均为原创丨本网站采用BY-NC-SA协议进行授权 , 转载请注明Junit测试时ContextLoader.getCurrentWebApplicationContext()返回空值