Spring是一个轻量级的控制反转(IoC)和面向切面(AOP)的容器框架,如何在程序中不经过注解的形式(@Resource、@Autowired)获取Spring配置的bean呢?java
Bean工厂(com.springframework.beans.factory.BeanFactory)是Spring框架最核心的接口,它提供了高级IoC的配置机制。BeanFactory使管理不一样类型的Java对象成为可能,应用上下文(com.springframework.context.ApplicationContext)创建在BeanFactory基础之上,提供了更多面向应用的功能,它提供了国际化支持和框架事件体系,更易于建立实际应用。咱们通常称BeanFactory为IoC容器,而称ApplicationContext为应用上下文。但有时为了行文方便,咱们也将ApplicationContext称为Spring容器。
对于二者的用途,咱们能够进行简单划分:BeanFactory是Spring框架的基础设施,面向Spring自己;ApplicationContext面向使用Spring框架的开发者,几乎全部的应用场合咱们都直接使用ApplicationContext而非底层的BeanFactory。web
工厂方式:spring
Resource resource = new ClassPathResource("applicationContext.xml"); BeanFactory factory = new XmlBeanFactory(resource); factory.getBean(strName);
ApplicationContext的初始化和BeanFactory有一个重大的区别:BeanFactory在初始化容器时,并未实例化Bean,直到第一次访问某个Bean时才实例目标Bean;而ApplicationContext则在初始化应用上下文时就实例化全部单实例的Bean。所以ApplicationContext的初始化时间会比BeanFactory稍长一些缓存
附加信息,简要说明Spring何时实例化bean,首先要分2种状况
第一:若是你使用BeanFactory做为Spring Bean的工厂类,则全部的bean都是在第一次使用该Bean的时候实例化
第二:若是你使用ApplicationContext做为Spring Bean的工厂类,则又分为如下几种状况:
(1):若是bean的scope是singleton的,而且lazy-init为false(默认是false,因此能够不用设置),则 ApplicationContext启动的时候就实例化该Bean,而且将实例化的Bean放在一个map结构的缓存中,下次再使用该Bean的时候, 直接从这个缓存中取
(2):若是bean的scope是singleton的,而且lazy-init为true,则该Bean的实例化是在第一次使用该Bean的时候进行实例化
(3):若是bean的scope是prototype的,则该Bean的实例化是在第一次使用该Bean的时候进行实例化mybatis
要获取XML中配置的Bean,最关键的是获取org.springframework.context.ApplicationContextapp
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml" );
或:框架
ApplicationContext context = new FileSystemXmlApplicationContext("D:/Workspaces/MyEclipse Professional 2014/dubbo-customer/src/main/resources/applicationContext.xml" );
这种方式实例化applicationContext是很是耗时的,这种方式适用于采用Spring框架的独立应用程序,仅仅推荐使用在程序须要经过配置文件手工初始化Spring的状况。
ApplicationContext的主要实现类是ClassPathXmlApplicationContext和FileSystemXmlApplicationContext,前者默认从类路径加载配置文件,后者默认从文件系统中装载配置文件。ide
经过Spring提供的工具类获取ApplicationContext对象,专为web工程定制的方法,推荐Web项目中使用。例如:工具
ServletContext sc = request.getSession().getServletContext(); ApplicationContext ac1 = WebApplicationContextUtils .getRequiredWebApplicationContext(sc) ApplicationContext ac2 = WebApplicationContextUtils .getWebApplicationContext(sc) ac1.getBean("beanId"); ac2.getBean("beanId");
其中,获取ServletContext对象时的request.getSession().getServletContext()能够改为this.getServletContext()。ui
注意:当使用WebApplicationContextUtils获取ApplicationContext实例时,须要在web.xml配置文件中添加org.springframework.web.context.ContextLoaderListener监听器,不然获取不到ApplicationContext对象,返回Null。
web.xml配置:
<listener> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> </listener> <context-param> <param-name>contextConfigLocation</param-name> <param-value>classpath:applicationContext.xml</param-value> </context-param>
说明:抽象类ApplicationObjectSupport提供getApplicationContext()方法,能够方便的获取到ApplicationContext。
Spring初始化时,会经过该抽象类的setApplicationContext(ApplicationContext context)方法将ApplicationContext 对象注入。
经过继承org.springframework.web.context.support.WebApplicationObjectSupport使用getWebApplicationContext() 获取到org.springframework.web.context.WebApplicationContext
因为Web应用比通常的应用拥有更多的特性,所以WebApplicationContext扩展了ApplicationContext。WebApplicationContext定义了一个常量ROOT_WEB_APPLICATION_ CONTEXT_ATTRIBUTE,在上下文启动时,WebApplicationContext实例即以此为键放置在ServletContext的属性列表中,所以咱们能够在java类中直接经过如下语句从Web容器中获取WebApplicationContext:
ServletContext sc = this.getServletContext(); WebApplicationContext wac = (WebApplicationContext)sc.getAttribute( WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE); DemoService demoService = (DemoService)wac.getBean("demoService");
实现该接口的setApplicationContext(ApplicationContext context)方法,并保存ApplicationContext 对象。Spring初始化时,会经过该方法将ApplicationContext 对象注入。
package com.test.smsweb.context; import org.springframework.beans.BeansException; import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContextAware; public class AppContext implements ApplicationContextAware { private static ApplicationContext applicationContext; /** * 当继承了ApplicationContextAware类以后,那么程序在调用 getBean(String)的时候会自动调用该方法,不用本身操做 */ @Override public void setApplicationContext(org.springframework.context.ApplicationContext applicationContext) throws BeansException { this.applicationContext = applicationContext; } public Object getBean(String beanName) { return this.applicationContext.getBean(beanName); } }
须要在配置文件中注入该类的bean
<bean id="appContext" name="appContext" class="com.test.smsweb.context.AppContext"> </bean>
而后在java类中获取spring的bean
AppContext appContext = new AppContext(); UserService userService = (UserService) appContext.getBean("userService"); ------------------ package smsweb; import org.junit.Before; import org.junit.Test; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; import com.test.smsweb.context.AppContext; import com.test.smsweb.services.UserService; public class AppContextTest { @Before public void setUp() { //使用"spring.xml"和"spring-mybatis.xml"这两个配置文件建立Spring上下文 ApplicationContext ac = new ClassPathXmlApplicationContext(new String[]{"applicationContext.xml","spring-mybatis.xml"}); } @Test public void testAppContext() { System.out.println("-------------"); AppContext appContext = new AppContext(); UserService userService = (UserService) appContext.getBean("userService"); System.out.println(userService.getById(1).getUsername()); } }