1. 程式人生 > >關於spring獲取webApplication.getBean多種途徑和簡單解釋

關於spring獲取webApplication.getBean多種途徑和簡單解釋

illegal {} 工廠 ring 後者 ram title 關於 files

  1. ApplicationContext ac1 = new FileSystemXmlApplicationContext("com/spark/system/applicationContext.xml");//如果配置文件放在文件系統的目錄下則優先使用該方式
  2. //com/spark/system/applicationContext.xml等價於"file:com/spark/system/applicationContext.xml"
  3. ac1.getBean("beanId");
  4. //ApplicationContext ac2=new ClassPathXmlApplicationContext("com/spark/system/applicationContext.xml");//如果配置文件在類路徑下則優先使用該方式
  5. //com/spark/system/applicationContext.xml 等價於"classpath:com/spark/system/applicationContext.xml"
  6. ac2.getBean("beanId");
說明:

這種方式適用於采用Spring框架的獨立應用程序,需要程序通過配置文件手工初始化Spring的情況。


  1. public void getBean(HttpServletRequest req,HttpSession se)
  2. {
  3. // se.getServletContext() 也可以
  4. WebApplicationContext wac=(WebApplicationContext)req.getServletContext().getAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE);
  5. wac.getBean("");
  6. }
說明:此種方式正是我們下面所提到的WebApplicationContextUtils 工具類中getWebApplicationContext(ServletContext sc) 方法的內部實現,以下方式是通過spring 提供的WebApplicationContextUtils 工具類獲取WebApplicationContext


方式一:

  1. import org.springframework.web.context.support.WebApplicationContextUtils;
  2. ApplicationContext ac1 = WebApplicationContextUtils.getRequiredWebApplicationContext(ServletContext sc)
  3. ApplicationContext ac2 = WebApplicationContextUtils.getWebApplicationContext(ServletContext sc)
  4. ac1.getBean("beanId");
  5. ac2.getBean("beanId");
說明:
這種方式適合於采用Spring框架的B/S系統,通過ServletContext對象獲取ApplicationContext對象,然後在通過它獲取需要的類實例。
上面兩個工具方式的區別是,前者在獲取失敗時拋出異常,後者返回null。


方式二:

  1. import org.springframework.web.context.WebApplicationContext;
  2. import org.springframework.web.context.support.WebApplicationObjectSupport;
  3. public class ApplicationContextUtils extends WebApplicationObjectSupport{
  4. public WebApplicationContext isgetWebApplicationContext(){
  5. return super.getWebApplicationContext();
  6. }
  7. }


繼承自抽象類WebApplicationObjectSupport
說明:
抽象類WebApplicationObjectSupport 繼承自ApplicationObjectSupport提供getApplicationContext()方法,可以方便的獲取到ApplicationContext。Spring初始化時,會通過該ApplicationObjectSupport 的setApplicationContext(ApplicationContext context)方法將ApplicationContext 對象註入。當然直接繼承ApplicationObjectSupport自己實現也可以,既然spring 提供了更方便的抽象工具類WebApplicationObjectSupport 建議使用它。以免出現問題

下面看WebApplicationObjectSupport關鍵源碼(紅色部分)

  1. /*** Eclipse Class Decompiler, copyright (c) 2012 cnfree ([email protected]) ***/
  2. package org.springframework.web.context.support;
  3. import java.io.File;
  4. import javax.servlet.ServletContext;
  5. import org.springframework.context.ApplicationContext;
  6. import org.springframework.context.support.ApplicationObjectSupport;
  7. import org.springframework.web.context.ServletContextAware;
  8. import org.springframework.web.context.WebApplicationContext;
  9. import org.springframework.web.util.WebUtils;
  10. public abstract class WebApplicationObjectSupport <span style="color:#FF0000;">extends ApplicationObjectSupport</span> implements ServletContextAware{
  11. private ServletContext servletContext;
  12. public final void setServletContext(ServletContext servletContext){
  13. if (servletContext != this.servletContext){
  14. this.servletContext = servletContext;
  15. if (servletContext != null) initServletContext(servletContext);
  16. }
  17. }
  18. protected boolean isContextRequired(){
  19. return true;
  20. }
  21. protected void initApplicationContext(ApplicationContext context){
  22. super.initApplicationContext(context);
  23. if ((this.servletContext == null)
  24. && (context instanceof WebApplicationContext)){
  25. this.servletContext = ((WebApplicationContext)context)
  26. .getServletContext();
  27. if (this.servletContext != null)
  28. initServletContext(this.servletContext);
  29. }
  30. }
  31. protected void initServletContext(ServletContext servletContext){}
  32. <span style="color:#FF0000;">protected final WebApplicationContext getWebApplicationContext()
  33. throws IllegalStateException{
  34. ApplicationContext ctx = getApplicationContext();
  35. if (ctx instanceof WebApplicationContext){ return ((WebApplicationContext)getApplicationContext()); }
  36. if (isContextRequired()){ throw new IllegalStateException(
  37. "WebApplicationObjectSupport instance [" + this
  38. + "] does not run in a WebApplicationContext but in: "
  39. + ctx); }
  40. return null;
  41. }</span>
  42. protected final ServletContext getServletContext()
  43. throws IllegalStateException{
  44. if (this.servletContext != null){ return this.servletContext; }
  45. ServletContext servletContext = getWebApplicationContext()
  46. .getServletContext();
  47. if ((servletContext == null) && (isContextRequired())){ throw new IllegalStateException(
  48. "WebApplicationObjectSupport instance ["
  49. + this
  50. + "] does not run within a ServletContext. Make sure the object is fully configured!"); }
  51. return servletContext;
  52. }
  53. protected final File getTempDir() throws IllegalStateException{
  54. return WebUtils.getTempDir(getServletContext());
  55. }
  56. }

