概述
BeanFactory:
是Spring里面最低层的接口,提供了最简单的容器的功能,只提供了实例化对象和拿对象的功能。
ApplicationContext:
public interface ApplicationContext extends EnvironmentCapable, ListableBeanFactory, HierarchicalBeanFactory, MessageSource, ApplicationEventPublisher, ResourcePatternResolver
应用上下文,继承BeanFactory接口,所以ApplicationContext包含BeanFactory的所有功能以及更多功能。
- MessageSource:国际化
- ResourceLoader:资源访问
- 载入多个上下文
- ApplicationEvent、ApplicationListener:事件机制(监听器)
- AOP(拦截器)
两者装载bean的区别
- BeanFactory:延迟实例化。BeanFactory在启动的时候不会去实例化Bean,中有从容器中拿Bean的时候才会去实例化。
- 延迟实例化的优点:
- 应用启动的时候占用资源很少;对资源要求较高的应用,比较有优势;
- ApplicationContext:不延迟实例化。ApplicationContext在启动的时候就把所有的Bean全部实例化了。它还可以为Bean配置lazy-init=true来让Bean延迟实例化。
- 不延迟实例化的优点:
- 所有的Bean在启动的时候都加载,系统真正运行时的速度快;
- 在启动的时候所有的Bean都加载了,我们就能在系统启动的时候,尽早的发现系统中的配置问题;
MessageSource:国际化
spring中对国际化支持挺好的,比较简单,只需要按照语言配置几个properties文件;然后注册一个国际化的相关的bean,bean内需指定一下配置文件的位置,基本上就可以了。
spring中国际化是通过MessageSource这个接口来支持的,常见3个实现类:
- ResourceBundleMessageSource:这个是基于Java的ResourceBundle基础类实现,允许仅通过资源名加载国际化资源
- ReloadableResourceBundleMessageSource:这个功能和第一个类的功能类似,多了定时刷新功能,允许在不重启系统的情况下,更新资源的信息
- StaticMessageSource:它允许通过编程的方式提供国际化信息,一会我们可以通过这个来实现db中存储国际化信息的功能。
通常我们在ApplicationContext类型的容器中使用国际化3个步骤:
- 步骤一:创建国际化文件,国际化文件命名格式:名称_语言_地区.properties
- 步骤二:向容器中注册一个MessageSource类型的bean,bean名称必须为:messageSource,指定国际化文件路径
- 步骤三:调用AbstractApplicationContext中的getMessage来获取国际化信息,其内部将交给第二步中注册的messageSource名称的bean进行处理。
ResourceBundleMessageSource
步骤一:创建国际化文件
创建3个文件,文件目录ApplicationContextDemo/
message.properties:
name=您的姓名
personal_introduction=默认个人介绍:{0},{1}
当系统找不到的时候会使用这个默认的。
message_zh_CN.properties:中文【中国】:
name=姓名
personal_introduction=个人介绍:{0},{1},{0}
message_en_GB.properties:英文【英国】:
name=Full name
personal_introduction=personal_introduction:{0},{1},{0}
注册一个MessageSource类型的bean
注意必须是MessageSource类型的,bean名称必须为messageSource。
配置类MainConfig1 :
package ApplicationContextDemo;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.support.ResourceBundleMessageSource;
@Configuration
public class MainConfig1 {
@Bean
public ResourceBundleMessageSource messageSource() {
ResourceBundleMessageSource result = new ResourceBundleMessageSource();
//可以指定国际化化配置文件的位置,格式:路径/文件名称,注意不包含【语言_国家.properties】含这部分
result.setBasenames(new String[]{"ApplicationContextDemo/message"}); //@1
return result;
}
}
@1:这个地方的写法需要注意,可以指定国际化化配置文件的位置,格式:路径/文件名称,注意不包含【语言_国家.properties】含这部分。
容器调用getMessage来获取国际化信息
程序调用MessageSourceTest:
package ApplicationContextDemo;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import java.util.Locale;
public class MessageSourceTest {
public static void main(String[] args) {
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(MainConfig1.class);
//未指定Locale,此时系统会取默认的locale对象,本地默认的值中文【中国】,即:zh_CN
System.out.println(context.getMessage("name", null, null));
System.out.println(context.getMessage("name", null, Locale.CHINA)); //CHINA对应:zh_CN
System.out.println(context.getMessage("name", null, Locale.UK)); //UK对应en_GB
}
System.out.println(context.getMessage("personal_introduction", new String[]{"spring高手", "java高手"}, Locale.CHINA)); //CHINA对应:zh_CN
System.out.println(context.getMessage("personal_introduction", new String[]{"spring", "java"}, Locale.UK)); //UK对应en_GB
}
运行结果:
您的姓名
您的姓名
Full name
默认个人介绍:spring高手,java高手
personal_introduction:spring,java,spring
ReloadableResourceBundleMessageSource
ReloadableResourceBundleMessageSource这个类,功能和上面案例中的ResourceBundleMessageSource类似,不过多了个可以监控国际化资源文件变化的功能,有个方法用来设置缓存时间:
public void setCacheMillis(long cacheMillis)
StaticMessageSource
这个类它允许通过编程的方式提供国际化信息,这个类中有2个方法比较重要:
public void addMessage(String code, Locale locale, String msg);
public void addMessages(Map<String, String> messages, Locale locale);
通过这两个方法来添加国际化配置信息。
详见:https://www.cnblogs.com/konglxblog/p/15488207.html 《spring成神之路第二十六篇:国际化详解》
ResourceLoader:资源访问
这是spring对资源文件(如:properties)进行存取操作的功能。
步骤一:获取spring容器
ApplicationContext acxt =new ClassPathXmlApplicationContext("/applicationContext.xml");
步骤二:访问资源
1.通过虚拟路径来存取。当资源位于CLASSPATH路径下时,可以采用这种方式来存取。
Resource resource = acxt.getResource(“classpath:messages_en_CN.properties”);
2.通过绝对路径存取资源文件。
Resource resource = acxt.getResource(“file:F:/testwork/MySpring/src/messages_en_CN.properties”);
3.相对路径读取资源文件。
Resource resource = acxt.getResource("/messages_en_CN.properties");
Resource常用的方法:
- getFilename():获得文件名称
- contentLength():获得文件大小
- createRelative(path):在资源的相对地址上创建新文件
- exists():是否存在
- getFile():获得Java提供的File 对象
- getInputStream():获得文件的流
其实通过ApplicationContext上下文访问外部配置文件,还可以通过applicationContext.xml中配置<context:property-placeholder location="…" />指定外部属性文件,进而获取参数。详见 《Spring-IOC》-外部属性文件。
spring载入多个上下文
不同项目使用不同分模块策略,spring配置文件分为:
applicationContext.xml(主文件,包括JDBC配置,hibernate.cfg.xml,与所有的Service与DAO基类)
applicationContext-cache.xml(cache策略,包括hibernate的配置)
applicationContext-transaction.xml(事务)
moduleName-Service.xml
moduleName-dao.xml
配置方式
1、加载方式中可以加载多个配置文件,获取到ApplicationContext 对象中
String[] configs = {"applicationContext.xml","user_spring.xml"};
ApplicationContext ctx = new ClassPathXmlApplicationContext(configs);
AbstractDao myUserDAO = (AbstractDao) ctx.getBean("userDao");
2、web.xml文件中引用
web.xml里面可以定义两种参数:
1、application范围内的参数,存放在servletcontext中。中的参数(可以指定多个文件)
2、servlet范围内的参数,只能在servlet的init()方法中取得, 中的参数,在init方法中用this.getInitParameter(“param1”)获取
监听器、拦截器后续文章学习。
参考:https://www.iteye.com/blog/youyu4-2346183