【黑马】Spring底层原理第一讲

BeanFactoryApplicationContext的区别和联系

什么是BeanFactory

首先我们常用的启动类中的 SpringApplication.run(DemoApplication.class, args);返回的就是ConfigurableApplicationContext,他是继承BeanFactory的,也就是spring容器对象。下面是ConfigurableApplicationContext的类图 【打开类图的快捷键为 ctrl + alt + u

在这里插入图片描述

代码:

public static void main(String[] args) {
    // 返回的就是spring容器
    ConfigurableApplicationContext run = SpringApplication.run(DemoApplication.class, args);
    System.out.println(run);
}

说明:

BeanFactoryspring的核心容器,主要的ApplicationContext实现(或者说组合)了他的功能。

BeanFactory的实现类为DefaultListableBeanFactory,光看BeanFactory里面可能我们熟悉的只有getBean方法,但是控制反转,基本的依赖注入都是在实现类中完成的。

BeanFactory能干点啥?

其实主要定义了关于获取Bean的方法

在这里插入图片描述

BeanFactory的主要实现类是DefaultListableBeanFactory

管理单例类的实现类为DefaultSingletonBeanRegistry,在DefaultSingletonBeanRegistry中所有的单例对象都保存在一个ConcurrentHashMap

private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256);

这里可以通过反射获取到singletonObjects来观察其中的内容。

如果使用注解,将类交给Spring容器进行管理,那么在下面打印的键值对中,你也可以看到对应的类。

public static void main(String[] args) throws Exception {
    // 返回的就是spring容器
    ConfigurableApplicationContext context = SpringApplication.run(DemoApplication.class, args);

    Field singletonObjects = DefaultSingletonBeanRegistry.class.getDeclaredField("singletonObjects");
    singletonObjects.setAccessible(true);
    ConfigurableListableBeanFactory beanFactory = context.getBeanFactory();

    Map<String, Object> map = (Map<String, Object>) singletonObjects.get(beanFactory);
    /**
         * 所有注入到spring容器中的类都能获取到,可以自定义类查看
         */
    map.forEach((k, v) -> {
        System.out.println(k + " = " + v);
    });
}

ApplicationContext接口扩展了啥?

在这里插入图片描述

// 国际化【翻译】
context.getMessage("hi", null, Locale.US);
context.getMessage("hi", null, Locale.CANADA);

// 读取配置文件的
// class path resource [application.properties]
Resource resource = context.getResource("classpath:application.properties");
System.out.println(resource);
// classpath*
Resource[] resource1 = context.getResources("classpath*:META-INF/spring.factories");
for (Resource resource2 : resource1) {
    System.out.println(resource2);
}
// 结果为
//URL [jar:file:/D:/maven/apache-maven-3.6.3/resp/org/springframework/boot/spring-boot/2.3.7.RELEASE/spring-boot-2.3.7.RELEASE.jar!/META-INF/spring.factories]
//URL [jar:file:/D:/maven/apache-maven-3.6.3/resp/org/springframework/boot/spring-boot-autoconfigure/2.3.7.RELEASE/spring-boot-autoconfigure-2.3.7.RELEASE.jar!/META-INF/spring.factories]
//URL [jar:file:/D:/maven/apache-maven-3.6.3/resp/org/springframework/spring-beans/5.2.12.RELEASE/spring-beans-5.2.12.RELEASE.jar!/META-INF/spring.factories]

// 获取系统配置信息的
System.out.println(context.getEnvironment().getProperty("java_home"));// D:\jdk
System.out.println(context.getEnvironment().getProperty("spring.application.name"));// demo

事件发布器:【比较有趣】

发送事件的方式

context.publishEvent(new UserEvent(context));

定义事件发送类

public class UserEvent extends ApplicationEvent {
    public UserEvent(Object source) {
        super(source);
    }
}

定义事件接受类

方法名任意,但参数必须为想要接收的事件的类型,可以同时定义多个,发送的时候,是广播的形式,所有的接收类都会收到这个事件。

@Component
public class Component1 {
    @EventListener
    public void aaa(UserEvent event){
        System.out.println("我收到事件了");
    }
}
@Component
public class Component2 {
    @EventListener
    public void aaa(UserEvent event){
        System.out.println("我收到事件了222222");
    }
}

那么事件具体有什么用呢?

如果在用户注册动作中,在用户注册完毕之后,想要发送一个邮件,或者短信,这时候就可以使用事件的方式。

结合Spring技术内幕来补充

1、对于Spring的具体IoC容器实现来说,它需要满足的基本特性是什么呢?它需要满足BeanFactory这个基本的接口定义。

可想而知BeanFactory继承树等级是最高的,同时也是最基础的。

2、在Spring提供的基本IoC容器的接口定义和实现的基础上,Spring通过定义BeanDefinition来管理基于Spring的应用中的各种对象以及他们之间的相互依赖关系。BeanDefinition抽象了我们对Bean的定义,是让容器起作用的主要数据类型

这里的BeanDefinition按照书中的解释,可以这么理解,如果Spring容器可以看作是各式各样的水桶,那么BeanDefinition就是水桶中的水。也就是水桶发挥作用的根本。

3、计算机中所有的功能都是建立在通过数据对现实进行抽象的基础上进行的。

虽然这句话在书中仅仅是作为铺垫,但是在学习设计模式的时候,我就深有感触,在设计模式中,你会发现,这就是我们生活中的例子,只不过前辈们依靠编程语言的特性和计算机设计思想总结出了23种设计模式。但设计模式的难度在于,没有一定的开发经验,或者没有经历过这种场景的,有时候很难理解。推荐黑马的设计模式,讲的很透彻

本文是通过黑马程序员的spring5底层原理视频学习总结的,包含一些个人看法,总结了一些Spring技术内幕书籍中的关键语句。如有错误,欢迎指正。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值