Spring IOC----容器刷新(refresh())之前

Posted nijunyang

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Spring IOC----容器刷新(refresh())之前相关的知识,希望对你有一定的参考价值。

首先本次分析是基于注解形式的,想来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不会马上被初始化了

技术图片

 

以上是关于Spring IOC----容器刷新(refresh())之前的主要内容,如果未能解决你的问题,请参考以下文章

spring IOC容器的扩展

Spring源码分析之-加载IOC容器

03.Spring IoC 容器 - 初始化

图解spring3-IoC与AOP

Spring IOC----如何注册bean定义

初识Spring