`

Spring学习之一:Ioc容器加单学习+applicationcontext

  
阅读更多
最近工作比较轻松,自主学习的时间很多,对于前段时间在网上学习,没有方向没有目的 感到遗憾不已,总是觉得要学习新的技术,却忘记了之前学习的东西都还没有巩固.还好,现在醒悟不算太晚.要学习的东西真的很多.而现在,终于想开始学习Spring了


Ioc容器学习 + applicationcontext

Ioc 控制反转,也叫依赖注入.先讲下控制反转的意思,控制是指容器控制程序的关系,而不是传统的用代码来控制程序.反转,即这种代码控制程序转移为容器控制程序.
依赖注入:组件之间的依赖关系由容器在运行期间完成,由容器动态的管理组件之间的依赖关系.
传统的方式:需要一个对象就自己 New()一个对象来使用.而现在直接从容器中获取就ok了.
 
Spring 的Ioc容器,其实可以理解我BeanFactory,通过BeanFactory来实例化,配置和管理对象.BeanFactory是一个接口,常见的实现有XmlBeanFactory(使用Xml定义容器中的bean),AbstractBeanFactory,DefaultListableBeanFactory.
另外Resource接口用来抽象bean定义数据,XmlBeanDefinitionReader用于对xml定义bean的文件的解析。
看一下BeanFactory的源码:

    public   interface  BeanFactory {  
     
         //这里是对FactoryBean的转义定义,因为如果使用 bean的名字检索FactoryBean得到的对象是工厂生成的对象,  
         //如果需要得到工厂本身,需要转义         
        String FACTORY_BEAN_PREFIX =  "&" ;  
     
     
         //这里根据bean的名字,在IOC容器中得到bean实 例,这个IOC容器就是一个大的抽象工厂。  
        Object getBean(String name)  throws  BeansException;  
     
         //这里根据bean的名字和Class类型来得到bean实 例,和上面的方法不同在于它会抛出异常:如果根据名字取得的bean实例的Class类型和需要的不同的话。  
        Object getBean(String name, Class requiredType)  throws  BeansException;  
     
         //这里提供对bean的检索,看看是否在IOC容器有这个名 字的bean  
         boolean  containsBean(String name);  
     
         //这里根据bean名字得到bean实例,并同时判断这个 bean是不是单件  
         boolean  isSingleton(String name)  throws  NoSuchBeanDefinitionException;  
     
         //这里对得到bean实例的Class类型  
        Class getType(String name)  throws  NoSuchBeanDefinitionException;  
     
         //这里得到bean的别名,如果根据别名检索,那么其原名也 会被检索出来  
        String[] getAliases(String name);  
     
    } 


接下来简单的给大家看一下Ioc容器的创建过程:

 1. 创建IOC配置文件的抽象资源
   2. 创建一个BeanFactory
   3. 把读取配置信息的BeanDefinitionReader,这里是XmlBeanDefinitionReader配置给BeanFactory
   4. 从定义好的资源位置读入配置信息,具体的解析过程由XmlBeanDefinitionReader来完成,这样完成整个载入bean定义的过程。我们的 IoC容器就建立起来了。在BeanFactory的源代码中我们可以看到.
如下代码:
ClassPathResource res =  new  ClassPathResource( "beans.xml" );  
DefaultListableBeanFactory factory =  new  DefaultListableBeanFactory();  
XmlBeanDefinitionReader reader =  new  XmlBeanDefinitionReader(factory);  
reader.loadBeanDefinitions(res);

applicationcontext
先说几个applicationcontext的几个特点,
1,applicationcontext(Spring的上下文) 是在beanfactory的基础上扩展而来的,除了具备BeanFactory的全部能力,还具有其他的新的功能。
2,applicationcontext扩展了MessageSource
3,applicationcontext 支持ResourceLoader和Resource,可以从不同的地方访问bean资源
4,applicationcontext允许上下文嵌套,通过保持父上下文来维持一个上下文体系,这个体系在我们的web容器分析中可以看到.
BeanFactory 和 ApplicationContext在不同的使用层面上代表了Spring提供Ioc容器服务.
由于applicationcontext比BeanFactory更加好用,用的更多的当然就是它了。
ApplicationContext提供Ioc容器的主要接口,在其体系中有许多的抽象子类。例如常见的:AbstractApplicationContext,FileSystemXmlApplicationContext,ClassPathXmlApplicationContext.

接下来重点说一下web开发中获取Spring的AplicationContext的三种方式:

首先要看一下源码,了解一下ApplicationContext的存储.
web.xml中的配置:
    <listener> 
         <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> 
      </listener> 
配置了监听器ContextLoaderListener,追踪一下ContextLoaderListener

public class ContextLoaderListener implements ServletContextListener { 
 
    private ContextLoader contextLoader; 
 
    /**
     * Initialize the root web application context.
     */ 
    public void contextInitialized(ServletContextEvent event) { 
        this.contextLoader = createContextLoader(); 
        this.contextLoader.
    initWebApplicationContext(event.getServletContext()); 
    }

再看一下: initWebApplicationContext方法,

public WebApplicationContext initWebApplicationContext(ServletContext servletContext) 
            throws IllegalStateException, BeansException { 
 
        //从ServletContext中查找,是否存在以//WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE为Key的值

    if(servletContext.getAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE) != null){ 
        throw new IllegalStateException( 
                "Cannot initialize context because there is already a root application context present - " + 
                "check whether you have multiple ContextLoader* definitions in your web.xml!"); 
    } 
     
             
    try { 
        // Determine parent for root web application context, if any. 
        ApplicationContext parent = loadParentContext(servletContext); 
     
        // it is available on ServletContext shutdown. 
        this.context = createWebApplicationContext(servletContext, parent); 
        //将ApplicationContext放入ServletContext中,其key为//WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE

servletContext.setAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE, this.context);</span></span> 
            //将ApplicationContext放入ContextLoader的全局静态常量Map中,其中key
//为:Thread.currentThread().getContextClassLoader()即当前线程类加载器
        currentContextPerThread.put(Thread.currentThread().getContextClassLoader(), this.context); 
     
        return this.context; 
    } 

上面的代码表明,ContextLoaderListener实现了ServeletContextListenet,在ServletContext初始化的时候,会进行Spring的初始化。同时Spring初始化之后,将ApplicationContext存到在了两个地方,意味着我们有两种方式可以获取ApplicationContext。
第一种:
注意:WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE = WebApplicationContext.class.getName() + ".ROOT";

即为 "org.springframework.web.context.WebApplicationContext.ROOT"
那就可以这样获得ApplicationContext:
request.getSession().getServletContext().getAttribute("org.springframework.web.context.WebApplicationContext.ROOT") ,其实Spring已经给了我们接口,
使用spring的工具类来获取:

ApplicationContext ac1 = WebApplicationContextUtils.getRequiredWebApplicationContext(ServletContext sc);
ApplicationContext ac2 = WebApplicationContextUtils.getWebApplicationContext(ServletContext sc);
ac1.getBean("beanId");
ac2.getBean("beanId");
说明:
这种方式适合于采用Spring框架的B/S系统,通过ServletContext对象获取ApplicationContext对象,然后在通过它获取需要的类实例。


其中 servletContext sc 可以具体 换成 servlet.getServletContext()或者 this.getServletContext() 或者 request.getSession().getServletContext(); 另外,由于spring是注入的对象放在ServletContext中的,所以可以直接在ServletContext取出 WebApplicationContext 对象: WebApplicationContext webApplicationContext = (WebApplicationContext) servletContext.getAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE);


第二种方法:
前面说到Spring初始化的时候,将ApplicationContext还存了一份到ContextLoader的Map里面,然而这个Map是私有的,我们直接拿不到的呢。
当然spring也提供了方法的:
    <span style="color: #000000;">public static</span> WebApplicationContext getCurrentWebApplicationContext() { 
            return (WebApplicationContext) currentContextPerThread.get(Thread.currentThread().getContextClassLoader()); 
        } 

第三种方式:
借用ApplicationContextAware,ApplicationContext的帮助类能够自动装载ApplicationContext,只要你将某个类实现这个接口,并将这个实现类在Spring配置文件中进行配置,Spring会自动帮你进行注

入 ApplicationContext.ApplicationContextAware的代码结构如下:

    public interface ApplicationContextAware { 
         
            void setApplicationContext(ApplicationContext applicationContext) throws BeansException; 
     
    } 



关于spring中的ApplicationContext可在另外一篇博客中看。

分享到:
评论

相关推荐

    Spring的IoC容器(《Spring揭秘》的精选版)

    Spring IoC容器ApplicationContext 5.1 统一资源加载策略 5.2 国际化信息支持 5.3 容器内部事件发布 5.4 多配置模块加载的简化 5.5 小结 Spring IoC容器之扩展篇 6.1 Spring 2.5的基于注解的依赖注入 6.2 Spring ...

    09 Spring IoC容器ApplicationContext如何实现国际化慕课专栏1

    背景国际化是指让产品或是程序在无需做出改变的情况下,就能够适应不同语言和地区的需要, internationalization 单词太长 ,又被简称为 i18n

    Spring总结——Spring容器、Spring中的IoC

    从代码上讲:一个Spring容器就是某个实现了ApplicationContext接口的类的实例。也就是说,从代码层面,Spring容器其实就是一个ApplicationContext(一个实例化对象)。 实例化Spring容器: Spring最基本的接口就是...

    尚硅谷]_佟刚_Spring IOC 容器中 Bean 的生命周期.pdf

    这是为了加载多个配置文件,当然也可以把这些配置文件构造为一个数组(new String[] {“config1.xml”, config2.xml})传给ApplicationContext实现进行加载多个配置文件,那一个更适合由用户决定;这两种方式都是...

    浅析Java的Spring框架中IOC容器容器的应用

    主要介绍了Java的Spring框架中IOC容器容器的应用,包括BeanFactory容器和ApplicationContext容器的介绍,需要的朋友可以参考下

    java8源码-Spring5:Spring5新特性

    Spring提供IOC容器实现的2种方式: BeanFactory:IOC容器基本实现,Spring内部使用接口 加载配置文件时候不会创建对象,获取对象时后才会创建。 ApplicationContext:BeanFactory的子接口,提供更多强大的功能,一般...

    Spring教程  主要内容:介绍Spring的历史,Spring的概论和它的体系结构,重点阐述它在J2EE中扮演的角色。

    Spring的IoC容器 6 用户注册的例子 7 面向接口编程 8 (用户持久化类)重构第一步——面向接口编程 8 重构第二步——工厂(Factory)模式 9 重构第三步——工厂(Factory)模式的改进 10 重构第四步-IoC容器 11 ...

    Spring IoC中的基础知识

    Spring的定义:是一个IoC容器  分为: spring core  spring beans: 组件工厂BeanFactory  spring context: 环境,装配  spring expression 3.Spring 组件的作用域 单例(默认):全局唯一 原型:每次获得...

    spring课堂笔记.docx

    Spring 容器:介绍了 Spring 容器的不同类型,包括 BeanFactory 和 ApplicationContext,以及它们在管理对象生命周期和依赖注入方面的作用。 依赖注入:详细解释了依赖注入的原理和用法,以及如何配置和管理 Bean ...

    学习spring ioc和aop

    spring 核心功能演示项目 1. applicationContext xml方式和注解方式配置 2. pring bean循环依赖。 3. spring bean 启动顺序。 4. BeanDefinition编程式注入到容器。 5. spring aop 打印 6. spring 事务

    spring培训-笔记

    Spring的IoC容器 6 用户注册的例子 7 面向接口编程 8 (用户持久化类)重构第一步——面向接口编程 8 重构第二步——工厂(Factory)模式 9 重构第三步——工厂(Factory)模式的改进 10 重构第四步-IoC容器 ...

    Spring-IOC::label:手写实现了Spring框架的基本功能,存在了注解以及xml配置,并且实现了引用注入等功能,还实现了SpringMVC的简单功能

    我的春天Spring IOC容器简单实现,实现了一些基本的核心功能以及简单的MVC基本框架及映射访问说明文档目前已实现: xml注入注解注入简单MVC功能注入支持递归注入属性注入引用注入(但未解决循环依赖)注解配置单例...

    java查看sun包源码-learning-spring:Spring框架讲解

    在SpringIOC容器读取bean配置创建bean实例之前,必须对它进行实例化。只有在容器实例化后,才可以从IOC容器里获取bean实例并使用 Spring提供了两种类型的IOC容器实现 BeanFactory:IOC容器的基本实现,在调用getBean...

    Spring.html

    Spring IOC 控制反转:把创建对象的权利交给Spring 创建对象 1.无参构造 2.静态工厂 3.实例工厂 管理对象 对象关系DI 构造器注入 set注入 生命周期 scope:prototype/singleton init-...

    spring-learn:Spring轻松学习demo

    1.弹簧IOC容器 1.弹簧注入方式 set方法注入 构造方法注入 2.Bean的装配 1.豆的作用域 单例单例获取 原型每次请求都创建实例 2.豆的生命周期 定义,初始化,使用,销毁 待补充... 3.意识到弹簧-让bean获取spring容器...

    xmljava系统源码-Myioc:这是一个简单的IoC容器实现

    正好IoC容器的实现大量地使用了IoC,反射,设计模式,所以打算自己写一个简单的IoC容器来练习,网上查了一下,发现github上有一个叫 的开源项目,简化了Spring的IoC容器和AOP,API名字都是仿照Spring,所以临摹了一下...

    Spring4 HelloWorld

    Spring4 HelloWorld初学Spring,java bean通过applicationContext.xml配置SpringIoC容器生成。

    海创软件组-Spring 核心之IoC(一)

    Spring IoC容器的两个接口 依赖注入的类型 Bean的配置 …IOC:控制反转依赖注入。它使程序组件或类之间尽量形成一种松耦合的结构,开发者在使用类的实列之前,需要先创建对象的实列。而IoC是将创建实列的任务交给了...

    struts2+spring+hibernate整合示例

    b 在struts.xml中添加action,使用通配符的方式 , 注意这里和单独struts2不同的地方: class属性指向的是bean 的 id ,这里我们配置bean采用spring ioc注解的方式, 所以默认的bean的id 为 类名(首字母小写) ...

Global site tag (gtag.js) - Google Analytics