zoukankan      html  css  js  c++  java
  • Spring中的容器

    1.Spring容器

    Spring容器最基本的接口就是BeanFactory, 负责配置,创建和管理bean。我们通常不直接使用BeanFactory接口,而是使用其子接口ApplicationContext.

    接口ApplicationContext常用实现类是FileSystemXmlApplicationContext和ClassPathXmlApplicationContext等。后者最常用。

    ApplicationContext的实例就是一个容器,Spring容器的意义在于创建和初始化类对象,管理类的依赖关系。

    2.ApplicationContext的事件机制

    AppicationContext的事件机制是观察者模式的实现,按以下方式可以实现。

    • 首先我们需要自定义一个事件类,此事件类是需要继承ApplicationEvent类
    • 然后我们定义一个监听类,监听类作为一个Spring容器中的bean,同时需要实现ApplicationListner接口
    • 然后我们就可以使用ApplicationContext的实例发布事件,相应监听类的实例(bean)负责监听具体的事件

    下面是一个简单的例子,

     事件类,必须继承ApplicationEvent,是否为Spring容器的bean无所谓,

     1 package spi;
     2 
     3 import org.springframework.context.ApplicationEvent;
     4 
     5 public class EmailEvent extends ApplicationEvent {
     6     private String address;
     7     public String getAddress() {
     8         return address;
     9     }
    10     public void setAddress(String address) {
    11         this.address = address;
    12     }
    13     public String getText() {
    14         return text;
    15     }
    16     public void setText(String text) {
    17         this.text = text;
    18     }
    19     private String text;
    20     public EmailEvent(Object source) {
    21         super(source);
    22     }
    23     public EmailEvent(Object source, String address, String text) {
    24         super(source);
    25         this.address =  address;
    26         this.text = text;
    27     }
    28 }

    监听类,必须作为Spring容器的bean,同时需要实现ApplicationListener接口,重写onApplicationEvent方法

     1 package spi;
     2 
     3 import org.springframework.context.ApplicationEvent;
     4 import org.springframework.context.ApplicationListener;
     5 
     6 public class EmailNotifier implements ApplicationListener {
     7 
     8     @Override
     9     public void onApplicationEvent(ApplicationEvent evt) {
    10         if (evt instanceof EmailEvent) {
    11             EmailEvent emailEvent = (EmailEvent)evt;
    12             System.out.println("邮件地址:"+emailEvent.getAddress());
    13             System.out.println("邮件内容:"+emailEvent.getText());
    14         } else {
    15             System.out.println("其他事件:"+evt);
    16         }
    17     }
    18 
    19 }

    将监听类配置进Spring容器配置文件中,并没有什么特殊之处,

    <bean class="spi.EmailNotifier" />

    下面写一个测试类,

    1     public static void test2() {
    2         ApplicationContext ctx = new ClassPathXmlApplicationContext("beans.xml");
    3         EmailEvent ele = new EmailEvent("test", "test@test.com", "this is a test");
    4         ctx.publishEvent(ele);
    5     }

    执行测试类,发现我们不仅监听到了想要监听的事件EmailEvent,同时还有一个系统事件ContextRefreshedEvent也被监听到了,输出如下,

    1 其他事件:org.springframework.context.event.ContextRefreshedEvent[source=org.springframework.context.support.ClassPathXmlApplicationContext@1873eb2: startup date [Fri Feb 03 01:19:21 CST 2017]; root of context hierarchy]
    2 邮件地址:test@test.com
    3 邮件内容:this is a test

    3.ApplicationContext的国际化支持

    ApplicationContext接口继承了MessageSource接口,因此具有国际化功能。MessageSource接口提供了getMessage(...)方法用来进行字符串转换。

    Spring要实现国际化,需要将MessageSource的实例配置成Spring容器中的bean,在bean的属性(即依赖注入)中配置国际化文件,

     1     <!-- ApplicationContext的实例将会查找是否有messageSource的实例并初始化它 -->
     2     <bean id="messageSource" class="org.springframework.context.support.ResourceBundleMessageSource">
     3         <!-- 这里即依赖注入 -->
     4         <property name="basenames">
     5             <list>
     6             <!-- 在这里添加国际化配置文件 -->
     7                 <value>message</value>
     8             </list>
     9         </property>
    10     </bean>

    为此我们需要创建两份国际化配置文件,第一份为英语,文件名 message_en_US.properties,内容如下,

    1 str1=welcome,{0}
    2 str2=now is : {0}

    第二份为中文,文件名为message.properties,内容如下,

    1 str1=欢迎,{0}
    2 str2=现在时间是:{0}

    由于这个文件包含了非西欧字符,因此我们用java自带的native2ascii进行转换,命令为

    1 cd C:Program Files (x86)Javajdk1.7.0_79in
    2 native2ascii C:PROJECTJavaBasicPROJECT_JavaBasicsrcmessage.properties C:PROJECTJavaBasicPROJECT_JavaBasicsrcmessage_zh_CN.properties

    转换后得到message_zh_CN.properties文件即可。

    接着写一个测试类,

     1     public static void test3() {
     2         ApplicationContext ctx = new ClassPathXmlApplicationContext("beans.xml");
     3         String str1 = ctx.getMessage("str1", new String[]{"孙悟空"}, 
     4                 Locale.getDefault(Locale.Category.FORMAT));
     5         String str2 = ctx.getMessage("str2", new Object[]{new Date()}, 
     6                 Locale.getDefault(Locale.Category.FORMAT));
     7         System.out.println(str1);
     8         System.out.println(str2);
     9         
    10         String str3 = ctx.getMessage("str1", new String[]{"孙悟空"}, 
    11                 Locale.US);
    12         String str4 = ctx.getMessage("str2", new Object[]{new Date()}, 
    13                 Locale.US);
    14         System.out.println(str3);
    15         System.out.println(str4);
    16     }

    我们分别在中文环境和英文环境测试了两个字符串str1和str2,得到结果如下,

    1 欢迎,孙悟空
    2 现在时间是:17-2-3 上午1:31
    3 welcome,孙悟空
    4 now is : 2/3/17 1:31 AM

    上面的文字“孙悟空”因为是直接写在代码里面,不属于properties配置文件的,因此在中英文结果都保留原来的文字。

    4.让Bean获取Spring容器

    如果需要让Bean主动获取它所在的Spring容器的引用,可以让该Bean实现BeanFactoryAware接口,并实现setBeanFactory(BeanFactory beanFactory)方法。

    下面是一个例子,

     1 package spi;
     2 
     3 import java.util.Locale;
     4 
     5 import org.springframework.beans.BeansException;
     6 import org.springframework.context.ApplicationContext;
     7 import org.springframework.context.ApplicationContextAware;
     8 
     9 public class GetContextViaBean implements ApplicationContextAware {
    10     private ApplicationContext ctx;
    11     @Override
    12     public void setApplicationContext(ApplicationContext ctx)
    13             throws BeansException {
    14         this.ctx = ctx;
    15     }
    16     public void SayHi(String name) {
    17         System.out.println(ctx.getMessage("str1", new String[]{name}, Locale.US));
    18     }
    19 
    20 }

    将这个类作为一个普通bean配置进Spring中,

    <bean id="getContextViaBean" class="spi.GetContextViaBean" />

    下面写一个测试类,来实现前面的国际化的功能,

    1     public static void test4() {
    2         ApplicationContext ctx = new ClassPathXmlApplicationContext("beans.xml");
    3         GetContextViaBean bean = ctx.getBean("getContextViaBean", GetContextViaBean.class);
    4         bean.SayHi("孙悟空");
    5     }

    执行结果为,

    1 welcome,孙悟空

    与前面国际化方式相比,其实本质上没有区别,只不过前面的国际化是在测试类中,直接使用ApplicationContext的实例调用MessageSource的getMessage()方法,

    而这里是在Bean中,主动去获取所在容器(ApplicationContext)的引用,并在beanzhong通过ApplicationContext的引用调用了MessageSource的getMessage()方法。

  • 相关阅读:
    隐性改变display类型
    垂直居中-父元素高度确定的多行文本(方法二)
    去掉WIN7 桌面图标的小箭头
    搭建高可用mongodb集群(三)—— 深入副本集内部机制
    搭建高可用mongodb集群(二)—— 副本集
    搭建高可用mongodb集群(一)——配置mongodb
    Linux:Tomcat报错: Error creating bean with name 'mapScheduler' defined in ServletContext resource 的解决方法
    LINUX ORACLE 启动与关闭
    Linux 安装 Oracle 11g R2
    ORACLE 数据库优化原则
  • 原文地址:https://www.cnblogs.com/fysola/p/6361932.html
Copyright © 2011-2022 走看看