首先本次分析是基于注解形式的, 想来 xml 格式的原理都是类似的.
首先说一下什么是 Bean 定义(beandefinition):bean 定义并不是实例化的 bean, 而是 bean 对象的一些信息, 根据这些定义的信息最后来初始化 bean. 比方说就是一些类的信息, 还有我们配置的该实例的信息(是否懒加载, 单例还是多例, 作用域等等信息).
进入正题:
AnnotationConfigApplicationContext 构造方法传入一个主配置类, 那么就从该构造方法进去.
一, 我们先来看在容器刷新 (refresh()) 之前, 都干了什么.
1.this()首先会调用无参构造, 进而调用父类的无参构造, 初始化 beanFactory(DefaultListableBeanFactory), 再者初始化注解模式下的 bean 定义读取器, classPath 类型的 bean 定义扫描器;
2.register(annotatedClasses), 基于上面初始化的 bean 定义读取器去解析注册我们自己的配置类信息到容器中.
具体的流程图如下:
完成了这些准备工作. refresh()里面就会实例化具体的 bean 了.
二, 两个个扩展点
1. BeanDefinitionRegistryPostProcessor
Bean 定义处理器, 在注册 bean 定义的时候调用, 可以自己注册新的 bean 定义
先直接通过上下文对象获取一个 student, 会报错, 没有对应的 bean 定义
实现自己的 Bean 定义处理器
- MyBeanDefinitionRegistryPostProcessor
- package com.nijunyang.spring;
- import com.nijunyang.spring.model.Student;
- import org.springframework.beans.BeansException;
- import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
- import org.springframework.beans.factory.support.BeanDefinitionRegistry;
- import org.springframework.beans.factory.support.BeanDefinitionRegistryPostProcessor;
- import org.springframework.beans.factory.support.RootBeanDefinition;
- import org.springframework.stereotype.Component;
- /**
- * @author: create by nijunyang
- * @date:2019/10/6
- */
- @Component
- public class MyBeanDefinitionRegistryPostProcessor implements BeanDefinitionRegistryPostProcessor {
- //bean 定义注册处理器, 在注册 bean 定义的时候调用, 可以自己注册新的 bean 定义, 比如 Student
- @Override
- public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
- System.out.println("bean 定义的数据量:"+registry.getBeanDefinitionCount());
- RootBeanDefinition rootBeanDefinition = new RootBeanDefinition(Student.class);
- // 注册一个名为 student 的 bean 定义进去
- registry.registerBeanDefinition("student", rootBeanDefinition);
- System.out.println("bean 定义的数据量:"+registry.getBeanDefinitionCount());
- }
- @Override
- public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
- }
- }
注意需要加上 @Component, 并且主配置指定扫描的包将自己定义的类加载进去
- MainConfig
- package com.nijunyang.spring;
- import org.springframework.context.annotation.ComponentScan;
- import org.springframework.context.annotation.Configuration;
- /**
- * @author: create by nijunyang
- * @date:2019/10/6
- */
- @Configuration
- @ComponentScan(basePackages = "com.nijunyang.spring")
- public class MainConfig {
- }
正常获取 bean.
2.BeanFactoryPostProcessor
BeanFactory 后置处理器, 注册了 bean 定义之后调用, 可以修改 bean 定义, 比如实现一个自己的 BeanFactory 后置处理器, 把某个 bean 设置成懒加载.
断点运行 1 步骤中的代码, 发现 student 不是懒加载的
实现自己的 BeanFactory 后置处理器, 将 student 设置成懒加载
- MyBeanFactoryPostProcessor
- package com.nijunyang.spring;
- import org.springframework.beans.BeansException;
- import org.springframework.beans.factory.config.BeanDefinition;
- import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
- import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
- import org.springframework.stereotype.Component;
- /**
- * @author: create by nijunyang
- * @date:2019/10/6
- */
- @Component
- public class MyBeanFactoryPostProcessor implements BeanFactoryPostProcessor {
- // 注册了 bean 定义之后调用, 可以修改 bean 定义, 比如把 student 设置成懒加载
- @Override
- public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
- for(String name : beanFactory.getBeanDefinitionNames()) {
- if("student".equals(name)) {
- BeanDefinition beanDefinition = beanFactory.getBeanDefinition(name);
- beanDefinition.setLazyInit(true);
- }
- }
- }
- }
同样断点运行, 发现 student 不会马上被初始化了
来源: https://www.cnblogs.com/nijunyang/p/11628954.html