Spring FrameWork Core Tech

The IoC Container 1.15

2019-02-27  本文已影响0人  小鲍比大爷

1.15. Additional Capabilities of the ApplicationContext

ApplicationContext继承了很多接口,所以它还提供以下能力:

1.15.1. Internationalization using MessageSource

ApplicationContext提供了国际化能力:

The ApplicationContext interface extends an interface called MessageSource and, therefore, provides internationalization (“i18n”) functionality

具体国际化介绍可以参考下文:
spring学习4-国际化

MessageSource接口提供以下方法:

Spring ApplicationContext会主动寻找名为MessageSource的bean,如果能找到,就使用这个bean进行国际化;如果找不到,则默认给一个空的DelegatingMessageSource实现。
Spring提供了一些MessageSourcede 的实现,比如ResourceBundleMessageSource。

MessageSource的basename设置方式如下。
xml方式:

<beans>
    <bean id="messageSource"
            class="org.springframework.context.support.ResourceBundleMessageSource">
        <property name="basenames">
            <list>
                <value>format</value>
                <value>exceptions</value>
                <value>windows</value>
            </list>
        </property>
    </bean>
</beans>

注解方式:


@Configuration
@ComponentScan(basePackages = "examples")
public class AppConfig {

    @Bean
    public MessageSource messageSource() {
        ResourceBundleMessageSource resourceBundleMessageSource = new ResourceBundleMessageSource();
        resourceBundleMessageSource.setBasenames("format", "exceptions", "windows");
        return resourceBundleMessageSource;
    }
}

exceptions.properties:

# in exceptions.properties
argument.required=The {0} argument is required.
public class Application {
    public static void main(String[] args) {
        ApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
        System.out.println(((AnnotationConfigApplicationContext) context).getBeanFactory());

        context.getBean("example", Example.class).execute();
    }
}

上述代码的执行结果如下:

The userDao argument is required.

最后,通过按照国际化命名方式配置相应的配置文件,即可实现国际化。

As an alternative to ResourceBundleMessageSource, Spring provides a ReloadableResourceBundleMessageSource class.

1.15.2. Standard and Custom Events

支持事件的发布和订阅,类似观察者模式。有专门发布事件的组件以及接受通知的监听器组成。

Annotation-based Event Listeners
基于注解的实现事件监听实现。
发布事件的组件需要装配ApplicationEventPublisher对象,使用ApplicationEventPublisher对象发布具体事件:

@Data
@Component
public class EmailService {

    private List<String> blackList;
    @Autowired
    private ApplicationEventPublisher publisher;

    public void sendEmail(String address, String content) {
//        if (blackList.contains(address)) {
//            publisher.publishEvent(new BlackListEvent(this, address, content));
//            return;
//        }
        publisher.publishEvent(new BlackListEvent(this, address, content));
        // send email...
    }
}

监听方法直接添加注解@EventListener,事件可以作为参数传入,也可以是无参数的方法:

@Component
public class BlackListNotifier {

    private String notificationAddress;

    public void setNotificationAddress(String notificationAddress) {
        this.notificationAddress = notificationAddress;
    }

    @EventListener
    public void processBlackListEvent(BlackListEvent event) {
        // notify appropriate parties via notificationAddress...
        System.out.println("got BlackListEvent " + event.toString());
    }
}

事件定义,普通对象就可以作为事件对象:

public class BlackListEvent {

    private EmailService emailService;
    private String address;
    private String content;

    public BlackListEvent(EmailService emailService, String address, String content) {
        this.emailService = emailService;
        this.address = address;
        this.content = content;
    }
}

执行如下代码:

    EmailService emailService = context.getBean("emailService", EmailService.class);
    emailService.sendEmail("xi'an", "content");

执行结果,正常监听到事件:

got BlackListEvent examples.BlackListEvent@52e677af

@EventListener可以用来限制监听的事件种类:

@EventListener({ContextStartedEvent.class, ContextRefreshedEvent.class})

@EventListener支持SpEL表达式:

@EventListener(condition = "#blEvent.content == 'my-event'")
public void processBlackListEvent(BlackListEvent blEvent) {
    // notify appropriate parties via notificationAddress...
}

@EventListener支持返回值为通知事件,handleBlackListEvent函数返回后,会通知相关监听器处理ListUpdateEvent事件,这样可以构造类似锁链式的连续通知:

@EventListener
public ListUpdateEvent handleBlackListEvent(BlackListEvent event) {
    // notify appropriate parties via notificationAddress and
    // then publish a ListUpdateEvent...
}

上面的链式通知很明显不能在异步通知中使用:

This feature is not supported for asynchronous listeners.

可以通过返回集合类型发布多个通知:

If you need to publish several events, you can return a Collection of events instead.

Asynchronous Listeners
异步监听器,使用@Async即可实现:

@EventListener
@Async
public void processBlackListEvent(BlackListEvent event) {
    // BlackListEvent is processed in a separate thread
}

使用异步通知需要注意两点:

Ordering Listeners
监听器可以指定监听顺序,通过Order指定:

@EventListener
@Order(42)
public void processBlackListEvent(BlackListEvent event) {
    // notify appropriate parties via notificationAddress...
}

Generic Events
因为Spring支持任意Object的子类作为事件类型,所以该节没有意义,直接略过。

1.15.3. Convenient Access to Low-level Resources

1.15.4. Convenient ApplicationContext Instantiation for Web Applications

1.15.5. Deploying a Spring ApplicationContext as a Java EE RAR File

1.15.3 - 1.15.5中没有具体技术相关讲解,建议看官方文档。

上一篇 下一篇

猜你喜欢

热点阅读