一.ApplicationContext和BeanFactory
1. ApplicationContext是BeanFactory的子接口,
实现了BeanFactory的一些方法,例如getBean()
ConfigureableApplicationContext继承了ApplicationContext
2.BeanFactory的功能
1.BeanFactory才是Bean的核心容器
2.ApplicationContext是BeanFactory的组合
BeanFactory的功能很少,他的一个主要实现类DefaultListenableBeanFactory实现了大量方法
可以看到这里有很多实现类和接口,他们实现了大量的Spring容器中的方法
我们主要看一下DefaultSingletonBeanRegistry
3.DefaultSingletonBeanRegistry
这里的singletonObjects是Bean的底层集合,里面装着被Spring容器管理的Bean对象
我们来获取一下这个map:
ConfigurableApplicationContext context = SpringApplication.run(SpringIocApplication.class, args);
Field singletonObjects = DefaultSingletonBeanRegistry.class.getDeclaredField("singletonObjects");
//暴力破解
singletonObjects.setAccessible(true);
//获取beanFactory
ConfigurableListableBeanFactory beanFactory = context.getBeanFactory();
//获取bean的map集合
Map<String,Object> map = (Map<String, Object>) singletonObjects.get(beanFactory);
//遍历map集合
map.forEach((k,v)->{
System.out.println(k+"="+v);
});
因为bean太多了,我们这里仅将我们自己写的@Compont组件遍历出来
@Component
public class Component1 {
private String name;
}
@Component
public class Component2 {
private String name;
}
map.entrySet().stream().filter(e->e.getKey().startsWith("component"))
.forEach(e->{
System.out.println(e.getKey()+"="+e.getValue());
});
运行结果:
component1=com.example.springioc.component.Component1@25c5e994
component2=com.example.springioc.component.Component2@
这样就能看到我们自己定义的Bean了!
二.ApplicationContext的功能
看一下它继承图
1.MessageSource接口
该接口主要是用来实现国际化,为不同语言翻译
先准备三份不同语言的配置文件
messages_zh.properties
hi=你好
messages_en.properties
hi=hello
messages_ja.properties
hi=こんにちは
System.out.println(context.getMessage("hi", null, Locale.ENGLISH));
System.out.println(context.getMessage("hi", null, Locale.CHINA));
System.out.println(context.getMessage("hi", null, Locale.JAPANESE));
这样就可以获取到配置文件中不同语言的值
2.RscourcePatternReslover接口
该接口提供的方法getResources()获取资源文件
Resource[] resources = context.getResources("classpath*:/META-INF/spring.factories");
for (Resource resource : resources) {
System.out.println(resource);
}
获取所有的spring.factories文件
URL [jar:file:/C:/Users/JJH/.m2/repository/org/springframework/boot/spring-boot/2.6.13/spring-boot-2.6.13.jar!/META-INF/spring.factories]
URL [jar:file:/C:/Users/JJH/.m2/repository/org/springframework/spring-beans/5.3.23/spring-beans-5.3.23.jar!/META-INF/spring.factories]
URL [jar:file:/C:/Users/JJH/.m2/repository/org/springframework/boot/spring-boot-autoconfigure/2.6.13/spring-boot-autoconfigure-2.6.13.jar!/META-INF/spring.factories]
3.EnvironmentCapable接口
该接口提供getEnvironment()方法获取环境变量以及配置文件中的值
String java_home = context.getEnvironment().getProperty("java_home");
System.out.println(java_home);
String port= context.getEnvironment().getProperty("server.port");
System.out.println(port);
E:\java
8081
4.ApplicationEventPublisher接口
该接口提供了发布事件的功能
1.先写一个用户注册功能,需要继承ApplicationEvent
public class UserRegisterEvent extends ApplicationEvent {
public UserRegisterEvent(Object source) {
super(source);
}
}
2.发布事件
context.publishEvent(new UserRegisterEvent(context));
3.监听事件
@Component
public class Component2 {
private final static Logger log = (Logger) LoggerFactory.getLogger(Component2.class);
@EventListener
public void getEvent(UserRegisterEvent event){
log.info("{}",event);
}
}
运行结果:
2023-09-17 20:15:31.090 INFO 12308 --- [ main] c.e.springioc.component.Component2 : com.example.springioc.component.UserRegisterEvent[source=org.springframework.context.annotation.AnnotationConfigApplicationContext@7f0d96f2, started on Sun Sep 17 20:15:30 CST 2023]
可以看到,context发布了UserRegister事件,Component2接受到了该事件
下面模拟用户注册完发送短信功能:
1.定义用户注册功能
@Component
public class Component1 {
private final static Logger log = LoggerFactory.getLogger(Component1.class);
@Autowired
private ApplicationEventPublisher publisher;
public void register(){
log.info("用户注册!");
publisher.publishEvent(new UserRegisterEvent(this));
}
}
2.实现发送短信功能
@Component
public class Component2 {
private final static Logger log = (Logger) LoggerFactory.getLogger(Component2.class);
@EventListener
public void getEvent(UserRegisterEvent event){
log.info("发送短信");
}
}
4.调用注册方法
context.getBean(Component1.class).register();
5.运行结果
2023-09-17 20:29:18.311 INFO 4984 --- [ main] c.e.springioc.component.Component1 : 用户注册!
2023-09-17 20:29:18.311 INFO 4984 --- [ main] c.e.springioc.component.Component2 : 发送短信
实现了用户注册完发送短信的功能