关于spring获取webApplication.getBean多种途径和简单解释
ApplicationContext ac1 = new FileSystemXmlApplicationContext("com/spark/system/applicationContext.xml");//如果配置文件放在文件系统的目录下则优先使用该方式
//com/spark/system/applicationContext.xml等价于"file:com/spark/system/applicationContext.xml"
ac1.getBean("beanId");
//ApplicationContext ac2=new ClassPathXmlApplicationContext("com/spark/system/applicationContext.xml");//如果配置文件在类路径下则优先使用该方式
//com/spark/system/applicationContext.xml 等价于"classpath:com/spark/system/applicationContext.xml"
ac2.getBean("beanId");
说明:这种方式适用于采用Spring框架的独立应用程序,需要程序通过配置文件手工初始化Spring的情况。
public void getBean(HttpServletRequest req,HttpSession se)
{
// se.getServletContext() 也可以
WebApplicationContext wac=(WebApplicationContext)req.getServletContext().getAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE);
wac.getBean("");
}
说明:此种方式正是我们下面所提到的WebApplicationContextUtils 工具类中getWebApplicationContext(ServletContext sc) 方法的内部实现,以下方式是通过spring 提供的WebApplicationContextUtils 工具类获取WebApplicationContext
方式一:
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。
方式二:
import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.context.support.WebApplicationObjectSupport;
public class ApplicationContextUtils extends WebApplicationObjectSupport{
public WebApplicationContext isgetWebApplicationContext(){
return super.getWebApplicationContext();
}
}
继承自抽象类WebApplicationObjectSupport
说明:
抽象类WebApplicationObjectSupport 继承自ApplicationObjectSupport提供getApplicationContext()方法,可以方便的获取到ApplicationContext。Spring初始化时,会通过该ApplicationObjectSupport 的setApplicationContext(ApplicationContext context)方法将ApplicationContext 对象注入。当然直接继承ApplicationObjectSupport自己实现也可以,既然spring
提供了更方便的抽象工具类WebApplicationObjectSupport 建议使用它。以免出现问题
下面看WebApplicationObjectSupport关键源码(红色部分)
/*** Eclipse Class Decompiler, copyright (c) 2012 cnfree (cnfree2000@hotmail.com) ***/
package org.springframework.web.context.support;
import java.io.File;
import javax.servlet.ServletContext;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ApplicationObjectSupport;
import org.springframework.web.context.ServletContextAware;
import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.util.WebUtils;
public abstract class WebApplicationObjectSupport <span style="color:#FF0000;">extends ApplicationObjectSupport</span> implements ServletContextAware{
private ServletContext servletContext;
public final void setServletContext(ServletContext servletContext){
if (servletContext != this.servletContext){
this.servletContext = servletContext;
if (servletContext != null) initServletContext(servletContext);
}
}
protected boolean isContextRequired(){
return true;
}
protected void initApplicationContext(ApplicationContext context){
super.initApplicationContext(context);
if ((this.servletContext == null)
&& (context instanceof WebApplicationContext)){
this.servletContext = ((WebApplicationContext)context)
.getServletContext();
if (this.servletContext != null)
initServletContext(this.servletContext);
}
}
protected void initServletContext(ServletContext servletContext){}
<span style="color:#FF0000;">protected final WebApplicationContext getWebApplicationContext()
throws IllegalStateException{
ApplicationContext ctx = getApplicationContext();
if (ctx instanceof WebApplicationContext){ return ((WebApplicationContext)getApplicationContext()); }
if (isContextRequired()){ throw new IllegalStateException(
"WebApplicationObjectSupport instance [" + this
+ "] does not run in a WebApplicationContext but in: "
+ ctx); }
return null;
}</span>
protected final ServletContext getServletContext()
throws IllegalStateException{
if (this.servletContext != null){ return this.servletContext; }
ServletContext servletContext = getWebApplicationContext()
.getServletContext();
if ((servletContext == null) && (isContextRequired())){ throw new IllegalStateException(
"WebApplicationObjectSupport instance ["
+ this
+ "] does not run within a ServletContext. Make sure the object is fully configured!"); }
return servletContext;
}
protected final File getTempDir() throws IllegalStateException{
return WebUtils.getTempDir(getServletContext());
}
}
下面是ApplicationObjectSupport源码
/*** Eclipse Class Decompiler, copyright (c) 2012 cnfree (cnfree2000@hotmail.com) ***/
package org.springframework.context.support;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.ApplicationContextException;
public abstract class ApplicationObjectSupport implements
ApplicationContextAware{
protected final Log logger;
private ApplicationContext applicationContext;
private MessageSourceAccessor messageSourceAccessor;
public ApplicationObjectSupport(){
this.logger = LogFactory.getLog(super.getClass());
}
public final void setApplicationContext(ApplicationContext context)
throws BeansException{
if ((context == null) && (!(isContextRequired()))){
this.applicationContext = null;
this.messageSourceAccessor = null;
}
else if (this.applicationContext == null){
if (!(requiredContextClass().isInstance(context))){ throw new ApplicationContextException(
"Invalid application context: needs to be of type ["
+ requiredContextClass().getName() + "]"); }
this.applicationContext = context;
this.messageSourceAccessor = new MessageSourceAccessor(context);
initApplicationContext(context);
}
else if (this.applicationContext != context){ throw new ApplicationContextException(
"Cannot reinitialize with different application context: current one is ["
+ this.applicationContext + "], passed-in one is ["
+ context + "]"); }
}
protected boolean isContextRequired(){
return false;
}
protected Class requiredContextClass(){
return ApplicationContext.class;
}
protected void initApplicationContext(ApplicationContext context)
throws BeansException{
initApplicationContext();
}
protected void initApplicationContext() throws BeansException{}
public final ApplicationContext getApplicationContext()
throws IllegalStateException{
if ((this.applicationContext == null) && (isContextRequired())){ throw new IllegalStateException(
"ApplicationObjectSupport instance [" + this
+ "] does not run in an ApplicationContext"); }
return this.applicationContext;
}
protected final MessageSourceAccessor getMessageSourceAccessor()
throws IllegalStateException{
if ((this.messageSourceAccessor == null) && (isContextRequired())){ throw new IllegalStateException(
"ApplicationObjectSupport instance [" + this
+ "] does not run in an ApplicationContext"); }
return this.messageSourceAccessor;
}
}
通过源码很容易看得出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 实例
例如:
ResourcePatternResolver resolver=new PathMatchingResourcePatternResolver();
Resource resource=resolver.getResource("classpath:com/**/beans.xml");
BeanFactory bf=new XmlBeanFactory(resource);
bf.getBean("beanId");
有待研究 通过BeanFactory.getBean和ApplicationContext.getBean 的异同解释,和利弊以及使用情况。志同道合的同志可随时留言讨论,小弟欢迎大家一起学习
本文属于原创,请勿抄袭,谢谢!
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步