我正在使用Spring 3.0.3。
我想使用applicationContextProvider,所以我声明:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-3.0.xsd">
<bean id="applicationContextProvider" class="com.mycompany.util.ApplicationContextProvider"></bean>
<context:annotation-config/>
<tx:annotation-driven/>
</beans>
和我的ApplicationContextProvider:
public class ApplicationContextProvider implements ApplicationContextAware {
private static ApplicationContext applicationContext = null;
public static ApplicationContext getApplicationContext() {
return applicationContext;
}
public void setApplicationContext(ApplicationContext _applicationContext) throws BeansException {
applicationContext = _applicationContext;
}
}
但该套装永远不会被召唤!
每当我使用ApplicationContextProvider.getApplicationContext()
时,都会返回null。
为什么会这样?
答案 0 :(得分:4)
部分问题可能是你的getter是静态的。因此,您可以在Spring创建ApplicationContextProvider实例之前调用它。
当Spring准备好使用它时,你需要引用Spring为你创建的bean'applicationContextProvider'。见Bean lifecycle
E.g。通过在src / test / resources
中的'app-context.xml'中使用bean进行Junit测试package com.mycompany.util;
import static org.junit.Assert.*;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
@ContextConfiguration(locations="classpath:app-context.xml")
@RunWith(SpringJUnit4ClassRunner.class)
public class ApplicationContextProviderTest {
@Autowired // Injected by Spring when bean is "ready"
ApplicationContextProvider contextProvider;
@Test
public void testContext() {
assertNotNull(contextProvider);
ApplicationContext context = ApplicationContextProvider.getApplicationContext();
assertNotNull(context);
System.out.println("My context has " + context.getBeanDefinitionCount() + " beans");
}
}
然后,这将为设置applicationContext设置一个绿色条。
示例输出(不要将System.out保留在测试btw中)。
INFO : org.springframework.test.context.TestContextManager - @TestExecutionListeners is not present for class [class com.mycompany.util.ApplicationContextProviderTest]: using defaults.
INFO : org.springframework.beans.factory.xml.XmlBeanDefinitionReader - Loading XML bean definitions from class path resource [app-context.xml]
INFO : org.springframework.context.support.GenericApplicationContext - Refreshing org.springframework.context.support.GenericApplicationContext@4c331059: startup date [Sun Feb 27 13:38:13 GMT 2011]; root of context hierarchy
INFO : org.springframework.beans.factory.support.DefaultListableBeanFactory - Pre-instantiating singletons in org.springframework.beans.factory.support.DefaultListableBeanFactory@4b1c2b67: defining beans [applicationContextProvider,org.springframework.context.annotation.internalConfigurationAnnotationProcessor,org.springframework.context.annotation.internalAutowiredAnnotationProcessor,org.springframework.context.annotation.internalRequiredAnnotationProcessor,org.springframework.context.annotation.internalCommonAnnotationProcessor]; root of factory hierarchy
My context has 5 beans
INFO : org.springframework.context.support.GenericApplicationContext - Closing org.springframework.context.support.GenericApplicationContext@4c331059: startup date [Sun Feb 27 13:38:13 GMT 2011]; root of context hierarchy
INFO : org.springframework.beans.factory.support.DefaultListableBeanFactory - Destroying singletons in org.springframework.beans.factory.support.DefaultListableBeanFactory@4b1c2b67: defining beans [applicationContextProvider,org.springframework.context.annotation.internalConfigurationAnnotationProcessor,org.springframework.context.annotation.internalAutowiredAnnotationProcessor,org.springframework.context.annotation.internalRequiredAnnotationProcessor,org.springframework.context.annotation.internalCommonAnnotationProcessor]; root of factory hierarchy
APP-context.xml中:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="applicationContextProvider" class="com.mycompany.util.ApplicationContextProvider"></bean>
</beans>
答案 1 :(得分:0)
看起来你在这里做错了什么......你想从不受Spring管理的对象访问Spring bean吗? WebApplicationContextUtils:
怎么样?WebApplicationContextUtils.getRequiredWebApplicationContext(servletContext);
但是WebApplicationContextUtils
应始终被视为最后的手段,因为这不是 Spring方式。您确定无法以某种方式将Web服务与Spring集成吗?例如,对于Apache CXF,可以简单地将WS端点实现为Spring bean或将客户端代理注入其他bean ...
使用静态字段总是在问自己麻烦。我相信你能以更优雅的方式实现你的目标。
答案 2 :(得分:0)
这是一个已经被接受的答案的旧问题,但对我来说,为什么setApplicationContext()
方法没有在applicationContextProvider
上被调用,我们并不清楚。答案提供了如何,但实际上并非为什么。
Spring使用延迟策略创建bean:只在第一次需要时才创建bean。这就是为什么接受的答案中的示例有效:ApplicationContextProviderTest
需要bean,因此它是在那时创建的,而不是之前创建的,并且在那个时间点调用setApplicationContext()
方法按预期工作。
但是,如果您的bean没有自动连接到任何地方,则不会发生这种情况。在这种情况下,解决方案是告诉Spring不要使用惰性实例化,即:
<bean id="applicationContextProvider" lazy-init="false" class="com.mycompany.util.ApplicationContextProvider" />
这样,bean将在应用程序启动时创建,并且当时将调用方法setApplicationContext()
。然后,只要在应用程序启动完成后发生用法,就可以使用bean后缀。
当然,更好的方法是在任何需要的地方自动连接bean,但有时候不可能(阅读:遗留应用程序)。