ConfigurableApplicationContext
在我们使用SpringBoot项目的时候会发现启动类是这一串代码:
@SpringBootApplication
public class AppSpringBootApplication {
public static void main(String[] args) {
SpringApplication.run(AppSpringBootApplication.class, args);
}
}
那么这串代码是有什么作用呢?
ConfigurableApplicationContext context =
SpringApplication.run(A01Application.class, args);
我们将代码这个方法返回接收,本文主要讲解ConfigurableApplicationContext的主要作用:
在IDEA中点击此类 摁Ctrl+Alt+U可以看到ConfigurableApplicationContext的类图如下:
常见面试题:ApplicationContext与BeanFactory的关系?
在类图中我们可以看到ApplicationContext是BeanFactory的实现,集成了BeanFactory的功能。
那么BeanFactory是做什么的?
BeanFactory表面上只有getBean,但是实际上控制反转、基本的依赖注入、直至Bean的生命周期的各种功能都有它的实现类提供。
ApplicationContext 比 BeanFactory 多了什么?
我们从类图中可以看到ApplicationContext 多了几个实现,下文主要讲解各个实现的主要作用:
MessageSource: 国际化功能,支持多种语言。
ResourcePatternResolver: 通配符匹配资源路径。
EnvironmentCapable: 环境信息,系统环境变量,*.properties、*.application.yml等配置文件中的值。
ApplicationEventPublisher: 发布事件对象。
1.BeanFactory
我们可以通过BeanFactory拿到所有的Bean信息
Class<DefaultSingletonBeanRegistry> clazz = DefaultSingletonBeanRegistry.class;
Field singletonObjects = (Field) clazz.getDeclaredField("singletonObjects");
// 设置私有变量可以被访问
singletonObjects.setAccessible(true);
ConfigurableListableBeanFactory beanFactory = context.getBeanFactory();
//获取Bean集合
Map<String, Object> map = (Map<String, Object>) singletonObjects.get(beanFactory)
//遍历集合内所有的Bean
map.forEach((key, value) -> {
System.out.println("key ==>> " + key);
System.out.println("value ==>> " + value);
});
2.MessageSource接口
主要用于国际化功能呢,可以将语言进行翻译比如
我们在资源包中添加了翻译的内容
messages_en.properties 英语翻译
hi=hello
messages_ja.properties 日语翻译
hi=こんにちは
messages_zh.properties 中文翻译
hi=你好
我们可以通过context.getMessage()找到匹配的对应信息,翻译出我们想要的内容
System.out.println(context.getMessage("hi", null, Locale.CHINA));
System.out.println(context.getMessage("hi", null, Locale.ENGLISH));
System.out.println(context.getMessage("hi", null, Locale.JAPANESE));
3.ResourcePatternResolver接口
ResourcePatternResolver接口可以获取到文件名
//获取文件名数组
Resource[] resources = context.getResources("classpath:messages*.properties");
//遍历数组
for (Resource resource : resources) {
System.out.println(resource);
}
4.EnvironmentCapable接口
EnvironmentCapable可以获取到application.yml文件中信息,可以一获取系统环境信息例如:java_home
System.out.println(context.getEnvironment().getProperty("java_home"));
System.out.println(context.getEnvironment().getProperty("server.port"));
5.ApplicationEventPublisher
ApplicationEventPublisher完成事件注册发现功能
简单实现注册返现demo代码如下
UserService类
@Component
@Slf4j
public class UserService {
private final ApplicationEventPublisher context;
public UserService(ApplicationEventPublisher context) {
this.context = context;
}
public void register(String username, String password) {
log.debug("新用户注册,账号:" + username + ",密码:" + password);
context.publishEvent(new UserRegisteredEvent(this));
}
}
UserRegisteredEvent事件注册
public class UserRegisteredEvent extends ApplicationEvent {
public UserRegisteredEvent(Object source) {
super(source);
}
}
UserRegisteredListener事件监听
事件监听可以对UserRegisteredEvent中注册的事件进行监听,然后进行相应处理:
比如可以用户注册,发送短信方法;
用户一旦注册被监听到,就对该用户手机号码发送短信;
@Component
@Slf4j
public class UserRegisteredListener {
@EventListener
public void userRegister(UserRegisteredEvent event) {
System.out.println("UserRegisteredEvent...");
log.debug("{}", event);
}
}
测试代码:
//获取Bean对象
UserService userService = context.getBean(UserService.class);
//执行注册方法
userService.register("张三", "123456");
结果显示:
我们可以观察到监听器中的方法执行了。
总结:
通过本文我们可以了解到
BeanFactory 与 ApplicationContext 不不仅仅是简单接口继承的关系。
ApplicationContext 组合并扩展了 BeanFactory的功能。
ApplicationContext 增加了的各个功能和主要作用。
希望各位看到的读者觉得内容对自己有帮助点个赞,希望看到后续收藏加关注,读者的鼓励就是我的动力,谢谢大家!