Spring源码学习
BeanFactory 与 ApplicationContext 的区别
BeanFactory 接口,典型功能有getBean()
ApplicationContext 接口,是 BeanFactory 的子接口。它扩展了 BeanFactory 接口的功能,如:
国际化
通配符方式获取一组 Resource 资源
整合 Environment 环境(能通过它获取各种来源的配置信息)
事件发布与监听,实现组件之间的解耦
代码演示
@SpringBootApplication
@Slf4j
public class A01 {
public static void main(String[] args) throws Exception{
ConfigurableApplicationContext context = SpringApplication.run(A01.class);
/*
1. 到底什么是 BeanFactory
- 它是 ApplicationContext 的父接口
- 它才是 Spring 的核心容器, 主要的 ApplicationContext 实现都【组合】了它的功能
*/
System.out.println("context:" + context);
/*
2. BeanFactory 能干点啥
- 表面上只有 getBean
- 实际上控制反转、基本的依赖注入、直至 Bean 的生命周期的各种功能, 都由它的实现类提供
*/
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("compo")).forEach((e)->{
System.out.println(e.getKey() + "=" + e.getValue());
});
/*
3. ApplicationContext 比 BeanFactory 多点啥
*/
System.out.println(context.getMessage("hi",null, Locale.JAPANESE));
System.out.println(context.getMessage("hi",null, Locale.ENGLISH));
Resource[] resources = context.getResources("classpath*:META-INF/spring.factories");
for (Resource resource : resources) {
System.out.println(resource);
}
System.out.println(context.getEnvironment().getProperty("java_home"));
System.out.println(context.getEnvironment().getProperty("server.port"));
context.getBean(Component1.class).register();
}
/*
4. 学到了什么
a. BeanFactory 与 ApplicationContext 并不仅仅是简单接口继承的关系, ApplicationContext 组合并扩展了 BeanFactory 的功能
b. 又新学一种代码之间解耦途径
*/
}
Component1
@Component
public class Component1 {
@Resource
private ApplicationEventPublisher context;
public void register(){
System.out.println("用户注册");
context.publishEvent(new UserRegisteredEvent(this));
}
}
Component2
@Component
public class Component2 {
@EventListener
public void aaa(UserRegisteredEvent event){
System.out.println("event:" + event);
System.out.println("发送短信");
}
}
UserRegisteredEvent
public class UserRegisteredEvent extends ApplicationEvent {
public UserRegisteredEvent(Object source) {
super(source);
}
}
代码看不懂 不要着急
代码详解
BeanFactory 与 ApplicationContext 类图
鼠标移动到ConfigurableApplicationContext上,shift + alt + u 打开类关系图:
根据类图可以看出:ApplicationContext比BeanFactory多4个继承接口,分别为:
MessageSource 国际化
ResourcePatternResolver 通配符方式获取一组 Resource 资源
EnvironmentCapable 整合 Environment 环境(能通过它获取各种来源的配置信息)
ApplicationEventPublisher 事件发布与监听,实现组件之间的解耦
BeanFactory
-
1.通过DefaultSingletonBeanRegistry(默认单例Bean注册表)反射拿到属性singletonObjects(一级缓存)
-
2.反射中暴力破解该对象,使其能够调用对应的方法,属性
-
3.通过context调用getBeanFactory()得到beanFactory属性
getBeanFactory()是BeanFactory类下的一个方法
ApplicationContext继承BeanFactory,则通过方法名直接调用
ConfigurableListableBeanFactory也继承于BeanFactory
-
4. 通过get当前beanFactory对象,从一级容器中取出对象
-
5. 输出容器中名称前缀为compo的对象
当前容器存在多个对象(在一级缓存中,对象注入都是以类名小写)
filter -> 筛选类名前缀(startsWith)是compo的 并循环打印
ApplicationContext
ApplicationEventPublisher 事件发布与监听,实现组件之间的解耦
context.getBean(Component1.class).register();
@Component
public class Component1 {
@Resource
private ApplicationEventPublisher context;
public void register(){
System.out.println("用户注册");
// 事件发布
context.publishEvent(new UserRegisteredEvent(this));
}
}
@Component
public class Component2 {
// 这里的注解 表示事件监听 监听对象是UserRegisteredEvent
@EventListener
public void aaa(UserRegisteredEvent event){
System.out.println("event:" + event);
System.out.println("发送短信");
}
}
// 这里需要继承ApplicationEvent
public class UserRegisteredEvent extends ApplicationEvent {
public UserRegisteredEvent(Object source) {
super(source);
}
}
完结撒花!愿每一位程序员少走弯路是我创作的初心!如需博客文章代码,请私信
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/234905.html