是否有一种方法可以在Spring应用程序中静态/全局地请求ApplicationContext的副本?

假设主类启动并初始化了应用程序上下文,它是否需要通过调用堆栈向下传递给任何需要它的类,或者类是否有一种方法来请求先前创建的上下文?(我假设它必须是单例的?)


当前回答

在Spring应用程序中有许多获取应用程序上下文的方法。这些因素如下:

通过ApplicationContextAware: 进口org.springframework.beans.BeansException; 进口org.springframework.context.ApplicationContext; 进口org.springframework.context.ApplicationContextAware; 公共类AppContextProvider实现了ApplicationContextAware { private ApplicationContext; @Override setApplicationContext(ApplicationContext)抛出BeansException { 这一点。applicationContext = applicationContext; } }

这里setApplicationContext(ApplicationContext ApplicationContext)方法将获得ApplicationContext

ApplicationContextAware: 接口,由希望被通知的任何对象实现 它运行的ApplicationContext的。实现此接口 例如,当一个对象需要访问一组 合作bean。

通过Autowired的: @ autowired private ApplicationContext;

这里@Autowired关键字将提供applicationContext。自动连线有一些问题。这将在单元测试时产生问题。

其他回答

如果你使用的是web应用,还有另一种不使用单例的方式来访问应用上下文,那就是使用servletfilter和ThreadLocal。在过滤器中,您可以使用WebApplicationContextUtils访问应用程序上下文,并在TheadLocal中存储应用程序上下文或所需的bean。

警告:如果你忘记撤消ThreadLocal,你将在尝试撤消应用程序时遇到严重的问题!因此,您应该设置它,并立即开始尝试,在最后部分取消对ThreadLocal的设置。

当然,这仍然使用一个单例:ThreadLocal。但实际的豆子不需要再这样了。它甚至可以是请求范围的,如果应用程序中有多个war,并且EAR中的库也可以使用此解决方案。不过,您可能会认为ThreadLocal的这种使用与普通单例的使用一样糟糕。;-)

也许Spring已经提供了类似的解决方案?我没有找到,但我不确定。

在Spring bean中进行自动装配,如下所示:

@Autowired
private ApplicationContext appContext;

您将得到ApplicationContext对象。

在Spring应用程序中有许多获取应用程序上下文的方法。这些因素如下:

通过ApplicationContextAware: 进口org.springframework.beans.BeansException; 进口org.springframework.context.ApplicationContext; 进口org.springframework.context.ApplicationContextAware; 公共类AppContextProvider实现了ApplicationContextAware { private ApplicationContext; @Override setApplicationContext(ApplicationContext)抛出BeansException { 这一点。applicationContext = applicationContext; } }

这里setApplicationContext(ApplicationContext ApplicationContext)方法将获得ApplicationContext

ApplicationContextAware: 接口,由希望被通知的任何对象实现 它运行的ApplicationContext的。实现此接口 例如,当一个对象需要访问一组 合作bean。

通过Autowired的: @ autowired private ApplicationContext;

这里@Autowired关键字将提供applicationContext。自动连线有一些问题。这将在单元测试时产生问题。

请注意;下面的代码将创建新的应用程序上下文,而不是使用已经加载的上下文。

private static final ApplicationContext context = 
               new ClassPathXmlApplicationContext("beans.xml");

还要注意,beans.xml应该是src/main/resources的一部分,这意味着在war中它是WEB_INF/classes的一部分,其中真正的应用程序将通过Web.xml中提到的applicationContext.xml加载。

<context-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>META-INF/spring/applicationContext.xml</param-value>
</context-param>

在ClassPathXmlApplicationContext构造函数中很难提及applicationContext.xml路径。ClassPathXmlApplicationContext("META-INF/spring/applicationContext.xml")无法定位文件。

因此,最好通过使用注释来使用现有的applicationContext。

@Component
public class OperatorRequestHandlerFactory {

    public static ApplicationContext context;

    @Autowired
    public void setApplicationContext(ApplicationContext applicationContext) {
        context = applicationContext;
    }
}
SpringApplicationContext.java

import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;

/**
 * Wrapper to always return a reference to the Spring Application 
Context from
 * within non-Spring enabled beans. Unlike Spring MVC's 
WebApplicationContextUtils
 * we do not need a reference to the Servlet context for this. All we need is
 * for this bean to be initialized during application startup.
 */
public class SpringApplicationContext implements 
ApplicationContextAware {

  private static ApplicationContext CONTEXT;

  /**
   * This method is called from within the ApplicationContext once it is 
   * done starting up, it will stick a reference to itself into this bean.
  * @param context a reference to the ApplicationContext.
  */
  public void setApplicationContext(ApplicationContext context) throws BeansException {
    CONTEXT = context;
  }

  /**
   * This is about the same as context.getBean("beanName"), except it has its
   * own static handle to the Spring context, so calling this method statically
   * will give access to the beans by name in the Spring application context.
   * As in the context.getBean("beanName") call, the caller must cast to the
   * appropriate target class. If the bean does not exist, then a Runtime error
   * will be thrown.
   * @param beanName the name of the bean to get.
   * @return an Object reference to the named bean.
   */
  public static Object getBean(String beanName) {
    return CONTEXT.getBean(beanName);
  }
}

来源:http://sujitpal.blogspot.de/2007/03/accessing-spring-beans-from-legacy-code.html