Skip to content
On this page

Spring 第二讲 BeanFactory 和ApplicationContext

pom.xml 准备

xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.5.5</version>
        <relativePath/>
    </parent>

    <groupId>org.laoshiren</groupId>
    <artifactId>spring-bean-init</artifactId>
    <version>1.0-SNAPSHOT</version>

    <properties>
        <maven.compiler.source>8</maven.compiler.source>
        <maven.compiler.target>8</maven.compiler.target>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
        </dependency>


        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
        </dependency>

    </dependencies>
</project>
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
33
34
35
36

BeanFactory

  • BeanFactory 接口,典型功能有:

    • getBean
  • ApplicationContext 接口,是 BeanFactory 的子接口。它扩展了 BeanFactory 接口的功能,如:

    • 国际化
    • 通配符方式获取一组 Resource 资源
    • 整合 Environment 环境(能通过它获取各种来源的配置信息)
    • 事件发布与监听,实现组件之间的解耦
java
@Configuration
public class Config {
    @Bean
    public Bean1 bean1(){
        return new Bean1();
    }
    @Bean
    public Bean2 bean2(){
        return new Bean2();
    }
}

@Data
@Slf4j
public class Bean1 {
    @Autowired
    private Bean2 bean2;
    public Bean1(){
        log.info("bean1 构造");
    }
}

@Slf4j
public class Bean2 {
    public Bean2(){
        log.info("bean2 构造");
    }
}
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

当我们使用BeanFactory 加载这个Config类会有多少个Bean

