Spring学习之IOC容器BeanFactory和ApplicationContext(三)

来源:互联网 发布:mac口红chili真人试色 编辑:程序博客网 时间:2024/05/22 06:30

Spring 提供了以下两种不同类型的容器,BeanFactory和ApplicationContext。

  • Spring BeanFactory 容器

    这是一个最简单的容器,它主要的功能是为依赖注入 (DI) 提供支持,这个容器接口在 org.springframework.beans.factory.BeanFactor 中被定义。 BeanFactory 和相关的接口,比如,BeanFactoryAware、 DisposableBean、InitializingBean,仍旧保留在 Spring 中,主要目的是向后兼容已经存在的和那些 Spring 整合在一起的第三方框架。

    在 Spring 中,有大量对 BeanFactory 接口的实现。其中,最常被使用的是 XmlBeanFactory 类,但在Spring3.2中已被废弃,建议使用XmlBeanDefinitionReader,DefaultListableBeanFactory替代。

  • BeanFactory的类体系结构

    BeanFactory的类继承体系设计优雅,堪称经典,通过继承体系,我们可以容易了解到BeanFactory具有哪些功能。

    这里写图片描述

    BeanFactory接口位于类结构树的顶端,它最主要的方法就是getBean(String beanName),该方法从容器中返回特定名称的Bean。BeanFactory的功能通过其他接口得到不断扩展。

    • ListableBeanFactory:该接口定义了访问容器中Bean基本信息的若干方法,如查看Bean的个数、获取某一类型Bean的配置名、查看容器中是否包括某一Bean等。

    • HierarchicalBeanFactory:父子级联IOC容器的接口,子容器可以通过接口方法访问父容器。

    • ConfigurableBeanFactory:这是一个重要的接口,增强了Ioc容器的可定制性,它定义了设置类装载器、属性编辑器、容器初始化后置处理器等方法。

    • AutoWireCapableBeanFactory:定义了将容器中的Bean按某种规则(如按名字匹配、按类型匹配等)进行自动装配的方法。

    • SingletonBeanFactory:定义了允许在运行期间向容器注册单实例Bean的方法。

    • BeanDefinitionRegistry:Spring配置文件中每一个<bean> 节点元素在Spring容器里都通过一个BeanDefinition对象表示,它描述了Bean的配置信息。而BeanDefinition Registry接口提供了向容器手工注册BeanDefinition对象的方法。

  • 初始化BeanFactory

    bean.xml配置文件

    <?xml version="1.0" encoding="UTF-8"?><beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns:p="http://www.springframework.org/schema/p"xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans-3.0.xsd"><bean id="helloWorld" class="com.yf.HelloWorld"    p:message="Hello world!"/></beans>

    HelloWorld类:

    public class HelloWorld {private String message;public void setMessage(String message) {    this.message = message;}public void getMessage() {    System.out.println("Your Message : " + message);}}

    BeanFactoryTest#getBeanTest():

        ResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();    Resource resource = resolver.getResource("classpath:bean.xml");    System.out.println(resource.getURI());    // 在3.2被废弃,不建议使用    // BeanFactory bf = new XmlBeanFactory(resource);    DefaultListableBeanFactory factory = new DefaultListableBeanFactory();    XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(factory);    reader.loadBeanDefinitions(resource);    System.out.println("init BeanFactory");    HelloWorld hello = factory.getBean("helloWorld", HelloWorld.class);    System.out.println("helloWorld bean is ready for use");    hello.getMessage();

    XmlBeanDefinitionReader通过Resource装载Spring配置信息并启动Ioc容器,然后就可以通过BeanFactory#getBean(beanName)方法从Ioc容器中获取Bean。通过BeanFactory启动Ioc容器时,并不会初始化配置文件中定义的Bean,初始化动作发生在第一个调用时,对于实例(singleton)的Bean来说,BeanFactory会缓存Bean实例,所以第二次使用getBean()获取Bean时,将直接从Ioc容器的缓存中获取Bean实例。

    Spring的DefaultSingletonBeanRegistry类中提供了一个用于缓存单实例Bean的缓存器,它是一个用HashMap实现的缓存器,单实例的Bean以beanName为键保存在这个HashMap中。

    值得一提的是,在初始化BeanFactory时,必须为其提供一种日志框架,我们使用Log4J,即在类路径下提供Log4J配置文件,这样启动Spring容器才不会报错。

  • ApplicationContext

    如果说BeanFactory是Spring的“心脏”,那么ApplicationContext就是完整的“身躯”了,ApplicationContext由BeanFactory派生而来,提供了更多面向实际应用的功能,在BeanFactory中,很多功能需要以编程的方式实现,而在ApplicationContext中则可以通过配置的方式实现。

  • ApplicationContext类体系结构

    ApplicationContext主要实现类是 ClassPahXmlApplicationContext FiIeSystemXmlApplicationContext,前者默认从类路径加我配置文件,后者默认从文件系 统中装载配置文件。下面了解一下ApplicationContext的类继承休系,如图所示。

    这里写图片描述

    从图中可以看出,ApplicationContext继承了HierarchicalBeanFactory和 ListableBeanFactory接口,在此基础上,还通过多个其他的接口扩展了BeanFactory的功能。这些接口如下。

    • ApplicationEventPublisher:让容器拥有发布应用上下文事件的功能,包括容器启动事件、关闭事件等。实现了ApplicationListener事件监听接口的Bean可以 接收到容器事件,并对事件进行响应处理。在ApplicationContext抽象实现类 肋AbstractApplicationContext中存在一个ApplicationEventMulticaster,它负责保存所有的监听器,以便在容器产生上下文事件时通知这些事件监听者。

    • MessageSource: 为应用提供i18n国际化消息访问的功能。

    • ResourcePatterResolver:所有ApplicationContext实现类都实现了类似干 PathMatchingResourcePatternResolver的功能,可以通过带前缀的Ant风格的资 源文件路径装载Sping的配置文件。

    • LifeCycle:该接口提供了start()和stop()两个方法,主要用于控制异步处理过程。在具体使用时,该接口同时被ApplicationContext实现及具体Bean实现, ApplicationContext会将start/stop的信息传递给容器中所有实现了该接口的 Bean,以达到管理和控制JMX、任务调度等目的。

    • ConfigurableApplicationContext扩展于ApplicationContext,它新增了两个主要的方法:refresh()和close(),让ApplicationContext具有启动、刷新和关闭上下文的能力。在应用上下文关闭的情况相下调用refresh()即可启动应用上下文,在已经启动的状态下调用refresh()则可清除缓存并重新装载配置信息,而调用close()则可关闭应用上下文。这些接口方法为容器的控制管理带来了便利,但作为开发者,并不需要过多关心这些方法。

  • ApplicationContext初始化

    和BeanFactory初始化相似,ApplicationContext的初始化也很简单,如果配置文件在类路径下,则可优先考虑使用ClassPathXmlApplicationContext实现类

    ApplicationContext ctx = new ClassPathXmlApplicationContext("com/yf/context/beans.xml");

    对于ClassPathXmlApplicationContext来说,”com/yf/context/beans.xml”等同于”classpath:com/yf/context/beans.xml”。
    如果配置文件在文件系统的路径下,则可优先考虑使用FileSystemXmlApplicationContext实现类

    ApplicationContext ctx = new FileSystemXmlApplicationContext("com/yf/context/beans.xml");

    对于FileSystemXmlApplicationContext来说,”com/yf/context/beans.xml”等同于”file:com/yf/context/beans.xml”。
    还可以指定一组配置文件,Spring会自动将多个配置文件在内存“整合”成一个配置文件:

    ApplicationContext ctx = new ClassPathXmlApplicationContext(new String[]{"conf/beans1.xml","conf/beans2.xml"});

    当然,FileSystemXmlApplicationContext和ClassPathXmlApplicationContext都可以显式使用带资源类型前缀的路径,它们的区别在于如果不显式指定资源类型前缀,则分别将路径解析为文件系统路径和类路径。

    在获取ApplicationContext实例后,就可以像BeanFactory一样调用 getBean(beanName)返回Bean了。ApplicationContext的初始化和BeanFactory宥一个重大的区别:BeanFactory 在初始化容器时,并未实例化Bean,直到第一次访问某个Bean时才实例化目标Bean; 而ApplicationContext则在初始化应用上下文吋就实例化所有单实例的Bean。因此ApplicationContext的初始化时间会比BeanFactory稍长一些,不过稍后的调用则没有“第 一次惩罚”的问题。

    Spring支持基于类注解的配置方式,主要功能来自Spring的一个名为JavaConfig的子项目。JavaConfig现已升级为Spring核心框架的一部分。一个标注@Configuration注解的POJO即可提供Spring所需的Bean配置信息。
    实例:
    带注解的JAVA类提供的配置信息

