0%

spring | BeanFactory && ApplicationContext

spring boot 程序入口

1
2
3
4
5
6
7
8
9
@SpringBootApplication
public class Application {

public static void main(String[] args) {
// run 返回的就是 spring 容器 ConfigurableApplicationContext 是 ApplicationContext 子接口
ConfigurableApplicationContext configurableApplicationContext = SpringApplication.run(Application.class, args);

}
}

什么是 BeanFactory

  • 它是 ApplicationContext 的父接口
  • 它才是 Spring 的核心容器,主要的 ApplicationContext 实现都是组合了它的功能

代码如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
@SpringBootApplication
public class Application {

public static void main(String[] args) {
// run 返回的就是 spring 容器 ConfigurableApplicationContext 是 ApplicationContext 子接口
ConfigurableApplicationContext configurableApplicationContext = SpringApplication.run(Application.class, args);

configurableApplicationContext.getBean("aaa");
// 安装 command + option + 点击会调转到实现类的方法
/**
* 上述跳转代码wei
*
* public Object getBean(String name) throws BeansException {
* this.assertBeanFactoryActive();
* return this.getBeanFactory().getBean(name);
*}
*
* 可以看出其也是 this.getBeanFactory() 然后接着执行
* */

}
}

BeanFactory 功能

虽然表面上只有 getBean 方法,实际上 控制反转、基本的依赖注入、直至 Bean 的生命周期的各种功能都由它实现类提供。

它的实现类叫做 DefaultListableBeanFactory,其类图如下

DefaultListableBeanFactory 能够操作单例是因为实现了 DefaultSingletonBeanRegistryDefaultSingletonBeanRegistry 里面有一个属性

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

存放着所有的单例。

通过反射,我们可以查找到这些单例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
package com.lou.springboot;

import org.mybatis.spring.annotation.MapperScan;
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
import org.springframework.beans.factory.support.DefaultSingletonBeanRegistry;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ConfigurableApplicationContext;

import java.lang.reflect.Field;
import java.util.Map;

/**
* Hello shiyanlou!
*/
@SpringBootApplication
public class Application {

public static void main(String[] args) throws NoSuchFieldException, IllegalAccessException {
// run 返回的就是 spring 容器 ConfigurableApplicationContext 是 ApplicationContext 子接口
ConfigurableApplicationContext configurableApplicationContext = SpringApplication.run(Application.class, args);
Field field = DefaultSingletonBeanRegistry.class.getDeclaredField("singletonObjects");
field.setAccessible(true);
ConfigurableBeanFactory configurableApplicationContext1 = configurableApplicationContext.getBeanFactory();
Map<String, Object> map = (Map<String, Object>) field.get(configurableApplicationContext1);
map.forEach(
(k, v) -> {
System.out.println(k + "=" + v);
}
);
}
}
请我喝杯咖啡吧~