BeanFactory 接口
是什么?
先来看我们的boot项目启动类的run方法
public static ConfigurableApplicationContext run(Class<?> primarySource, String... args) {
return run(new Class[]{primarySource}, args);
}
返回一个 ConfigurableApplicationContext
的spring 容器,那么通过名称我们想到这个run返回的Spring容器和ApplicationContext具有一定的关系
我们查看ConfigurableApplicationContext
的类图
可以看到ConfigurableApplicationContext
的父接口是ApplicationContext
,而再向上看找到了BeanFactory
的顶级接口,说明ApplicationContext
扩展了BeanFactory
, 去实现了:
去实现了图中的四个接口。
那么看到这里,什么是BeanFactory
?
他是ApplicationContext的父接口,同时是Spring的核心容器,主要的ApplicationContext
实现都组合了BeanFactory
的功能
能做什么?
我们查看 BeanFactory
的接口看到
接口中的表面功能其实并不多,但是我们的IOC、基本的DI、Bean的生命周期的功能,都在他的实现类DefaultListableBeanFactory
里面:
那么DefaultListableBeanFactory
的父类中,有个DefaultSingletonBeanRegistry
实现了我们常说的单例对象的注册接口,那么我们看看他里面有哪些东西
//run方法返回applicationContext的可配置容器
ConfigurableApplicationContext applicationContext =
SpringApplication.run(SpringBootCloudStudyApplication.class, args);
System.out.println(applicationContext);
/**
* 然后我们根据父子类关系看到了BeanFactory和ApplicationContext的关系,
* 而其中BeanFactory的实现类DefaultListableBeanFactory中,有个父类DefaultSingletonBeanRegistry实现类单例注册接口
*
*/
//我们反射调用一下试下拿到DefaultSingletonBeanRegistry的所有单例对象
Field singletonObjects = DefaultSingletonBeanRegistry.class.getDeclaredField("singletonObjects");
singletonObjects.setAccessible(true);
ConfigurableListableBeanFactory beanFactory = applicationContext.getBeanFactory();
//获取当前容器的所有单例对象
Map<String, Object> beans = (Map<String, Object>) singletonObjects.get(beanFactory);
beans.forEach((k, v) -> {
System.out.println(k + " : " + v);
});
ApplicationContext 接口
我们刚刚其实看到了,ApplicationContext
相比于BeanFactory
多了四个接口实现,也就是BeanFactory
不具备的:
那么这些接口用来干嘛呢?
MessageSource:具备处理国际语言的能力
ResourcePatternResolver : 具备根据通配符匹配资源的能力
ApplicationEventPublisher:具备发布事件对象的能力
EnvironmentCapable:可以读取项目的环境信息,比如我们的yml的项目配置文件之类的能力
我们来看下具体的功能实现:
//MessageSource:具备处理国际语言的能力
System.out.println(applicationContext.getMessage("hi", null, Locale.CHINA));
System.out.println(applicationContext.getMessage("hi", null, Locale.ENGLISH));
//ResourcePatternResolver : 具备根据通配符匹配资源的能力
//类路径
Resource[] resources = applicationContext.getResources("classpath:application.properties");
for (Resource resource : resources) {
System.out.println(resource);
}
}
//ResourcePatternResolver : 具备根据通配符匹配资源的能力
//jar包中的资源文件
Resource[] JarResources = applicationContext.getResources("classpath*:META-INF/spring.factories");
for (Resource resource : JarResources) {
System.out.println(resource);
}
//EnvironmentCapable:可以读取项目的环境信息,比如我们的yml的项目配置文件之类的能力
String javaHome = applicationContext.getEnvironment().getProperty("JAVA_HOME");
String port = applicationContext.getEnvironment().getProperty("server.port");
System.out.println(javaHome);
System.out.println(port);
@Component
public class UserRegisteredListener {
@EventListener
public void onUserRegistered(UserRegisteredEvent event){
System.out.println("onUserRegistered监听器监听到了" );
}
}
public class UserRegisteredEvent extends ApplicationEvent {
public UserRegisteredEvent(Object source) {
super(source);
System.out.println("触发了用户注册事件");
}
}
//ApplicationEventPublisher:具备发布事件对象的能力
//需要先定义一个事件继承于ApplicationEvent,然后就可以发布事件
applicationContext.publishEvent(new UserRegisteredEvent(applicationContext));
其实这样也就实现了我们说的事件解耦
小结
BeanFactory和ApplicationContext之间并不是简单的接口继承关系,ApplicationContext组合并扩展了BeanFactory的功能
又学了一种代码之间的解耦关系
- ApplicationContext BeanFactory 容器 Spring gtapplicationcontext beanfactory容器spring applicationcontext beanfactory源码spring applicationcontext beanfactory体系spring 容器applicationcontext beanfactory多种 applicationcontext beanfactory框架spring applicationcontext beanfactory applicationcontext beanfactory之间 beanfactory源码spring beanfactory factorybean spring beanfactory版本spring