//这是一个配置信息提供类@Configurationpublic class Beans {    // 定义一个Bean    @Bean(name = "helloWorld")    public HelloWorld bulidHello() {        HelloWorld helloWorld = new HelloWorld();        helloWorld.setMessage("hello world");        return helloWorld;    }}

通过带@Configuration的配置类启动容器

public class AnnotationApplicationContextTest {    @Test    public void getBean() {        // 通过一个带@Configuration的POJO装载Bean配置        ApplicationContext context = new AnnotationConfigApplicationContext(Beans.class);        HelloWorld hw = context.getBean("helloWorld", HelloWorld.class);        hw.getMessage();    }}

AnnotationConfigApplicationContext将加载Bean.class中的Bean定义并调用Bean.class中的方法实例化Bean,启动容器并装配Bean。

阅读全文
1 0
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 饿了么商家差评怎么办 淘宝不给补差价怎么办 淘宝顾客给差评怎么办 淘宝买家账号体检违规怎么办 买家淘宝账户体检中心违规怎么办 淘宝卖家电话骚扰该怎么办 手机欠费销户了怎么办 想下载好多个淘宝怎么办 送快递不记得路怎么办 淘宝物流弄丢了怎么办 邮政快递碰上难缠客户怎么办 举证工伤对方不签收怎么办 快递员收件的钱怎么办 锐捷网卡是空的怎么办 mac系统excel太慢怎么办 二手车交易发票丢了怎么办 转转上买二手电脑被骗了怎么办 如果电脑买贵了怎么办 电脑配置低玩lol卡怎么办 电视打开显示无信号怎么办 电脑卡怎么办换个驱动 刚开始开淘宝店没人买怎么办 公司有人带自己电脑办公怎么办 组装电脑连不上网怎么办 显卡玩不起吃鸡怎么办 u盘内存是假的怎么办 新买的电脑应该怎么办 海尔一体机电脑开不开机怎么办 苹果笔记本系统坏了怎么办 苹果笔记本电脑电池坏了怎么办 苹果笔记本电脑屏幕坏了怎么办 平板开关键坏了怎么办 平板电脑电池坏了怎么办 平板电脑充电口坏了怎么办 平板电脑系统坏了怎么办 平板电脑充电器坏了怎么办 平板电脑触摸屏坏了怎么办 平板电脑关不了机怎么办 平板电脑触摸屏没反应怎么办 平板电脑声音太小怎么办 平板电脑频碎了怎么办?