获取spring 的bean 方法总结
获取spring 的bean 方法总结
hello菜bird 发表于2年前
获取spring 的bean 方法总结
  • 发表于 2年前
  • 阅读 8999
  • 收藏 221
  • 点赞 8
  • 评论 16

Spring是一个轻量级的控制反转(IoC)和面向切面(AOP)的容器框架,如何在程序中获取Spring配置的bean呢?

 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。

工厂方式: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的时候进行实例化
   

本文不涉及通过@Resource @Autowired 自动注入,仅仅通过ApplicationContext获取Sping配置文件中的Bean

   要获取XML中配置的Bean,最关键的是获取org.springframework.context.ApplicationContext

 

  第一种获取ApplicationContext的方法:

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.FileSystemXmlApplicationContext;
ApplicationContext applicationContext = new FileSystemXmlApplicationContext("applicationContext.xml");
或者
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
private ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");

   这种方式实例化applicationContext是非常耗时的,这种方式适用于采用Spring框架的独立应用程序,仅仅推荐使用在程序需要通过配置文件手工初始化Spring的情况。
   ApplicationContext的主要实现类是ClassPathXmlApplicationContext和FileSystemXmlApplicationContext,前者默认从类路径加载配置文件,后者默认从文件系统中装载配置文件

例子:

public class BeanManager {
    private static ApplicationContext context = new ClassPathXmlApplicationContext("appcontext.xml") ;

    public static Object getBean(String beanId) {
        return context.getBean(beanId);
    }
}

web.xml中写一个servlet,自动启动,init方法中调用一下BeanManager

  init()  throws ServletException {

       BeanManager bm = new BeanManager();//可选的,为的是在web应用启动的时候就让spring加载bean配置。

    // 否则会在第一次调用BeanManager的时候加载,影响一次速度。

}

  在java代码中使用 BeanManager.getBean(String beanId); 来获得bean实例。

  第二种获取ApplicationContext的方法:通过Spring提供的工具类获取ApplicationContext对象,专为web工程定制的方法,推荐Web项目中使用。例如:

ServletContext servletContext = request.getSession().getServletContext();

ApplicationContext ac1 = WebApplicationContextUtils  .getRequiredWebApplicationContext(ServletContext sc)  

ApplicationContext ac2 = WebApplicationContextUtils  .getWebApplicationContext(ServletContext sc) 

  

ac1.getBean("beanId"); 

ac2.getBean("beanId"); 

   通过javax.servlet.ServletContext 获取到ApplicationContext实例对象,这意味着,必须使用到request、session等等。
   这样,就不能把ApplicationContext对象设置为成员变量。需要在每个具体的方法中通过request、session等获取到ServletContext再获取ApplicationContext实例。
   因此,此方法仅仅推荐使用在可以获取到ServletContext对象的Web项目中,并且不需要将ApplicationContext对象定义为成员变量的情况下。

   注意:当使用WebApplicationContextUtils获取ApplicationContext实例时,需要在web.xml配置文件中添加org.springframework.web.context.ContextLoaderListener监听器,否则获取不到ApplicationContext对象,返回Null。

   配置文件:web.xml

<!--ContextLoaderListener自动注入  applicationContext,通过
WebApplicationContextUtils.getWebApplicationContext(request.getSession().getServletContext())获取 -->
<!--Spring配置文件加载位置 -->
<context-param>
  <param-name>contextConfigLocation</param-name>
 <param-value>/WEB-INF/spring/appContext.xml,/WEB-INF/spring/appInterceptor.xml</param-value>
</context-param>
<listener>
  <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>

 

3. 继承自抽象类ApplicationObjectSupport

抽象类ApplicationObjectSupport提供getApplicationContext()方法,可以方便的获取到ApplicationContext。Spring初始化时,会通过该抽象类的setApplicationContext(ApplicationContext context)方法将ApplicationContext 对象注入。

4. 继承自抽象类WebApplicationObjectSupport

通过继承org.springframework.web.context.support.WebApplicationObjectSupport使用getWebApplicationContext() 获取到org.springframework.web.context.WebApplicationContext
   由于Web应用比一般的应用拥有更多的特性,因此WebApplicationContext扩展了ApplicationContext。WebApplicationContext定义了一个常量ROOT_WEB_APPLICATION_ CONTEXT_ATTRIBUTE,在上下文启动时,WebApplicationContext实例即以此为键放置在ServletContext的属性列表中,因此我们可以直接通过以下语句从Web容器中获取WebApplicationContext:

WebApplicationContext wac = (WebApplicationContext)servletContext.getAttribute(
WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE);
 

5. 实现接口ApplicationContextAware

实现该接口的setApplicationContext(ApplicationContext context)方法,并保存ApplicationContext 对象。Spring初始化时,会通过该方法将ApplicationContext 对象注入。

public class SpringContextUtil implements ApplicationContextAware{//Spring的工具类,用来获得配置文件中的bean

private static ApplicationContext applicationContext = null;

/***
* 当继承了ApplicationContextAware类之后,那么程序在调用
* getBean(String)的时候会自动调用该方法,不用自己操作
*/
public void setApplicationContext(ApplicationContext applicationContext)throws BeansException {
SpringContextUtil.applicationContext = applicationContext;
}
public static ApplicationContext getApplicationContext() {
return applicationContext;
}
public static Object getBean(String name) throws BeansException {
return applicationContext.getBean(name);
}

}

 第三、四、五种方法都需要将类配置在Spring配置文件中:

<!--假定ApplicationContextTool为继承或者实现了第三、四、五种方法的具体实现类-->
<bean class="com.twovv.utils.ApplicationContextTool"></bean>

   否则将获取不到ApplicationContext,返回Null

共有 人打赏支持
粉丝 69
博文 103
码字总数 98010
评论 (16)
微苦微蓝
thanks
改着名儿玩
我去!spring哪里轻了?!!!
1527
spring有几百斤呢
一条大河波浪宽
啊 排版太乱了
景愿
8年前你说Spring是个轻量级的IOC框架我信,现在简直是巨人
Left-Shift
你们不要人云亦云,先吃透了再说轻不轻的话
Left-Shift
你们不要人云亦云,先吃透了再说轻不轻的话
shuaia

引用来自“Left-Shift”的评论

你们不要人云亦云,先吃透了再说轻不轻的话

如果你只用IOC只用IOC只用IOC也没多重。
hello菜bird
总结…不是原创…互相学习…
GITTODO
真的轻?
kut
Spring的确是一相当过瘾的一货。
death_rider
用maven引一个坐标能有多重?
notreami

引用来自“景愿”的评论

8年前你说Spring是个轻量级的IOC框架我信,现在简直是巨人
2天前,你这话我信,周末瞅了瞅EJB,那才是重量,长得高没事,重才是最恐怖的~
LC
前边好多人是不是把spring和springmvc搞混了? 单纯的IOC还不轻?
JSR330本来就是个轻量需求
Nox
轻量级。。。。。。
Wi_Ki
123
×
hello菜bird
如果觉得我的文章对您有用,请随意打赏。您的支持将鼓励我继续创作!
* 金额(元)
¥1 ¥5 ¥10 ¥20 其他金额
打赏人
留言
* 支付类型
微信扫码支付
打赏金额:
已支付成功
打赏金额: