一.使用ApplicationContext获得Bean
首先新建一个类,该类必须实现ApplicationContextAware接口,改接口有一个方法,public void setApplicationContext(ApplicationContext applicationContext)throws BeansException,也就是说框架会自动调用这个方法返回一个ApplicationContext对象。具体类如下:
package com.bijian.study.test; import org.springframework.beans.BeansException; import org.springframework.beans.factory.NoSuchBeanDefinitionException; import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContextAware; public class SpringContextUtils implements ApplicationContextAware {// Spring的工具类,用来获得配置文件中的bean private static ApplicationContext applicationContext = null; public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { SpringContextUtils.applicationContext = applicationContext; } public static ApplicationContext getApplicationContext() { return applicationContext; } public static Object getBean(String name) throws BeansException { return applicationContext.getBean(name); } public static Object getBean(String name, Class requiredType) throws BeansException { return applicationContext.getBean(name, requiredType); } public static boolean containsBean(String name) { return applicationContext.containsBean(name); } public static boolean isSingleton(String name) throws NoSuchBeanDefinitionException { return applicationContext.isSingleton(name); } public static Class getType(String name) throws NoSuchBeanDefinitionException { return applicationContext.getType(name); } public static String[] getAliases(String name) throws NoSuchBeanDefinitionException { return applicationContext.getAliases(name); } }
该类中有一个getBean(String name)方法,该方法用applicationContext去获得Bean实例,而applicationContext是由系统启动时自动设置的。
注意,需要把该类在applicationContext.xml配置文件中进行注册。
二.通过BeanFactory接口获得Bean
也是新建一个类,不过该类需要实现BeanFactoryAware接口,该接口有一个方法public void setBeanFactory(BeanFactory beanFactory) throws BeansException;该方法是为了设置BeanFactory对象,系统会在启动的时候自动设置BeanFactory。具体代码如下:
package com.bijian.study.test; import org.springframework.beans.BeansException; import org.springframework.beans.factory.BeanFactory; import org.springframework.beans.factory.BeanFactoryAware; public class SpringBeanFactoryUtils implements BeanFactoryAware { private static BeanFactory beanFactory = null; private static SpringBeanFactoryUtils factoryUtils = null; public void setBeanFactory(BeanFactory beanFactory) throws BeansException { SpringBeanFactoryUtils.beanFactory = beanFactory; } public static BeanFactory getBeanFactory() { return beanFactory; } public static SpringBeanFactoryUtils getInstance() { if (factoryUtils == null) { // factoryUtils = // (SpringBeanFactoryUtils)beanFactory.getBean("springBeanFactoryUtils"); factoryUtils = new SpringBeanFactoryUtils(); } return factoryUtils; } public static Object getBean(String name) { return beanFactory.getBean(name); } }
不过应该注意的是,改类中有一个getInstance方法,由于该代码是网上摘抄的,他提供了这么一个方法,目的是利用单例模式获得该类的一个实例,但由于getBean(String name)方法是静态的,所以用不用单例都无关紧要,经过测试,两种方法都行的通。
另外一点就是必须把该类添加到applicationContext.xml的配置文件中
三.在servlet中可以用WebApplicationContext类去获取Bean,具体做法是:
ServletContext context = request.getServletContext(); //ServletContext context = request.getSession().getServletContext(); WebApplicationContext webcontext = (WebApplicationContext)context.getAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE); helloService = (HelloService) webcontext.getBean("helloService"); logger.info(helloService.processService("WebApplicationContext test"));
其中context是servlet的上下文,在servlet中可以通过this.getServletContext()或者request.getSession().getServletContext();获得servletContext。但是一点,spring的配置文件必须在WEB-INF下。WebApplicationContext 有一个方法getBean(String name);其实WebApplicationContext 就是ApplicationContext的另一种形式而已。
另外,在普通的java类中,即不是在servlet中可以用ContextLoader获得。ContextLoader是org.springframework.web.context包当中的一个类。
WebApplicationContext webApplication = ContextLoader.getCurrentWebApplicationContext(); helloService = (HelloService) webApplication.getBean("helloService"); logger.info(helloService.processService("ContextLoader.getCurrentWebApplicationContext() test"));
用这种方法就能获取一个WebApplicationContext 的对象。
最后经过测试,在重复100000次的基础上,第一二中方法只用了16毫秒,而第三种方法消耗了62毫秒,所以推荐使用第一二种方法。
四.非WEB项目
即在java main函数中执行spring的代码,如下有四种方式。
package com.bijian.study.test; import org.springframework.context.ApplicationContext; import org.springframework.context.support.FileSystemXmlApplicationContext; import org.springframework.context.support.GenericXmlApplicationContext; import com.bijian.study.service.HelloService; public class Main { public static void main(String[] args) throws Exception { String[] path1 = {"WebContent/WEB-INF/springMVC-servlet.xml"}; ApplicationContext context1 = new FileSystemXmlApplicationContext(path1); HelloService helloService1 = context1.getBean(HelloService.class); System.out.println(helloService1.processService("bijian")); String path2="WebContent/WEB-INF/springMVC-servlet.xml"; ApplicationContext context2 = new FileSystemXmlApplicationContext(path2); HelloService helloService2 = context2.getBean(HelloService.class); System.out.println(helloService2.processService("bijian")); ApplicationContext context = new FileSystemXmlApplicationContext("/WebContent/WEB-INF/springMVC-servlet.xml"); //HelloService helloService = context.getBean(HelloService.class); HelloService helloService = (HelloService) context.getBean("helloService"); System.out.println(helloService.processService("bijian")); GenericXmlApplicationContext context4 = new GenericXmlApplicationContext(); context4.setValidating(false); context4.load("classpath:springMVC-servlet.xml"); context4.refresh(); HelloService helloService4 = context4.getBean(HelloService.class); System.out.println(helloService4.processService("bijian")); } }
特别说明:context4.load("classpath:springMVC-servlet.xml");方式,需将springMVC-servlet.xml拷贝一份到src目录下,否则执行会报“class path resource [springMVC-servlet.xml] cannot be opened because it does not exist”,如下所示。
附:Web工程中验证的代码
@RequestMapping("/greeting") public ModelAndView greeting(@RequestParam(value = "name", defaultValue = "World") String name, HttpServletRequest request) { Mapmap = new HashMap (); try { //由于浏览器会把中文直接换成ISO-8859-1编码格式,如果用户在地址打入中文,需要进行如下转换处理 String tempName = new String(name.getBytes("ISO-8859-1"), "utf-8"); logger.trace("tempName:" + tempName); logger.info(tempName); String userName = helloService.processService(tempName); map.put("userName", userName); logger.trace("运行结果:" + map); helloService = (HelloService) SpringContextUtils.getBean("helloService"); logger.info(helloService.processService("SpringContextUtils test")); helloService = (HelloService) SpringBeanFactoryUtils.getBean("helloService"); logger.info(helloService.processService("SpringBeanFactoryUtils test")); ServletContext context = request.getServletContext(); //ServletContext context = request.getSession().getServletContext(); WebApplicationContext webcontext = (WebApplicationContext)context.getAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE); helloService = (HelloService) webcontext.getBean("helloService"); logger.info(helloService.processService("WebApplicationContext test")); WebApplicationContext webApplication = ContextLoader.getCurrentWebApplicationContext(); helloService = (HelloService) webApplication.getBean("helloService"); logger.info(helloService.processService("ContextLoader.getCurrentWebApplicationContext() test")); } catch (UnsupportedEncodingException e) { logger.error("HelloController greeting方法发生UnsupportedEncodingException异常:" + e); } catch (Exception e) { logger.error("HelloController greeting方法发生Exception异常:" + e); } return new ModelAndView("/hello", map); }
工程完整代码见附件《SpringMVC.zip》。