前言
〉 学习Spring,你一定遇到的纠结在于BeanFactory
和 FactoryBean
是啥玩意,Spring 起名页太不靠谱了吧。我只想说Spring的起名还是很见名知意的。虽然这两兄弟长得很像也很容易搞混淆,但是只要理解他们的作用你就再也不会纠结了。
- 首先BeanFactory 就是一个bean工厂, 这是Spring的基石。接下来我们先看看BeanFactory. 光是了解学习它就需要很长的篇幅了,所以今天我们只谈BeanFactory. 至于FactoryBean 我们后续继续
容器接口
Spring
可以说是Java
开发者的首选框架,没有之一。不知道这么说有没有要反驳 ~~~。- 我们启动一个
Spring
项目非常的简单。
java
@SpringBootApplication
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
- 不知道你有没有点进去
run
看看这个方法的结构。
java
public static ConfigurableApplicationContext run(Class<?> primarySource,
String... args) {
return run(new Class<?>[] { primarySource }, args);
}
- 所以
ConfigurableApplicationContext
的地位不言而喻了吧。
BeanFactory
- 通过看他的接口你可能会感觉
BeanFactory
好简单啊,基本上就一个getBean
这个方法。但是它的内部还包括对Bean
的生命周期管理,以及Bean
的单例。
-
这里我先强插一脚,在
Spring
中使用的是DefaultListableBeanFactory
这个实现类作为BeanFactory
的执行。我们也能够看到DefaultListableBeanFactory
继承了很多类,这也说明它具备很多功能,不仅仅是BeanFactory
中的getBean
。SingletonBeanRegistry
: 注册单例 BeanHierarchicalBeanFactory
: 父子容器ListableBeanFactory
: 列出容器内 BeanBeanDefinitionRegistry
: 注册Bean
-
很多的功能来自于父类. 接下来我们来随便看看它的功能,比如查看容器内单例对象,为了演示方便,这里我们就不通过代码跟踪的方式获取了。直接暴力点
-
因为我们的
ApplicationContext
本身就具备BeanFactory
功能,所以只需要反射下就行。
java
ConfigurableApplicationContext configurableApplicationContext = SpringApplication.run(A0001Application.class);
Field singletonObjects = DefaultSingletonBeanRegistry.class.getDeclaredField("singletonObjects");
singletonObjects.setAccessible(true);
Map<String, Object> o = (Map<String, Object>) singletonObjects.get(configurableApplicationContext.getBeanFactory());
for (Map.Entry<String, Object> entry : o.entrySet()) {
System.out.println("key:"+entry.getKey()+"
value:"+entry.getValue());
}
ApplicationContext
- 通过上面的 UML 类图,我们能够发现它继承了
BeanFactory
,说明了它具有BeanFactory
的能力,而BeanFactory
是获取操作Bean
的工具类。所以ApplicationContext
地位更加的重要。 - ApplicationContext 比 BeanFactory 多了点啥呢?
- 我们只需要对比下
ConfigurableApplicationContext
和DefaultListableBeanFactory
两个类的 UML 不难发现,ApplicationContext
大概多出了MessageSource
、ResourcePatternResolver
、ApplicationEventPublisher
、EnvironmentCapble
这四个类的功能。MessageSource
: 国际化功能ResourcePatternResolver
: 通配符匹配路径资源,classpath://hello/**
ApplicationEventPublisher
: 事件EnvironmentCapble
: 处理配置文件yml
等属性。
MessageSource
-
该功能是用来处理国际化的,处理国际化其实很简单,我们只需要在
resources
下准备好对应语言的提示文件,然后通过ApplicationContext
获取对应参数的属性值即可。 -
配置文件是
properties
所以在idea
中我们需要设置下对应的文件编码,否则会出现非英文乱码的。
- 接着我们在
resources
下分别准备汉语
、英语
、日语
三国语言。
text
hello=你好,新华
- 每个文件中我们准备好对应的 key 即可,然后在代码中获取的时候指定语言和 key 即可。
java
System.out.println(configurableApplicationContext.getMessage("hello", null, Locale.CHINA));
System.out.println(configurableApplicationContext.getMessage("hello", null, Locale.ENGLISH));
System.out.println(configurableApplicationContext.getMessage("hello", null, Locale.JAPANESE));
ResourcePatternResolver
- 该类是支持通配符获取资源文件。在
ApplicationContext
中的体现就是getResource