Spring IOC (一)

Spring IOC (一)

注册 **注解配置类、配置类 **的全过程

AnnotationConfigApplicationContext 类

定义:

​ 这个就是用Java配置类初始化的IOC容器 【以注解形式】

调用 AnnotationConfigApplicationContext(Class<?>… annotatedClasses) 构造方法,启动容器

构造方法:

​ 主要是通过构造方法来实例化 IOC容器 的,现在来看看构造方法

方法作用方法的类
super();初始化beanFactory 初始化 DefaultListableBeanFactory父类方法
this();初始化读取器 AnnotatedBeanDefinitionReader
扫描器 ClassPathBeanDefinitionScanner
本类
register(annotatedClasses);注册配置类 annotatedClassesreader 调用
refresh();刷新容器,重要方法本类

源码:

//根据参数类型可以知道,其实可以传入多个annotatedClasses,但是这种情况出现的比较少
    public AnnotationConfigApplicationContext(Class<?>... annotatedClasses) {
        //调用无参构造函数,会先调用父类GenericApplicationContext的构造函数
        //父类的构造函数里面就是初始化DefaultListableBeanFactory,并且赋值给beanFactory
        //本类的构造函数里面,初始化了一个读取器:AnnotatedBeanDefinitionReader read,一个扫描器ClassPathBeanDefinitionScanner scanner
        //scanner的用处不是很大,它仅仅是在我们外部手动调用 .scan 等方法才有用,常规方式是不会用到scanner对象的
        this();
        //把传入的类进行注册,这里有两个情况,
        //1. 传入传统的配置类
        //2. 传入bean(虽然一般没有人会这么做
        //spring把传统的带上@Configuration的配置类称之为FULL配置类,不带@Configuration的称之为Lite配置类
        //但是我们这里先把带上@Configuration的配置类称之为传统配置类,不带的称之为普通bean
        register(annotatedClasses);
        //刷新
        refresh();
    }

super()

定义:

​ 父类GenericApplicationContext的无参构造方法,用于初始化beanFactory

this()

定义:

​ 用于初始化 读取器 AnnotatedBeanDefinitionReader 和扫描器 ClassPathBeanDefinitionScanner

方法:

​ 主要是通过两个构造方法来实例化 读取器和扫描器,现在来看看构造方法

方法作用方法的类
AnnotatedBeanDefinitionReader(this)实例化reader,参数为this,即context
因为他实现了BeanDefinitionRegistry接口
用于注册配置类
reader类
ClassPathBeanDefinitionScanner(this)实例化scanner,参数为this,即context
因为他实现了BeanDefinitionRegistry接口
用于手动扫描类
scanner类

源码:

public class AnnotationConfigApplicationContext extends GenericApplicationContext implements AnnotationConfigRegistry {
	// 隐式调用super()
    //注解bean定义读取器,主要作用是用来读取被注解了的bean
    private final AnnotatedBeanDefinitionReader reader;
    
    //扫描器,它仅仅是在我们外部手动调用 .scan 等方法才有用,常规方式是不会用到scanner对象的
    private final ClassPathBeanDefinitionScanner scanner;

    public AnnotationConfigApplicationContext() {
        
        //初始化一个Bean读取器
        this.reader = new AnnotatedBeanDefinitionReader(this);

        //初始化一个扫描器,它仅仅是在我们外部手动调用 .scan 等方法才有用,常规方式是不会用到scanner对象
        this.scanner = new ClassPathBeanDefinitionScanner(this);
    }
}

AnnotatedBeanDefinitionReader()

定义:

​ 整个方法作用是:注册了配置类后置处理器,就是将实例化 配置类后置处理器 的原料放入了BeanDefinitionMap中,还没有真正的创建 配置类后置处理器 这个Bean

作用:

  • 注册了配置类后置处理器 —— 生成对应的BeanDefinition,加入Map 和 List

源码:

// 一、调用构造方法,进行注册 **注解配置处理器**
public AnnotatedBeanDefinitionReader(BeanDefinitionRegistry registry) {
		// ... 
        AnnotationConfigUtils.registerAnnotationConfigProcessors(this.registry);
}

// 二、AnnotationConfigUtils类 #registerAnnotationConfigProcessors
// 判断是否已经注册 **配置类后置处理器**,如果没有,就去new一个BeanDefinition
public static void registerAnnotationConfigProcessors(BeanDefinitionRegistry registry) {
    // 常量:CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME = "org.springframework.context.annotation.internalConfigurationAnnotationProcessor"; => 他指向的就是 **配置类后置处理器**
    if (!registry.containsBeanDefinition(CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME)) {
	// 如果 BeanDefinitionMap 中没有加载过这个类 internalConfigurationAnnotationProcessor
        // 创建一个 **配置类后置处理器** 的BeanDefinition 
        RootBeanDefinition def = new RootBeanDefinition(ConfigurationClassPostProcessor.class);

        // **registerPostProcessor()方法将bean放进Map中**
        beanDefs.add(registerPostProcessor(registry, def, CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME));
    }
}

// 三、AnnotationConfigUtils类 #registerPostProcessor
// 设置BeanDefinition的信息,调用registry去注册
private static BeanDefinitionHolder registerPostProcessor(
    BeanDefinitionRegistry registry, RootBeanDefinition definition, String beanName) {
	// ...
    // 调用BeanFactory 注册BeanDefinition
    registry.registerBeanDefinition(beanName, definition);
    return new BeanDefinitionHolder(definition, beanName);
}

