关于初始化Spinrg容器、获取Spring容器实例及根据Spring容器获取Bean

9 篇文章 0 订阅
3 篇文章 0 订阅

上篇文章说到了在tomcat启动后如何进行系统的初始化工作:

想看的可点击—— tomcat启动后进行系统初始化及系统销毁执行业务

关于Spring容器初始化及获取实例,就要用到2个容器了:

一个是ServletContext,一个是WebApplicationContext。

ServletContext是servlet容器。用于获取web.xml中配置的参数,或者其他用户。

WebApplicationContext是spring的核心,是spring中的存放bean的容器。

说到初始化容器及获取实例,就要用到WebApplicationContextUtils这个工具类,

WebApplicationContextUtils是一个抽象类,其提供了一个很便利的方法来获取spring应用的上下文即WebApplicationContext。

其中的静态方法getWebApplicationContext(ServletContext sc),提供一个ServletContext 类型参数即可。

其原理十分简单,在spring容器初始化的方法

org.springframework.web.context.ContextLoader.initWebApplicationContext(ServletContext)

中通过servletContext.setAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE, this.context);已经将WebApplicationContext的实例放入ServletContext 中了。

然后在工具类的

org.springframework.web.context.support.WebApplicationContextUtils.getWebApplicationContext(ServletContext)

中就可以通过传入的ServletContext参数获取到WebApplicationContext实例了。

 

看一下代码

import javax.servlet.ServletContext;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.Assert;
import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.context.support.WebApplicationContextUtils;


/**
 * spring 
 */
public class SpringContext {
	private final static Logger logger = LoggerFactory.getLogger(SpringContext.class);
	private static ServletContext context;
	private static WebApplicationContext appContext;

	/**
	 * 初始化Spring容器(需在web起动时就初始化)
	 * @param sc
	 */
	public synchronized static void initContext(ServletContext sc){
		if(appContext == null){
			context = sc;
			appContext = WebApplicationContextUtils.getWebApplicationContext(sc,"org.springframework.web.servlet.FrameworkServlet.CONTEXT.springServlet");
		}
	}
	
	/**
	 * 返回容器 环境上下文
	 * @return
	 */
	public static ServletContext getContext(){
		return context;
	}
	
	/**
	 * 返回Spring容器 环境上下文
	 * @return
	 */
	public static WebApplicationContext getAppContext(){
		return appContext;
	}
	
	/**
	 * 根据类返回实例.
	 * <BR> 不建议使用。如果当前类有多个实现则无法定位到具体使用哪个实现类
	 * @param name
	 * @return
	 */
	public static <T> T getBean(Class<T> t){
		Assert.notNull(appContext);
		return (T)appContext.getBean(t);
	}
	
	/**
	 * 根据发布名称返回实例.
	 * @param name
	 * @return
	 */
	@SuppressWarnings("unchecked")
	public static <T> T getBean(String name){
		Assert.notNull(name);
		return (T)appContext.getBean(name);
	}
	
	/**
	 * 根据发布名称返回实例.
	 * @param name
	 * @return
	 */
	public static boolean containsBean(String name){
		Assert.notNull(name);
		return appContext.containsBean(name);
	}
	
	/**
	 * 根据类全称返回实例.
	 * @param name
	 * @return
	 */
	@SuppressWarnings("unchecked")
	public static <T> T getBeanByClassName(String name){
		Assert.notNull(name);
		try {
			Class<?> cls=Class.forName(name);
			return (T)appContext.getBean(cls);
		} catch (ClassNotFoundException e) {
			logger.error("根据类全称返回实例失败,找不到类:"+name,e);
			return null;
		}
		
	}
}

 

这里呢,我们不光获取了Spring容器的实例,还对该实例进行了一下方法扩展,因为Bean在Spring的管理下都是单例的,所以最好的办法就是用这些方法去Spring容器中获取Bean,

然后就用到了上篇文章的初始化方法了,  在初始化方法中执行initContext就行了,该方法加synchronized关键字是防止初始化多次

import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
 
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
 
/**
 * 所有初始化工作
 * @author Run the ant
 * @date 2018-08-17
 * @version 1.0
 */
public class InitServlet extends HttpServlet {
	private static final long serialVersionUID = 3117103275293498582L;
	private Logger logger = LoggerFactory.getLogger(InitServlet.class);
	
	public void init(ServletConfig config) throws ServletException {
		logger.info("InitServlet init start");
		long start = System.currentTimeMillis();
		
        //初始化SpringContext容器
		SpringContext.initContext(config.getServletContext());
        
        //下面这行不要忘了,执行这行才能生效!!!
		super.init(config);
		logger.info("InitServlet init completed in {}ms",(System.currentTimeMillis()-start));
	}
	
	public void destroy() {
		logger.info("InitServlet destroy.....");
		
		//在这里进行所有的销毁工作!!!
		super.destroy();
	}
	
}

好啦~~~~

 

其实还可以再改进一下,比如如果需要初始化的内容过多,不方便在该方法写,可以扩展一个类,或者接口等,用工厂模式,至于如何扩展,扩展到什么地步就看你自己啦,

为什么这样说呢,因为

SpringContext.initContext(config.getServletContext());

执行完之后,Spring的容器实例我们获取到了,并且已经有了各种获取Bean的方法了,我们完全可以根据这些方法,来获取某个初始化工厂的实例,然后执行初始化方法

import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
 
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
 
/**
 * 所有初始化工作
 * @author Run the ant
 * @date 2018-08-17
 * @version 1.0
 */
public class InitServlet extends HttpServlet {
	private static final long serialVersionUID = 3117103275293498582L;
	private Logger logger = LoggerFactory.getLogger(InitServlet.class);
    
//下面就是我的初始化工厂,该工厂有2个方法,一个init方法,一个destroy方法,
    private InitConfigFactory configFacroty;
	
	public void init(ServletConfig config) throws ServletException {
		logger.info("InitServlet init start");
		long start = System.currentTimeMillis();
		
        //初始化SpringContext容器
		SpringContext.initContext(config.getServletContext());
        
    //系统初始化,用我们之前初始化Spring容器写的方法获取到实例,执行就行了
		configFacroty = SpringContext.getBean(InitConfigFactory.class);
		configFacroty.init(config);

        //下面这行不要忘了,执行这行才能生效!!!
		super.init(config);
		logger.info("InitServlet init completed in {}ms",(System.currentTimeMillis()-start));
	}
	
	public void destroy() {
		logger.info("InitServlet destroy.....");
		
    //系统销毁,用工厂的销毁方法
		configFacroty.destroy();		

		super.destroy();
	}
	
}

所有的你能想到的扩展,都可以在InitConfigFactory工厂类中做文章了,JAVA的多态,尽情施展吧~~~

 

如果你还是不会扩展,等我下篇博文。。。。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Run_the_ant

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值