spring中获得applicationcontext的方法总结

 

方法一:在初始化时保存ApplicationContext对象

 

注:其中FileSystemXmlApplicationContext和ClassPathXmlApplicationContext与BeanFactory的xml文件定位方式一样是基于路径的。   

说明:这种方式适用于采用Spring框架的独立应用程序,需要程序通过配置文件手工初始化Spring的情况。


方法二:通过Spring提供的工具类获取ApplicationContext对象

 

 

import org.springframework.web.context.support.WebApplicationContextUtils;
ApplicationContext ac1 = WebApplicationContextUtils.getRequiredWebApplicationContext(ServletContext sc);
ApplicationContext ac2 = WebApplicationContextUtils.getWebApplicationContext(ServletContext sc);
ac1.getBean("beanId");
ac2.getBean("beanId");

说明:
这种方式适合于采用Spring框架的B/S系统,通过ServletContext对象获取ApplicationContext对象,然后在通过它获取需要的类实例。
上面两个工具方式的区别是,前者在获取失败时抛出异常,后者返回null。
其中 servletContext sc 可以具体 换成 servlet.getServletContext()或者 this.getServletContext() 或者 request.getSession().getServletContext(); 另外,由于spring是注入的对象放在ServletContext中的,所以可以直接在ServletContext取出 WebApplicationContext 对象: WebApplicationContext webApplicationContext = (WebApplicationContext) servletContext.getAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE);


方法三:继承自抽象类ApplicationObjectSupport

 

说明:抽象类ApplicationObjectSupport提供getApplicationContext()方法,可以方便的获取到ApplicationContext。
Spring初始化时,会通过该抽象类的setApplicationContext(ApplicationContext context)方法将ApplicationContext 对象注入。


方法四:继承自抽象类WebApplicationObjectSupport
说明:类似上面方法,调用getWebApplicationContext()获取WebApplicationContext


方法五:实现接口ApplicationContextAware
说明:实现该接口的setApplicationContext(ApplicationContext context)方法,并保存ApplicationContext 对象。
Spring初始化时,会通过该方法将ApplicationContext对象注入。
在web应用中一般用ContextLoaderListener加载webapplication,如果需要在action之外或者control类之外获取webapplication思路之一是,单独写个类放在static变量中,
类似于:

 

public class AppContext {

  private static AppContext instance;

  private AbstractApplicationContext appContext;

  public synchronized static AppContext getInstance() {
    if (instance == null) {
      instance = new AppContext();
    }
    return instance;
  }

  private AppContext() {
    this.appContext = new ClassPathXmlApplicationContext(
        "/applicationContext.xml");
  }

  public AbstractApplicationContext getAppContext() {
    return appContext;
  }
} 

 不过这样,还是加载了2次applicationcontext,servlet一次,路径加载一次;觉得不如直接用路径加载,舍掉servlet加载.
在网上也找了些其他说法:实现ApplicationContextAware,,, 接口,或者servletcontextAware接口,还要写配置文件。有的竟然要把配置文件里的listener,换成自己的类,这样纯粹多此一举。不过有的应用不是替换,是在补一个listener,我在一版的jpetstore(具体那一版不知道)里发现了这个:[web.xml]里 

  <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>
    
    <listener>
        <listener-class>com.ibatis.jpetstore.util.SpringInit</listener-class>
    </listener>

其中SpringInit实现接口ServletContextListener :

package com.ibatis.jpetstore.util;

import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import org.springframework.context.ApplicationContext;
import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.context.support.WebApplicationContextUtils;


public class SpringInit implements ServletContextListener {
    

    private static WebApplicationContext springContext;
    
    public SpringInit() {
        super();
    }
    
    public void contextInitialized(ServletContextEvent event) {
        springContext = WebApplicationContextUtils.getWebApplicationContext(event.getServletContext());
    }
    

    public void contextDestroyed(ServletContextEvent event) {
    }
    
