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

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


当前回答

这里有一个很好的方法(不是我的,原始参考在这里: http://sujitpal.blogspot.com/2007/03/accessing-spring-beans-from-legacy-code.html

我使用过这种方法,效果很好。基本上,它是一个简单的bean,包含对应用程序上下文的(静态)引用。通过在spring配置中引用它来初始化它。

看看原来的裁判,非常清楚。

其他回答

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

不确定这有多有用,但你也可以在初始化应用程序时获得上下文。这是最快的你可以获得上下文,甚至在@Autowire之前。

@SpringBootApplication
public class Application extends SpringBootServletInitializer {
    private static ApplicationContext context;

    // I believe this only runs during an embedded Tomcat with `mvn spring-boot:run`. 
    // I don't believe it runs when deploying to Tomcat on AWS.
    public static void main(String[] args) {
        context = SpringApplication.run(Application.class, args);
        DataSource dataSource = context.getBean(javax.sql.DataSource.class);
        Logger.getLogger("Application").info("DATASOURCE = " + dataSource);

方法1:您可以通过实现ApplicationContextAware接口来注入ApplicationContext。参考链接。

@Component
public class ApplicationContextProvider implements ApplicationContextAware {

    private ApplicationContext applicationContext;

    public ApplicationContext getApplicationContext() {
        return applicationContext;
    }

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        this.applicationContext = applicationContext;
    }
}

方法2:在任何spring托管bean中自动装配应用程序上下文。

@Component
public class SpringBean {
  @Autowired
  private ApplicationContext appContext;
}

参考链接。

你可以实现ApplicationContextAware或者使用@Autowired:

public class SpringBean {
  @Autowired
  private ApplicationContext appContext;
}

SpringBean将注入ApplicationContext,在其中实例化此bean。例如,如果你有一个非常标准的上下文层次结构的web应用程序:

main application context <- (child) MVC context

并且SpringBean是在主上下文中声明的,它将被注入主上下文; 否则,如果它是在MVC上下文中声明的,它将被注入MVC上下文。

如果需要访问容器的对象是容器中的bean,则只需实现BeanFactoryAware或ApplicationContextAware接口。

如果容器外部的对象需要访问容器,我为spring容器使用了标准的GoF单例模式。这样,您的应用程序中只有一个单例bean,其余的都是容器中的单例bean。