容器接口
- BeanFactory能做那些事
- ApplicationContext有哪些扩展功能
- 事件解耦
@SpringBootApplication
public class Spring01Application {
public static void main(String[] args) throws Exception {
ConfigurableApplicationContext context = SpringApplication.run(Spring01Application.class, args);
// ----class org.springframework.boot.web.servlet.context.AnnotationConfigServletWebServerApplicationContext
System.out.println("----"+context.getClass());
}
}
打印 context.getClass()
,springBoot的启动程序返回的ConfigurableApplicationContext 的具体实现类是AnnotationConfigServletWebServerApplicationContext
AnnotationConfigServletWebServerApplicationContext又间接继承了GenericApplicationContext
,在这个类里面可以找到beanFactory
作为成员变量出现。
到底什么是BeanFactory
查看springBoot 默认的ConfigurableApplicationContext 类中的BeanFactory
的实际类型
ConfigurableApplicationContext context = SpringApplication.run(Spring01Application.class, args);
// ----class org.springframework.boot.web.servlet.context.AnnotationConfigServletWebServerApplicationContext
System.out.println("----"+context.getClass());
// class org.springframework.beans.factory.support.DefaultListableBeanFactory
System.out.println(context.getBeanFactory().getClass());
实际的结果为DefaultListableBeanFactory
类图
先看DefaultListableBeanFactory的父类DefaultSingletonBeanRegistry,选中,按F4,跳对于源码
有一个私有成员变量singletonObjects
通过反射获取该成员变量
反射获取成员变量步骤
public static void main(String[] args) throws Exception {
ConfigurableApplicationContext context = SpringApplication.run(Spring01Application.class, args);
ConfigurableListableBeanFactory beanFactory = context.getBeanFactory();
Field singletonObjects = DefaultSingletonBeanRegistry.class.getDeclaredField("singletonObjects");
singletonObjects.setAccessible(true);
// 通过反射获取 beanFactory 对象的值
Map<String, Object> map = (Map<String, Object>) singletonObjects.get(beanFactory);
map.forEach((k,v)->{
System.out.println(k+"===="+v);
});
}
ApplicationContext 比 BeaFactory多实现了4个接口
MessageSource
: 国际化功能,支持多种语言ResourcePatternResolver
: 通配符匹配资源路径EnvironmentCapable
: 环境信息,系统环境变量,*.properties
、*.application.yml
等配置文件中的值ApplicationEventPublisher
: 发布事件对象在文件中定义不同的值
hi=hello
hi=こんにちは
hi=你好
ConfigurableApplicationContext context = SpringApplication.run(Spring01Application.class, args);
ConfigurableListableBeanFactory beanFactory = context.getBeanFactory();
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));
**例1.**获取类路径下的messages开头的配置文件
Resource[] resources = context.getResources("classpath:messages*.properties");
for (Resource resource : resources) {
System.out.println(resource);
}
**例2.**获取spring相关jar包中spring.factories配置文件
Resource[] resources = context.getResources("classpath*:META-INF/spring.factories");
for (Resource resource : resources) {
System.out.println(resource);
}
获取系统环境变量中 java_home 和项目的 application.yml 中的server.port属性
System.out.println(context.getEnvironment().getProperty("java_home"));
System.out.println(context.getEnvironment().getProperty("server.port"));
@Component
@Slf4j
public class UserService {
@Autowired
private ApplicationEventPublisher context;
public void register(String username, String password) {
log.info("新用户注册,账号:" + username + ",密码:" + password);
context.publishEvent(new UserRegisteredEvent(this));
}
}
发表事件的来源——继承ApplicationEvent
public class UserRegisteredEvent extends ApplicationEvent {
public UserRegisteredEvent(Object source) {
super(source);
}
}
监听事件——@EventListener
@Component
@Slf4j
public class UserRegisteredListener {
@EventListener
public void userRegist(UserRegisteredEvent event) {
System.out.println("UserRegisteredEvent...");
log.info("{}", event);
}
}