`

Spring基本用法2——使用Spring容器(ApplicationContext)

阅读更多

        前言:Spring有两个核心接口(BeanFactory和ApplicationContext),其中ApplicationContext是BeanFactory的子接口,它们都可以代表Spring容器,而Spring容器就是生成Bean实例的工厂,并管理容器中的Bean。而ApplicationContext作为功能更强大的Spring容器,提供了诸如资源访问(URL和文件)、事件机制、同时加载多个配置文件、国际化支持等扩展功能。因此,本文介绍在项目中常用到的功能模块

本篇文章重点关注以下问题:

  • ApplicationContext的国际化支持
  • ApplicationContext的事件机制
  • 在Bean中获取Spring容器

1. ApplicationContext的国际化支持

       ApplicationContext接口继承了MessageSource接口,因此具备了国际化功能。下面是MessageSource接口中定义的三个用于国际化的方法:

public interface MessageSource {
    /**
     * 尝试解析国际化信息,如果为找到相关国际化配置,则返回默认信息
     * @param code              待国际化信息在配置文件中的关键字
     * @param args              待国际化信息中占位符的值
     * @param defaultMessage    查找国家化配置失败后的默认返回值
     * @param locale            Locale信息
     * @return 
     */
    String getMessage(String code, @Nullable Object[] args, @Nullable String defaultMessage, Locale locale);

    /**
     * 尝试解析国际化信息,如果为找到相关国际化配置,则返回null
     * @param code              待国际化信息在配置文件中的关键字
     * @param args              待国际化信息中占位符的值
     * @param locale            Locale信息
     * @return 
     */
    String getMessage(String code, @Nullable Object[] args, Locale locale) throws NoSuchMessageException;

    /**
     * 以国际化解析器进行国际化
     * @param resolvable        国际化解析接口
     * @param locale            Locale信息
     * @return 
     */
    String getMessage(MessageSourceResolvable resolvable, Locale locale) throws NoSuchMessageException;
}

 

1.1 在Spring中配置MessageSource的Bean:通常使用ResourceBundleMessageSource类

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
                           http://www.springframework.org/schema/beans/spring-beans-4.3.xsd">
                           
    <bean id="messageSource" class="org.springframework.context.support.ResourceBundleMessageSource">
        <!-- 驱动Spring调用messageSource Bean的setBasenames()方法,该方法需要一个数组参数,使用list元素配置多个数组元素 -->
        <property name="basenames">
            <list>
                <value>com/wj/chapter2/applicationContextg/i18/message</value>
                <!-- 如果有多个资源文件,全部列在此处 -->
            </list>
        </property>
    </bean>
</beans>
      上面配置文件中的粗体字只指定了一份国际化资源文件,其baseName是message,然后给出它的两份资源文件:message_en_US.properties、message_zh_CN.properties。
 

1.2 生成资源文件(中式、美式)

      首先是美式资源文件:message_en_US.properties

hello=welcome,{0}
now=now is :{0}
      然后是中式资源文件:message_zh_CN.properties。
hello=欢迎你,{0}
now=现在时间是 :{0}

     

       因为资源文件中含有简体中文,所以需要用native2ascii工具将这份资源文件国际化(native2ascii 源文件 目标文件),得到的文件内容如下:

hello=\u6b22\u8fce\u4f60\uff0c{0}
now=\u73b0\u5728\u65f6\u95f4\u662f\uff1a{0}

      至此,程序就拥有了两份资源文件,可用于自适应美式英语和简体中文环境。

 

1.3 编写国际化功能测试代码

public class I18Main {
    
    // 1.指明xml配置文件位置,便于Spring读取,从而知道Bean的相关信息
    private static final String PATH_XML = "com/wj/chapter2/applicationContextg/i18/applicationContext.xml";
    
    @SuppressWarnings("resource")
    public static void main(String[] args)throws Exception {
        // 2.根据xml配置文件,创建Spring IOC容器的上下文
        ApplicationContext ctx = new ClassPathXmlApplicationContext(PATH_XML);
        // 3.使用getMessage()方法获取本地化消息。(Locale的getDefault方法返回计算机环境的默认Locale)
        String hello = ctx.getMessage("hello" , new String[]{"熊燕子"}, Locale.getDefault(Locale.Category.FORMAT));
        String now   = ctx.getMessage("now" , new Object[]{new Date()}, Locale.getDefault(Locale.Category.FORMAT));
        // 打印出两条本地化消息
        System.out.println(hello);
        System.out.println(now);
    }
}

 

1.4 查看运行结果

 

2. ApplicationContext的事件机制

        ApplicationContext的事件机制是典型的观察者设计模式,通过ApplicationEvent类和ApplicationListener接口,可以实现ApplicationContext的事件处理。如果容器中有一个ApplicationListener的Bean,每当ApplicationContext发布ApplicationEvent时,ApplicationListener的Bean都将自动触发。

       Spring的事件框架有如下两个重要成员:

  • ApplicationEvent:容器事件,必须由ApplicationContext发布。
  • ApplicationListener:监听器,可由容器中的任何监听器Bean担任。(必须实现ApplicationListener接口)
       实际上,Spring事件机制与所有的事件机制相似,都是由事件源、事件和事件监听组成,在Spring事件机制中,事件源是ApplicationContext,事件是ApplicationEvent的实现,监听器是ApplicationListener的实现。

2.1 首先定义一个Spring容器事件

/**
 * 定义容器事件,此事件必须由容器ApplicationContext发布
 * @author Administrator
 */
public class EmailEvent extends ApplicationEvent {
    private static final long serialVersionUID = 1259505481443188920L;
    
    private String address;
    private String text;

    public EmailEvent(Object source) {
        super(source);
    }
    
    // 初始化全部成员变量的构造器
    public EmailEvent(Object source , String address , String text) {
        super(source);
        this.address = address;
        this.text = text;
    }
    
    // setter|getter
    public String getAddress()             { return address;         }
    public String getText()                { return text;            }
    public void setAddress(String address) { this.address = address; }
    public void setText(String text)       { this.text = text;       }
}
        上面的EmailEvent类继承了ApplicationEvent,则该对象就可作为Spring容器的容器事件,便可通过容器发布。

 

2.2 实现容器事件的监听类

       容器事件的监听器必须实现ApplicationListener接口,并实现接口中的唯一方法:

@FunctionalInterface
public interface ApplicationListener<E extends ApplicationEvent> extends EventListener {

	/**
	 * 每当容器内发生任何事件,此方法都会被触发.
	 * @param event the event to respond to
	 */
	void onApplicationEvent(E event);

}

       EmailEvent事件对应的监听器如下:

/**
 * 定义监听器,当事件发生时,通知所有观察者
 */
public class EmaiListener implements ApplicationListener<EmailEvent> {
    
    // 该方法会在容器发生事件时自动触发
    @Override
    public void onApplicationEvent(EmailEvent evt) {
        System.out.println("需要发送邮件的接收地址: " + evt.getAddress());
        System.out.println("需要发送邮件的邮件正文: " +  evt.getText());
    }
}

 

2.3 补充: 定义一个全局的事件监听器

/**
 * 通过此监听器可观察所有在Spring容器中定义的事件(泛型指定顶层接口)
 */
public class AllEventListener implements ApplicationListener<ApplicationEvent> {
    
    // 该方法会在容器发生事件时自动触发
    @Override
    public void onApplicationEvent(ApplicationEvent evt) {
        System.out.println("ApplicationEvent : " + evt);
    }
}

       利用泛型指定顶层ApplicationEvent类,关注所有发生的容器事件。

 

2.4 将监听器配置到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"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
                           http://www.springframework.org/schema/beans/spring-beans-4.3.xsd">
                           
    <!-- 配置监听器(在Spring事件机制中,只需配置监听器即可) -->
    <bean class="com.wj.chapter2.applicationContextg.event.EmaiListener"/>
    <bean class="com.wj.chapter2.applicationContextg.event.AllEventListener"/>
</beans>

     从上面粗体字可看出,为Spring容器注册事件监听器,不需要像Swing编程那样采用代码进行编辑,只需在配置文件中简单说明即可。

 

2.5 通过ApplicationContext容器发布事件

public class EventTest {
    
    private static final String PATH_XML = "com/wj/chapter2/applicationContextg/event/applicationContext.xml";
    
    public static void main(String[] args) {
        /** 1.触发ContextRefreshedEvent事件. */
        ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext(PATH_XML);
        
        // 创建一个ApplicationEvent对象
        EmailEvent emainEvent = new EmailEvent("test", "super_wj@163.com" , "this is a test");
        /** 2.触发EmailEvent事件. */
        ctx.publishEvent(emainEvent);
        
        /** 3.触发ContextClosedEvent事件. */
        ctx.close();
    }
}

       测试代码中会触发三个事件,两个容器自定义事件(ContextRefreshedEvent、ContextClosedEvent),一个用户自定义事件(EmailEvent)事件。

 

2.6 观察测试结果输出

      如上图所示,可检测到三个事件的发布:ContextRefreshedEvent、EmailEvent、ContextClosedEvent。

 

2.7 补充说明Spring提供的内置事件

  1.  ContextRefreshedEvent:ApplicationContext容器初始化或刷新时触发该事件(如上面测试结果)。该事件触发说明ApplicationContext容器已就绪可用。
  2. ContextStartedEvent:当使用ConfigurableApplicationContext接口的start()方法启动ApplicationContext容器时触发该事件。
  3. ContextClosedEvent:当使用ConfigurableApplicationContext接口的close()方法关闭ApplicationContext容器时触发该事件(如上面测试结果)。
  4. ContextStoppedEvent:当使用ConfigurableApplicationContext接口的Stop()方法使ApplicationContext停止时触发该事件。
  5. RequestHandledEvent:Web相关的事件,只能应用于使用DispatcherServlet的Web、应用中,在使用SpringMVC作为前端的MVC控制器时,当Spring处理用户请求结束后,系统会自动触发该事件。
  6. 其他事件:Spring4.0.3后新增用于WebSocket的事件:SessionConnectedEvent、SessionConnectEvent、SessionDisconnectEvent

 3. 让Bean获取Spring容器

       前面的实例中,都是由程序显示的创建Spring容器,在这种访问模式下,程序中总是持有Spring容器的引用。但在Web应用中,Spring容器通常采用在web.xml中声明式方式配置产生,程序Bean处于容器管理之下,Bean无需主动访问容器。但是当需要借助Spring容器实现特定功能(如上述国际化、事件机制)时,就必须让Bean先获取Spring容器,然后借助Spring容器实现该功能。

       先设定需求:Person类sayHi(String name)方法必须能输出国际化消息,由于国际化功能需要借助于Spring容器实现,因此必须让Person获取到Spring容器对象,以便其拥有国际化的能力。

 

3.1 Person类实现ApplicationContextAware接口,并提供相应的setter方法

        为了让一个Bean获取它所在的Spring容器,可以让该Bean实现ApplicationContextAware接口,并复写接口里的唯一方法:

void setApplicationContext(ApplicationContext applicationContext) throws BeansException;

        这个方法将有Spring在创建该Bean对象时调用,以便在Spring容器调用该方法时,将容器自身作为参数传入该方法。

/**
 * 通过继承ApplicationContextAware接口,获取Application容器,从而调用国际化案例
 */
public class Person implements ApplicationContextAware {
    
    // 将BeanFactory容器以成员变量保存
    private ApplicationContext ctx;

    /**
     *  Spring容器会检测容器中所有Bean,如果发现某个Bean实现了
     *  ApplicationContextAware接口,Spring容器会在创建该Bean之后,
     *  Spring自动调用该Bean的setApplicationContext()方法,调用该方法时,
     *  Application会将容器本身作为参数传给该方法。
     */
    public void setApplicationContext(ApplicationContext ctx) throws BeansException {
        this.ctx = ctx;
    }
    
    public void sayHi(String name) {
        System.out.println(ctx.getMessage("hello" , new String[]{name}, Locale.getDefault(Locale.Category.FORMAT)));
    }
}

 

3.2 配置Spring配置文件

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
                           http://www.springframework.org/schema/beans/spring-beans-4.3.xsd">

    <!-- 加载容器国际化所需要的语言资源文件 -->
    <bean id="messageSource" class="org.springframework.context.support.ResourceBundleMessageSource">
        <property name="basenames">
            <list>
                <value>com/wj/chapter2/applicationContextg/i18/message</value>
            </list>
        </property>
    </bean>
    
    <!-- Spring容器会检测容器中所有Bean,如果发现某个Bean实现了
         ApplicationContextAware接口,Spring容器会在创建该Bean之后,
         Spring自动调用该Bean的setApplicationContext()方法,调用该方法时,
         Application会将容器本身作为参数传给该方法。-->
    <bean id="person" class="com.wj.chapter2.applicationContextg.ApplicationContextAware.Person"/>
</beans>

       由配置文件可以看出,配置Person对象Bean时,与配置其他Bean并没有区别。

 

3.3 编写测试程序

public class Main {
    
    // 1.指明xml配置文件位置,便于Spring读取,从而知道Bean的相关信息
    private static final String PATH_XML = "com/wj/chapter2/applicationContextg/ApplicationContextAware/applicationContext.xml";

    @SuppressWarnings("resource")
    public static void main(String[] args) {
        // 2.根据xml配置文件,创建Spring IOC容器的上下文
        ApplicationContext ctx = new ClassPathXmlApplicationContext(PATH_XML);
        
        // 3.获取Person对象,调用国际化功能
        ctx.getBean("person" , Person.class).sayHi("熊燕子");
    }

}

 

3.4 查看测试结果

      可以看出,的确安装资源文件的格式输出,说明Person类拿到ApplicationContext容器后具有了国际化能力。
 

 

代码下载地址:http://pan.baidu.com/s/1skOq7El,密码:qpi5

  • 大小: 10.1 KB
  • 大小: 23.8 KB
  • 大小: 22.7 KB
  • 大小: 10.8 KB
分享到:
评论

相关推荐

    三、Spring源码分析——ApplicationContext

    总的来说,ApplicationContext作为Spring的核心组件,扮演着应用程序的“大脑”角色,它负责管理和协调整个Spring容器中的Bean。理解并掌握ApplicationContext的工作原理和使用技巧,对于深度开发和优化Spring应用至...

    spring學習筆記——Helloworld

    在本篇“Spring学习笔记——HelloWorld”中...通过这个HelloWorld示例,我们学习了Spring的基本用法,但这只是开始,更多的知识等待我们去探索。在实际项目中,Spring可以帮助我们处理复杂的企业级问题,提升开发效率。

    二、Spring源码分析——BeanFactory

    《Spring源码分析——BeanFactory》 在Java的IoC(Inversion of Control)和DI(Dependency Injection)领域,Spring框架扮演着至关重要的角色。BeanFactory是Spring的核心组件之一,它是容器的基石,负责管理应用...

    小读spring ioc源码(一)——整体介绍

    《Spring IOC源码解析(一)——整体介绍》 在深入理解Spring框架的过程中,源码分析是不可或缺的一环。本文将对Spring的IOC(Inversion of Control,控制反转)容器的源码进行初步探讨,旨在帮助读者从整体上把握...

    Spring——jar包详解

    了解了Spring的基本模块后,我们来看看如何在实际项目中使用jar包。通常,我们需要在项目的类路径下包含相应的Spring库,例如`spring-context.jar`、`spring-webmvc.jar`等。在现代开发环境中,这通常通过Maven或...

    Spring源码解析.zip

    本压缩包“Spring源码解析”提供了对Spring框架核心组件——IOC(Inversion of Control,控制反转)、AOP(Aspect Oriented Programming,面向切面编程)以及Transaction(事务管理)的源码分析,帮助开发者更全面地...

    Spring3.1.3 Ioc在Web容器中的建立

    综上所述,"Spring3.1.3 Ioc在Web容器中的建立"涵盖了Spring的核心特性之一——IoC,以及在Web环境下的具体配置和使用方法。这个过程涉及到Spring容器的初始化、bean的定义与依赖注入,以及Web应用的结构配置。通过...

    tiny-spring-step-6-invite-application-context.zip

    它将对象的创建和管理从应用代码中分离出来,交由Spring容器负责。这样,开发者只需要定义对象之间的依赖关系,而无需关注如何实例化和组装这些对象。Spring通过XML配置、注解或Java配置三种方式来实现IoC,使得代码...

    Spring基础:IoC容器(2)

    为了使Spring容器管理我们的对象,我们需要对这些对象进行“bean化”。这意味着我们需要定义bean的配置元数据,这可以通过XML、Java注解或基于Java的配置来完成。在XML配置中,我们定义bean的类名、属性、依赖关系等...

    Spring2.5.6源代码分析(一):IOC容器

    在本篇中,我们将深入探讨Spring框架的核心组件——IoC(Inversion of Control)容器,这是Spring 2.5.6版本的一部分。IoC容器是Spring框架的心脏,它负责管理对象的生命周期和依赖关系,使得开发者能够实现松耦合和...

    征服Spring AOP—— @AspectJ

    本篇文章将深入探讨@AspectJ的使用方法和背后的原理。 首先,我们需要理解面向切面编程(AOP)的基本概念。AOP是一种编程范式,它允许开发者将关注点(如日志、事务处理)与业务逻辑分离,从而提高代码的可读性和可...

    spring3.0_doc_api

    5. **ApplicationContext**:高级的bean工厂,除了基本的bean管理功能外,还提供了消息源、国际化、事件传播等功能。 **Spring 3.0新特性** 1. **JSR-330注解支持**:引入了JSR-330规范的注解,如`@Inject`和`@...

    Spring.3.x企业应用开发实战(完整版).part2

    《Spring3.x企业应用开发实战》是在《精通Spring2.x——企业应用开发详解》的基础上,经过历时一年的重大调整改版而成的,本书延续了上一版本追求深度,注重原理,不停留在技术表面的写作风格,力求使读者在熟练使用...

    Spring练习

    4. 获取bean:通过Spring容器的`getBean`方法获取需要的bean实例,然后就可以在代码中使用了。 然而,现代Spring应用更多地使用注解驱动的配置。比如,可以使用`@Component`、`@Service`、`@Repository`和`@...

    Spring_2.0_Samples

    Spring提供了两种主要的IoC容器:BeanFactory和ApplicationContext。在Spring 2.0中,ApplicationContext是更为推荐的选择,它提供了更多的企业级服务,如消息源和AOP代理。 AOP(Aspect-Oriented Programming,...

    springDemo初学入门

    在Spring项目中,配置文件通常为XML格式(如`applicationContext.xml`或`beans.xml`),它定义了Spring容器如何创建、配置和组装对象。配置文件可能包含了bean的定义,包括它们的类名、属性以及依赖关系。此外,...

    Spring学习笔记,精华摘要

    bean的管理者——Spring容器,有两个主要接口:BeanFactory和ApplicationContext。BeanFactory是最基础的接口,负责bean的配置、创建和管理,而ApplicationContext提供了更多的企业级服务,如国际化、事件发布等。...

    Spring依赖注入使用构造设注入demo

    本篇将详细讲解如何使用构造器注入作为Spring依赖注入的一种方式,并通过一个完整的可运行示例——"SpringIOCTest2"来加深理解。 首先,理解依赖注入的概念。依赖注入允许我们不在类内部创建对象,而是通过外部源...

    Spring快速入门教程

    本快速入门教程将带你深入理解Spring的核心概念和基本用法。 1. **Spring框架概述** Spring框架是由Rod Johnson发起的,它是一个全面的后端开发解决方案,提供了众多模块,包括核心容器、数据访问/集成、Web、AOP...

    Spring完整Jar包

    通过DI,Spring容器负责管理对象的生命周期和相互关系,使得代码更易于测试和维护。 2. **面向切面编程(Aspect-Oriented Programming, AOP)**: Spring的AOP模块允许开发者定义“切面”,这些切面可以封装跨越多...

Global site tag (gtag.js) - Google Analytics