是根据黑马Spring源码课程总结的
第一讲、容器初步
1、容器接口
Spring容器的接口主要有两个,一个是BeanFactory,一个是ApplicationContext。
实际上BeanFactory是Spring的核心容器,ApplicationContext是它的子接口,也实现了更多的功能。
2、BeanFactory初步
类的继承图如下:
当使用到getBean()方法的时候,实际上就是使用的BeanFactory的getBean()方法:
context.getBean("aa");
Ctrl + Alt + 鼠标左键,查看源码是:
public Object getBean(String name) throws BeansException {
this.assertBeanFactoryActive();
return this.getBeanFactory().getBean(name);
}
也就可以看出先getBeanFactory()后,用BeanFactory的getBean()方法。
进入BeanFactory,使用Ctrl + F12查看所有方法:
BeanFactory的重要实现类是DefaultListableBeanFactory:
DefaultSingletonBeanRegistry实现了单例bean,点击类图中的该类,然后按F4进入该类,这个参数就是保存了单例,key是String类型的名字,value是Object类型的实例:
private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256);
可以使用debug的方式或者反射的方式:
Field singletonObjects = DefaultSingletonBeanRegistry.class.getDeclaredField("singletonObjects");
singletonObjects.setAccessible(true);
ConfigurableListableBeanFactory beanFactory = context.getBeanFactory();
Map<String, Object> map = (Map<String, Object>) singletonObjects.get(beanFactory);
map.entrySet().stream().filter(e -> e.getKey().startsWith("component"))
.forEach(e -> {
System.out.println(e.getKey() + "=" + e.getValue());
});
总而言之,控制反转、依赖注入、Bean的生命周期都是由BeanFactory提供的。
3、ApplicationContext初步
还是上面的类图,ApplicationContext有几个比较关键的继承接口:
- MessageSource:具备处理国际化资源的能力,但是注意要做i8n
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));
- ResourcePatternResolver:具有通配符匹配资源的能力
下面的代码可以处理上面两个功能:
//classpath*:是可以找到jar包里的文件的,下面的这个可以找到多个文件
Resource[] resources = context.getResources("classpath*:META-INF/spring.factories");
for (Resource resource : resources) {
System.out.println(resource);
}
- EnvironmentCapable:具有可以读取环境信息的能力
System.out.println(context.getEnvironment().getProperty("java_home"));
System.out.println(context.getEnvironment().getProperty("server.port"));
- ApplicationEventPublisher:具备发布事件对象的功能
组件1:
@Component
public class Component1 {
private static final Logger log = LoggerFactory.getLogger(Component1.class);
@Autowired
private ApplicationEventPublisher context;
public void register() {
log.debug("用户注册");
context.publishEvent(new UserRegisteredEvent(this));
}
}
组件2:
@Component
public class Component2 {
private static final Logger log = LoggerFactory.getLogger(Component2.class);
@EventListener
public void aaa(UserRegisteredEvent event) {
log.debug("{}", event);
log.debug("发送短信");
}
}
测试类:
context.getBean(Component1.class).register();