// 四、DefaultListableBeanFactory类 #registerBeanDefinition
// 将bean定义推入BeanDefinitionMap 和 List
public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition) {
    //这里就是把beanName作为key,ScopedProxyMode作为value,推到map里面
    this.beanDefinitionMap.put(beanName, beanDefinition);

    //beanDefinitionNames就是一个List<String>,这里就是把beanName放到List中去
    this.beanDefinitionNames.add(beanName);
}
总结:
  • 实例化Reader()仅仅是将配置类后置处理器ConfigurationClassPostProcessor,注册到BeanDefinitionMap中,没有将他实例化,然后放入单例池

  • 只是把原料放进了map,没有拉进工厂生产

流程:

  • 构造方法,注册所有 注解配置处理器
  • 发现 配置类后置处理器(属于 注解配置处理器)未注册
  • 转换为BeanDefinition
  • 放入Map

注解配置处理器有哪些?

  • ConfigurationClassPostProcessor —— 处理@Configuration类

  • AutowiredAnnotationBeanPostProcessor —— 解析@Autowired、@Value注解

  • CommonAnnotationBeanPostProcessor —— 解析@Resource注解、@PostConstruct、@PreDestroy

    • JSR250标准,推荐使用@Resource
  • PersistenceAnnotationBeanPostProcessor —— Bean持久化到数据库有关的

    • JPA包支持
  • EventListenerMethodProcessor —— 时间监视器

  • DefaultEventListenerFactory —— 支持@EventListener注解

register(annotatedClasses)

定义:

​ 整个方法的作用是:注册了一群配置类们,【因为是可变参数嘛】,就是将实例化 配置类的原料放入了BeanDefinitionMap中,还没有真正创建 配置类 这群Bean

// 一、调用register(annotatedClasses)注册传入的配置类
// 注意,刚刚是注册**配置类后置处理器**,现在是注册**配置类**
// **配置类后置处理器**,是用来解析**配置类**的,帮助配置类实例化的
public void register(Class<?>... componentClasses) {
   // ...
    this.reader.register(componentClasses);
}

// 二、AnnotatedBeanDefinitionReader类 #register
// 开始循环注册**配置类**
public void register(Class<?>... componentClasses) {
    for (Class<?> componentClass : componentClasses) {
        registerBean(componentClass);
    }
}

// 三、AnnotatedBeanDefinitionReader类 #registerBean
public void registerBean(Class<?> beanClass) {
    // 执行注册**配置类**
    doRegisterBean(beanClass, null, null, null, null);
}

// 四、AnnotatedBeanDefinitionReader类 #doRegisterBean
// 拿到**配置类**的注解,按要求来注册**配置类**
private <T> void doRegisterBean(Class<T> annotatedClass ...) {

    // AnnotatedGenericBeanDefinition类,里面有一个getMetadata方法,可以拿到类上的注解
    // 转换的目的就是为了拿到注解@,开始解析配置类的注解
    AnnotatedGenericBeanDefinition abd = new AnnotatedGenericBeanDefinition(annotatedClass);

    // @Condition注解起效,可以跳过类
    if (this.conditionEvaluator.shouldSkip(abd.getMetadata())) {
        return;
    }

    // @Scope注解起效,默认单例
    ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(abd);
    abd.setScope(scopeMetadata.getScopeName());

    // 获得beanName
    String beanName = (name != null ? name : this.beanNameGenerator.generateBeanName(abd, this.registry));

    // 解析通用注解
    // @Lazy:懒加载;@Primary:优先使用注解;@DependsOn:依赖于某个Bean;@Role:标识角色;@Description:Bean描述信息
    AnnotationConfigUtils.processCommonDefinitionAnnotations(abd);

    // beanName和AnnotatedGenericBeanDefinition 进行绑定
    BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(abd, beanName);

    //注册,最终会调用DefaultListableBeanFactory中的registerBeanDefinition方法去注册,
    BeanDefinitionReaderUtils.registerBeanDefinition(definitionHolder, this.registry);
}


// 五、AnnotationConfigUtils类 #registerBeanDefinition
// 拿到**配置类的所有bean定义信息**,调用registry去注册,如果有别名,还支持别名继续注册
public static void registerBeanDefinition(
    BeanDefinitionHolder definitionHolder, BeanDefinitionRegistry registry) {

    // 获取beanName
    String beanName = definitionHolder.getBeanName();

    // 让 beanFactory 注册bean咯~~~~
    registry.registerBeanDefinition(beanName, definitionHolder.getBeanDefinition());

    // 别名注册,是通过 alias 与 beanName 绑定进行注册
    // 有一个Map<alias,beanName> 存放这些
    String[] aliases = definitionHolder.getAliases();
    if (aliases != null) {
        for (String alias : aliases) {
            registry.registerAlias(beanName, alias);
        }
    }
}

// 六、DefaultListableBeanFactory类 #registerBeanDefinition
// 将bean定义推入BeanDefinitionMap 和 List
public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition) {
    //这里就是把beanName作为key,ScopedProxyMode作为value,推到map里面
    this.beanDefinitionMap.put(beanName, beanDefinition);

    //beanDefinitionNames就是一个List<String>,这里就是把beanName放到List中去
    this.beanDefinitionNames.add(beanName);
}

总结:

  • register(annotatedClasses)仅仅是将配置类annotatedClasses,注册到BeanDefinitionMap中,没有将他实例化,然后放入单例池

  • 只是把原料放进了map,没有拉进工厂生产

流程:

  1. 传入Class
  2. 读取,封装为AnnotatedGenericBeanDefinition
  3. 转换为BeanDefinition
  4. 放入Map

小总结:

​ **this()register(annotatedClasses)**做的事情差不多

  • 他们都是将类注册为BeanDefinition,提供原材料给**refresh()**方法
  • this()针对的对象是注解配置类;而register(annotatedClasses)针对的对象是传入的参数annotatedClasses => 配置类
  • 他们将类注册为 BeanDefinition基础都是reader对象,只有reader对象能将类注册为BeanDefinition

refresh()方法后面在分析

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值