    public static ApplicationContext getApplicationContext() {
        return springContext;
    }

    
}

  

 
<think>好的,用户现在的问题是想要在Spring的单元测试中获取ApplicationContext。之前他们已经询问过关于Java判断路径的问题,现在转向了Spring框架的单元测试,可能是在开发中遇到了需要访问应用上下文的情况。 首先,我需要确定用户的使用场景。他们可能是在编写单元测试时,需要从ApplicationContext中获取Bean来进行测试。比如,测试某个Service类时,可能需要注入依赖的其他组件。这时候,如何正确获取ApplicationContext就变得重要了。 接下来,用户可能的身份应该是一个Java开发者,对Spring框架有一定的了解,但可能在单元测试的具体实现上还不够熟悉。他们可能在使用Spring Boot,或者传统的Spring项目,需要知道不同环境下如何获取应用上下文。 用户的需求明确是获取ApplicationContext,但可能还有更深层的需求。比如,他们可能希望了解不同方法之间的区别,哪种方法更适合当前项目,或者在不同测试框架(如JUnit 4和JUnit 5)中的实现方式有什么不同。此外,可能还关心如何避免常见的错误,比如空指针异常,或者如何在没有启动整个应用的情况下进行测试。 在之前的回答中,用户得到了关于文件路径判断的解决方案,现在转向Spring单元测试,可能需要类似的步骤清晰的指导。所以,我应该分点说明不同的方法,并比较它们的优缺点,同时提供示例代码,确保用户能够直接应用。 首先想到的是使用Spring Test框架提供的注解,比如@RunWith(SpringJUnit4ClassRunner.class)或@ExtendWith(SpringExtension.class),这取决于使用的是JUnit 4还是5。在这些测试类中,可以通过@Autowired直接注入ApplicationContext,这是最常用的方法,但需要确保测试类被正确配置,加载了上下文。 另外,如果用户使用的是Spring Boot,@SpringBootTest注解会自动加载应用上下文,这时候注入ApplicationContext会更简单。但需要注意测试的配置是否正确,比如主启动类的位置。 还有一种情况是,用户可能在编写非集成测试,或者需要手动获取ApplicationContext。这时候可能需要通过ContextConfiguration来指定配置文件,或者使用AnnotationConfigApplicationContext来构建上下文。不过这种情况在单元测试中较少见,更多用于集成测试或独立的应用中。 此外,需要提醒用户注意测试的依赖是否正确引入,比如是否添加了spring-test的依赖,以及JUnit的版本是否匹配。否则,注解可能无法正常工作,导致ApplicationContext无法注入。 还要考虑可能的陷阱,比如测试类没有被Spring管理,导致自动注入失败。这时候需要检查测试类是否正确使用了Spring的Runner或扩展。另外,如果应用上下文较大,启动时间较长,可能影响测试效率,这时候可以使用@MockBean或@SpyBean来模拟部分依赖,而不是加载整个上下文。 最后,总结不同方法的适用场景,推荐用户根据项目情况选择合适的方式。比如,如果使用Spring Boot和JUnit 5,优先选择@SpringBootTest和@ExtendWith的组合;如果是传统的Spring项目,可能需要使用@ContextConfiguration和@RunWith。</think>在 Spring 单元测试中获取 `ApplicationContext` 是常见的需求,以下是 **不同场景下的实现方法** 和最佳实践: --- ### 方法 1:直接注入 `ApplicationContext`(推荐) 通过 `@Autowired` 注解直接注入上下文(适用于 **Spring Boot** 和传统 Spring 项目): ```java @SpringBootTest // Spring Boot 测试 // @ContextConfiguration(classes = AppConfig.class) // 传统 Spring 项目需指定配置类 public class MyTest { @Autowired private ApplicationContext applicationContext; // 直接注入 @Test public void testContextLoads() { Assert.assertNotNull(applicationContext); } } ``` --- ### 方法 2:通过测试基类获取(继承 `AbstractJUnit4SpringContextTests`) 仅适用于 **JUnit 4** 和传统 Spring 项目: ```java @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(locations = "classpath:applicationContext.xml") public class LegacySpringTest extends AbstractJUnit4SpringContextTests { @Test public void testContext() { ApplicationContext ctx = super.applicationContext; // 直接从基类获取 Assert.assertNotNull(ctx.getBean("myBean")); } } ``` --- ### 方法 3:手动加载上下文(适用于简单场景) 通过 `AnnotationConfigApplicationContext` 或 `ClassPathXmlApplicationContext` **手动创建**: ```java public class ManualContextTest { @Test public void testManualContext() { // 基于注解配置(推荐) ApplicationContext ctx = new AnnotationConfigApplicationContext(AppConfig.class); // 或基于 XML 配置 // ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml"); Assert.assertNotNull(ctx.getBean(MyService.class)); } } ``` --- ### 方法 4:通过 `TestContext` 框架获取(灵活但复杂) 适用于需要动态操作的场景: ```java @SpringJUnitConfig(classes = AppConfig.class) // JUnit 5 风格 public class AdvancedTest { @Autowired private ApplicationContext applicationContext; @Test public void testWithTestContext() { // 通过 TestContextManager 访问上下文(极少需要) TestContextManager testContextManager = new TestContextManager(getClass()); testContextManager.prepareTestInstance(this); Assert.assertNotNull(applicationContext); } } ``` --- ### 关键注意事项 1. **依赖配置**: - 确保测试类添加了 `@SpringBootTest`(Spring Boot)或 `@ContextConfiguration`(传统 Spring)。 - Maven/Gradle 需引入 `spring-test` 依赖: ```xml <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> ``` 2. **JUnit 版本适配**: - **JUnit 4**:使用 `@RunWith(SpringRunner.class)` - **JUnit 5**:使用 `@ExtendWith(SpringExtension.class)`(已包含在 `@SpringBootTest` 中) 3. **性能优化**: - 使用 `@MockBean` 或 `@SpyBean` 减少上下文加载的 Bean 数量。 - 通过 `@TestConfiguration` 局部覆盖配置,避免加载完整上下文。 --- ### 常见问题解决 - **空指针异常**: - 检查是否漏写 `@SpringBootTest` 或 `@ContextConfiguration`。 - 确认测试类在 `src/test/java` 目录下,且包路径与主代码一致。 - **上下文未加载 Bean**: - 使用 `@ComponentScan` 或在配置类中明确定义 Bean。 - 确保测试配置类(如 `AppConfig.class`)包含所需 Bean。 --- ### 总结 - **优先选择**:直接注入 `ApplicationContext`(方法 1),简单且与 Spring Boot 深度集成。 - **传统项目**:使用方法 2 或方法 3。 - **避免过度加载**:通过 `@SpringBootTest(webEnvironment = NONE)` 关闭 Web 环境以加速测试。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值