傳統Spring項目
在寫傳統的spring項目中,一般通過初始化抽象類AbstractXmlApplicationContext 的實現類,並傳入spring.xml,來獲取應用上下文,最終通過getBean方法獲取bean,如下:
ApplicationContext app1 = new FileSystemXmlApplicationContext("applicationContext.xml");
app1.getBean("beanName");
ApplicationContext app2 = new ClassPathXmlApplicationContext("applicationContext.xml");
app2.getBean("beanName");
SpringBoot項目獲取bean的幾種方式
1. 通過啟動類中返回的上下文獲取
ConfigurableApplicationContext app = SpringApplication.run(BeanDemoApplication.class, args);
SpringUtil.setAppContext(app);
public class SpringUtil {
private static ApplicationContext appContext;
public static void setAppContext(ApplicationContext appContext) {
SpringUtil.appContext = appContext;
}
public static ApplicationContext getAppContext() {
return appContext;
}
}
在第三方類中使用:
ApplicationContext appContext = SpringUtil.getAppContext();
appContext.getBean("beanName");
2. 通過工具類獲取
RequestContextUtils.findWebApplicationContext(HttpServletRequest request)
,WebApplicationContextUtils.getWebApplicationContext(ServletContext sc)
a. 在controller中傳入request,例如:
public String test(HttpServletRequest request,HttpServletRequest response) {
WebApplicationContext wc = RequestContextUtils.findWebApplicationContext(request);
wc.getBean("beanName");
WebApplicationContext wc2 = WebApplicationContextUtils.getWebApplicationContext(request.getServletContext());
wc2.getBean("beanName");
}
b. 在service中或者其他后端服務中獲取:
HttpServletRequest request = ((ServletRequestAttributes)RequestContextHolder.getRequestAttributes()).getRequest();
WebApplicationContext wc = RequestContextUtils.findWebApplicationContext(request);
WebApplicationContext wc2 = WebApplicationContextUtils.getWebApplicationContext(request.getServletContext());
wc.getBean("beanName");
wc2.getBean("beanName");
3. 通過實現接口ApplicationContextAware
@Component
public class TestApplicationContextAware implements ApplicationContextAware {
private ApplicationContext applicationContext;
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
this.applicationContext = applicationContext;
}
public Object getBean(String beanName) {
return applicationContext.getBean(beanName);
}
public ApplicationContext getApplicationContext() {
return applicationContext;
}
}
在其他類中調用
@Autowired
private TestApplicationContextAware app;
public void testMethod() {
app.getBean("beanName");
}
4. 通過繼承抽象類:ApplicationObjectSupport,WebApplicationObjectSupport
原理參考第3點
5. 其他方式
在網上看,發現也可以直接調用:ContextLoader.getCurrentWebApplicationContext(),或者 ContextLoaderListener.getCurrentWebApplicationContext() 其實都是調用同一段代碼,如下:
@Nullable
public static WebApplicationContext getCurrentWebApplicationContext() {
ClassLoader ccl = Thread.currentThread().getContextClassLoader();
if (ccl != null) {
WebApplicationContext ccpt = currentContextPerThread.get(ccl);
if (ccpt != null) {
return ccpt;
}
}
return currentContext;
}
說明:目前通過這種方式獲取上下文為null,從代碼可以看出,上下文是通過currentContextPerThread.get(ccl)
來獲取的,而currentContextPerThread緩存是通過方法contextInitialized(ServletContextEvent event)
來初始化的,至於為何獲取為空,參考:https://www.cnblogs.com/xysn/p/14863896.html