下面是ApplicationObjectSupport源碼

  1. /*** Eclipse Class Decompiler, copyright (c) 2012 cnfree ([email protected]) ***/
  2. package org.springframework.context.support;
  3. import org.apache.commons.logging.Log;
  4. import org.apache.commons.logging.LogFactory;
  5. import org.springframework.beans.BeansException;
  6. import org.springframework.context.ApplicationContext;
  7. import org.springframework.context.ApplicationContextAware;
  8. import org.springframework.context.ApplicationContextException;
  9. public abstract class ApplicationObjectSupport implements
  10. ApplicationContextAware{
  11. protected final Log logger;
  12. private ApplicationContext applicationContext;
  13. private MessageSourceAccessor messageSourceAccessor;
  14. public ApplicationObjectSupport(){
  15. this.logger = LogFactory.getLog(super.getClass());
  16. }
  17. public final void setApplicationContext(ApplicationContext context)
  18. throws BeansException{
  19. if ((context == null) && (!(isContextRequired()))){
  20. this.applicationContext = null;
  21. this.messageSourceAccessor = null;
  22. }
  23. else if (this.applicationContext == null){
  24. if (!(requiredContextClass().isInstance(context))){ throw new ApplicationContextException(
  25. "Invalid application context: needs to be of type ["
  26. + requiredContextClass().getName() + "]"); }
  27. this.applicationContext = context;
  28. this.messageSourceAccessor = new MessageSourceAccessor(context);
  29. initApplicationContext(context);
  30. }
  31. else if (this.applicationContext != context){ throw new ApplicationContextException(
  32. "Cannot reinitialize with different application context: current one is ["
  33. + this.applicationContext + "], passed-in one is ["
  34. + context + "]"); }
  35. }
  36. protected boolean isContextRequired(){
  37. return false;
  38. }
  39. protected Class requiredContextClass(){
  40. return ApplicationContext.class;
  41. }
  42. protected void initApplicationContext(ApplicationContext context)
  43. throws BeansException{
  44. initApplicationContext();
  45. }
  46. protected void initApplicationContext() throws BeansException{}
  47. public final ApplicationContext getApplicationContext()
  48. throws IllegalStateException{
  49. if ((this.applicationContext == null) && (isContextRequired())){ throw new IllegalStateException(
  50. "ApplicationObjectSupport instance [" + this
  51. + "] does not run in an ApplicationContext"); }
  52. return this.applicationContext;
  53. }
  54. protected final MessageSourceAccessor getMessageSourceAccessor()
  55. throws IllegalStateException{
  56. if ((this.messageSourceAccessor == null) && (isContextRequired())){ throw new IllegalStateException(
  57. "ApplicationObjectSupport instance [" + this
  58. + "] does not run in an ApplicationContext"); }
  59. return this.messageSourceAccessor;
  60. }
  61. }

通過源碼很容易看得出spring做的這兩次封裝是如何獲取到WebApplicationContext的 當然自己也可以實現底層接口自己封裝。

比如:繼承自抽象類ApplicationObjectSupport,抽象類ApplicationObjectSupport提供getApplicationContext()方法,可以方便的獲取到ApplicationContext。Spring初始化時,會通過該抽象類的setApplicationContext(ApplicationContext context)方法將ApplicationContext 對象註入。

再比如:實現接口ApplicationContextAware,實現該接口的setApplicationContext(ApplicationContext context)方法,並保存ApplicationContext 對象。Spring初始化時,會通過該方法將ApplicationContext 對象註入。

以上方法適合不同的情況,請根據具體情況選用相應的方法。
這裏值得提一點的是,系統中用到上述方法的類實際上就於Spring框架緊密耦合在一起了,因為這些類是知道它們是運行在Spring框架上的,因此,系統中,應該盡量的減少這類應用,使系統盡可能的獨立於當前運行環境,盡量通過DI的方式獲取需要的服務提供者。


PS:除了通過applicationContext來手動獲取getBean("beanId")之外,還可以通過beanfactory工廠的.getBean("beanId")獲取Bean 實例

例如:

  1. ResourcePatternResolver resolver=new PathMatchingResourcePatternResolver();
  2. Resource resource=resolver.getResource("classpath:com/**/beans.xml");
  3. BeanFactory bf=new XmlBeanFactory(resource);
  4. bf.getBean("beanId");

有待研究 通過BeanFactory.getBean和ApplicationContext.getBean 的異同解釋,和利弊以及使用情況。誌同道合的同誌可隨時留言討論,小弟歡迎大家一起學習

本文屬於原創,請勿抄襲,謝謝!


關於spring獲取webApplication.getBean多種途徑和簡單解釋