java
public class BeanFactoryMain {
    public static void main(String[] args) {
        DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
        // bean 定义(class  scope )BeanDefinition
        AbstractBeanDefinition configBeanDefinition = BeanDefinitionBuilder
                .genericBeanDefinition(Config.class)
                .getBeanDefinition();
        // 注册bean
        beanFactory.registerBeanDefinition("config", configBeanDefinition);
      
        for (String beanDefinitionName : beanFactory.getBeanDefinitionNames()) {
            System.out.println("\t"+beanDefinitionName);
        }
        System.out.println("------------------------------");
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
shell
# 打印结果
	config
------------------------------
1
2
3

只有自己注册的config 没有其他的Bean1 和 Bean2 是因为没有后置处理器处理去解析Config

我们给BeanFactory加载一些后置处理器

java
public class BeanFactoryMain {
    public static void main(String[] args) {
        DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
        // bean 定义(class  scope )BeanDefinition
        AbstractBeanDefinition configBeanDefinition = BeanDefinitionBuilder
                .genericBeanDefinition(Config.class)
                .getBeanDefinition();
        // 注册bean
        beanFactory.registerBeanDefinition("config", configBeanDefinition);
        // 给 beanFactory 添加一些常用的后置处理器
      	AnnotationConfigUtils.registerAnnotationConfigProcessors(beanFactory);
        for (String beanDefinitionName : beanFactory.getBeanDefinitionNames()) {
            System.out.println("\t"+beanDefinitionName);
        }
        System.out.println("------------------------------");
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
shell
## 打印结果
	config
	org.springframework.context.annotation.internalConfigurationAnnotationProcessor
	org.springframework.context.annotation.internalAutowiredAnnotationProcessor
	org.springframework.context.annotation.internalCommonAnnotationProcessor
	org.springframework.context.event.internalEventListenerProcessor
	org.springframework.context.event.internalEventListenerFactory
------------------------------
1
2
3
4
5
6
7
8

发现还是没有我们的Bean1 和 Bean2 是因为我们的后置处理器已经是Bean了 但是却没有工作

java
public class BeanFactoryMain {
    public static void main(String[] args) {
        DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
        // bean 定义(class  scope )BeanDefinition
        AbstractBeanDefinition configBeanDefinition = BeanDefinitionBuilder
                .genericBeanDefinition(Config.class)
                .getBeanDefinition();
        // 注册bean
        beanFactory.registerBeanDefinition("config", configBeanDefinition);
        // 给 beanFactory 添加一些常用的后置处理器
        AnnotationConfigUtils.registerAnnotationConfigProcessors(beanFactory);
        // 获取BeanFactory后置处理器 补充了Bean
        Map<String, BeanFactoryPostProcessor> beansOfType =
                beanFactory.getBeansOfType(BeanFactoryPostProcessor.class);
        // 执行后置处理器方法
        beansOfType
                .forEach((key, value) -> value.postProcessBeanFactory(beanFactory));
      	// 创建所有的单例Bean
        beanFactory.preInstantiateSingletons();
        for (String beanDefinitionName : beanFactory.getBeanDefinitionNames()) {
            System.out.println("\t"+beanDefinitionName);
        }
        System.out.println("------------------------------");
    }
}
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
shell
# 打印结果
	config
	org.springframework.context.annotation.internalConfigurationAnnotationProcessor
	org.springframework.context.annotation.internalAutowiredAnnotationProcessor
	org.springframework.context.annotation.internalCommonAnnotationProcessor
	org.springframework.context.event.internalEventListenerProcessor
	org.springframework.context.event.internalEventListenerFactory
	bean1
	bean2
------------------------------
1
2
3
4
5
6
7
8
9
10

但是我们Debug 发现Bean1 里的属性却是null,因为我们没有让我们的BeanPostProcessor 发挥作用

java
public class BeanFactoryMain2 {
    public static void main(String[] args) {
        DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
        // bean 定义(class  scope )BeanDefinition
        AbstractBeanDefinition configBeanDefinition = BeanDefinitionBuilder
                .genericBeanDefinition(Config.class)
                .getBeanDefinition();
        // 注册bean
        beanFactory.registerBeanDefinition("config", configBeanDefinition);
        // 给 beanFactory 添加一些常用的后置处理器
        AnnotationConfigUtils.registerAnnotationConfigProcessors(beanFactory);
        // 获取Bean后置处理器 补充了Bean
        Map<String, BeanFactoryPostProcessor> beansOfType =
                beanFactory.getBeansOfType(BeanFactoryPostProcessor.class);
        // 执行后置处理器方法
        beansOfType
                .forEach((key, value) -> value.postProcessBeanFactory(beanFactory));

        // Bean 后置处理器, 对bean 的生命周期各个阶段提供扩展 例如@Autowired
        Map<String, BeanPostProcessor> beanPostProcessorMap = beanFactory.getBeansOfType(BeanPostProcessor.class);
        // 添加后置处理器 getBean 的时候就会执行后置处理器
        beanPostProcessorMap.values()
                .forEach(beanFactory::addBeanPostProcessor);
        // 创建所有的单例Bean
        beanFactory.preInstantiateSingletons();
        for (String beanDefinitionName : beanFactory.getBeanDefinitionNames()) {
            System.out.println("\t"+beanDefinitionName);
        }
        System.out.println("------------------------------");
    }
}
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

这个时候才发现我们的Bean1才正常。而ApplicationContext 和BeanFactory 不一样。

ApplicationContext

我们获取的ApplicationContext 都是通过设计模式中的组合模式将我们BeanFactory 当做属性加载进来。而通过ApplicationContext 获取Bean 也是通过其中的BeanFactory 去获取的。

java
public class GenericApplicationContext 
    extends AbstractApplicationContext 
    implements BeanDefinitionRegistry {

	private final DefaultListableBeanFactory beanFactory;

}
1
2
3
4
5
6
7
java
public abstract class AbstractApplicationContext 
    extends DefaultResourceLoader
	implements ConfigurableApplicationContext {
    
    @Override
	public <T> T getBean(Class<T> requiredType) throws BeansException {
		assertBeanFactoryActive();
		return getBeanFactory().getBean(requiredType);
	}
}
1
2
3
4
5
6
7
8
9
10

a.png

除去BeanFactory 还实现了EnvironmentCapableMessageSourceApplicationEventPublisherResourcePatternResolver

MessageSource

MessageSource 是解决国际化的问题,我们在resource 创建3个文件

message.properties

shell

1

message_zh.properties

shell
user.login.username=用户名
user.login.password=密码
1
2

message_en.properties

shell
user.login.username=User name
user.login.password=Password
1
2
yaml
spring:
  messages:
    basename: messages
1
2
3
java
@SpringBootApplication
public class App {

    public static void main(String[] args) {
        ConfigurableApplicationContext ctx = SpringApplication.run(App.class, args);
        
        System.out.println(ctx.getMessage("user.login.password", null, Locale.CHINA));
        System.out.println(ctx.getMessage("user.login.password", null, Locale.US));
    }
}
1
2
3
4
5
6
7
8
9
10

ResourceLoader

加载文件使用的接口

java
@SpringBootApplication
public class App {

    public static void main(String[] args) {
        ConfigurableApplicationContext ctx = SpringApplication.run(App.class, args);
        // ResourceLoader
        // 外部文件 file:
        // classpath:
        // 其他jar包 classpath*:
        Resource resource = ctx.getResource("classpath:application.yml");
        System.out.println(resource);
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13

EnvironmentCapable

环境属性的接口

java
@SpringBootApplication
public class App {

    public static void main(String[] args) {
        ConfigurableApplicationContext ctx = SpringApplication.run(App.class, args);
        // EnvironmentCapable
        ConfigurableEnvironment environment = ctx.getEnvironment();
        System.out.println(environment.getProperty("java_home"));
    }
}
1
2
3
4
5
6
7
8
9
10

ApplicationEventPublisher

不解释使用的太多了

Released under the MIT License.