spring IOC源码分析

IoC 容器理念:通过容器将对象的构建方式统一,并且自动维护对象的依赖关系。由 IoC
容器帮对象找相应的依赖对象并注入,而不是由对象主动去找。

首先容器创建的源码入口

@Test
	public void test2(){
		// java Configuration
		AnnotationConfigApplicationContext context =
				new AnnotationConfigApplicationContext(AppConfig.class);
		context.getBean("test");

	}

创建AnnotationConfigApplicationContext对象

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

先来为构造方法做一个简单的说明:

  1. 这是一个有参的构造方法,可以接收多个配置类,不过一般情况下,只会传入一个配置类。
  2. 这个配置类有两种情况,一种是传统意义上的带上@Configuration注解的配置类,还有一种是没有带上@Configuration,但是带有@Component,@Import,@ImportResouce,@Service,@ComponentScan等注解的配置类,在Spring内部把前者称为Full配置类,把后者称之为Lite配置类。在本源码分析中,有些地方也把Lite配置类称为普通Bean。

使用断点调试,通过this()调用此类无参的构造方法,代码到下面:

public class AnnotationConfigApplicationContext extends GenericApplicationContext implements AnnotationConfigRegistry {

    //注解bean定义读取器,主要作用是用来读取被注解的了bean
    private final AnnotatedBeanDefinitionReader reader;

    //扫描器,它仅仅是在外部手动调用 .scan 等方法才有用,常规方式是不会用到scanner对象的
    private final ClassPathBeanDefinitionScanner scanner;

    /**
     * Create a new AnnotationConfigApplicationContext that needs to be populated
     * through {@link #register} calls and then manually {@linkplain #refresh refreshed}.
     */
    public AnnotationConfigApplicationContext() {
        //会隐式调用父类的构造方法,初始化DefaultListableBeanFactory

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

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

首先无参构造方法中就是对读取器reader和扫描器scanner进行了实例化,reader的类型是AnnotatedBeanDefinitionReader,可以看出它是一个 “打了注解的Bean定义读取器”,scanner的类型是ClassPathBeanDefinitionScanner,它仅仅是在外面手动调用.scan方法,或者调用参数为String的构造方法,传入需要扫描的包名才会用到,像这样方式传入的配置类是不会用到这个scanner对象的。

AnnotationConfigApplicationContext类是有继承关系的,会隐式调用父类的构造方法:

下面代码,初始化DefaultListableBeanFactory

public class GenericApplicationContext extends AbstractApplicationContext implements BeanDefinitionRegistry {

    private final DefaultListableBeanFactory beanFactory;

    @Nullable
    private ResourceLoader resourceLoader;

    private boolean customClassLoader = false;

    private final AtomicBoolean refreshed = new AtomicBoolean();


    /**
     * Create a new GenericApplicationContext.
     * @see #registerBeanDefinition
     * @see #refresh
     */
    public GenericApplicationContext() {
        this.beanFactory = new DefaultListableBeanFactory();
    }
}
DefaultListableBeanFactory是相当重要的,从字面意思就可以看出它是一个Bean的工厂,什么是Bean的工厂?当然就是用来生产和获得Bean的。

把目光回到AnnotationConfigApplicationContext的无参构造方法,看看Spring在初始化AnnotatedBeanDefinitionReader的时候做了什么:

public AnnotatedBeanDefinitionReader(BeanDefinitionRegistry registry) {
	this(registry, getOrCreateEnvironment(registry));
}

这里的BeanDefinitionRegistry当然就是AnnotationConfigApplicationContext的实例了,这里又直接调用了此类其他的构造方法:

public AnnotatedBeanDefinitionReader(BeanDefinitionRegistry registry, Environment environment) {
    Assert.notNull(registry, "BeanDefinitionRegistry must not be null");
    Assert.notNull(environment, "Environment must not be null");
    this.registry = registry;
    this.conditionEvaluator = new ConditionEvaluator(registry, environment, null);
    AnnotationConfigUtils.registerAnnotationConfigProcessors(this.registry);
}

把目光移动到这个方法的最后一行,进入registerAnnotationConfigProcessors方法:

public static void registerAnnotationConfigProcessors(BeanDefinitionRegistry registry) {
    registerAnnotationConfigProcessors(registry, null);
}

这又是一个门面方法,再点进去,这个方法的返回值Set,但是上游方法并没有去接收这个返回值,所以这个方法的返回值也不是很重要了,当然方法内部给这个返回值赋值也不重要了。由于这个方法内容比较多,这里就把最核心的贴出来,这个方法的核心就是注册Spring内置的多个Bean:

if (!registry.containsBeanDefinition(CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME)) {
            RootBeanDefinition def = new RootBeanDefinition(ConfigurationClassPostProcessor.class);
            def.setSource(source);
            beanDefs.add(registerPostProcessor(registry, def, CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME));
}
  1. 判断容器中是否已经存在了ConfigurationClassPostProcessor Bean
  2. 如果不存在(当然这里肯定是不存在的),就通过RootBeanDefinition的构造方法获得ConfigurationClassPostProcessor的BeanDefinition,RootBeanDefinition是BeanDefinition的子类:
  3. 执行registerPostProcessor方法,registerPostProcessor方法内部就是注册Bean,当然这里注册其他Bean也是一样的流程。

BeanDefinition是什么?
它是用来描述Bean的,里面存放着关于Bean的一系列信息,比如Bean的作用域,Bean所对应的Class,是否懒加载,是否Primary等等,这个BeanDefinition也相当重要,以后会常常和它打交道。**

private static BeanDefinitionHolder registerPostProcessor(
        BeanDefinitionRegistry registry, RootBeanDefinition definition, String beanName) {

    definition.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
    registry.registerBeanDefinition(beanName, definition);
    return new BeanDefinitionHolder(definition, beanName);
}

这方法为BeanDefinition设置了一个Role,ROLE_INFRASTRUCTURE代表这是spring内部的,并非用户定义的,然后又调用了registerBeanDefinition方法,再点进去,Oh No,你会发现它是一个接口,没办法直接点进去了,首先要知道registry实现类是什么,那么它的实现是什么呢?答案是DefaultListableBeanFactory:

public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition) throws BeanDefinitionStoreException {
    this.beanFactory.registerBeanDefinition(beanName, beanDefinition);
}

这又是一个门面方法,再点进去,核心在于下面两行代码:

//beanDefinitionMap是Map<String, BeanDefinition>,
//这里就是把beanName作为key,ScopedProxyMode作为value,推到map里面
this.beanDefinitionMap.put(beanName, beanDefinition);

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

从这里可以看出DefaultListableBeanFactory就是所说的容器了,里面放着beanDefinitionMap,beanDefinitionNames,beanDefinitionMap是一个hashMap,beanName作为Key,beanDefinition作为Value,beanDefinitionNames是一个集合,里面存放了beanName。

DefaultListableBeanFactory中的beanDefinitionMap,beanDefinitionNames也是相当重要的,以后会经常看到它,最好看到它,第一时间就可以反应出它里面放了什么数据
这里仅仅是注册,可以简单的理解为把一些原料放入工厂,工厂还没有真正的去生产。
上面已经介绍过,这里会一连串注册好几个Bean,在这其中最重要的一个Bean(没有之一)就是BeanDefinitionRegistryPostProcessor Bean。
ConfigurationClassPostProcessor实现BeanDefinitionRegistryPostProcessor接口,BeanDefinitionRegistryPostProcessor接口又扩展了BeanFactoryPostProcessor接口,BeanFactoryPostProcessor是Spring的扩展点之一,ConfigurationClassPostProcessor是Spring极为重要的一个类,必须牢牢的记住上面所说的这个类和它的继承关系。
除了注册了ConfigurationClassPostProcessor,还注册了其他Bean,其他Bean也都实现了其他接口,比如BeanPostProcessor等。
BeanPostProcessor接口也是Spring的扩展点之一。
至此,实例化AnnotatedBeanDefinitionReader reader分析完毕。
由于常规使用方式是不会用到AnnotationConfigApplicationContext里面的scanner的,所以这里就不看scanner是如何被实例化的了。
把目光回到最开始,再分析第二行代码:

register(annotatedClasses);

这里传进去的是一个数组,最终会循环调用如下方法:

<T> void doRegisterBean(Class<T> annotatedClass, @Nullable Supplier<T> instanceSupplier, @Nullable String name,
        @Nullable Class<? extends Annotation>[] qualifiers, BeanDefinitionCustomizer... definitionCustomizers) {
    //AnnotatedGenericBeanDefinition可以理解为一种数据结构,是用来描述Bean的,这里的作用就是把传入的标记了注解的类
    //转为AnnotatedGenericBeanDefinition数据结构,里面有一个getMetadata方法,可以拿到类上的注解
    AnnotatedGenericBeanDefinition abd = new AnnotatedGenericBeanDefinition(annotatedClass);

    //判断是否需要跳过注解,spring中有一个@Condition注解,当不满足条件,这个bean就不会被解析
    if (this.conditionEvaluator.shouldSkip(abd.getMetadata())) {
        return;
    }

    abd.setInstanceSupplier(instanceSupplier);

    //解析bean的作用域,如果没有设置的话,默认为单例
    ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(abd);
    abd.setScope(scopeMetadata.getScopeName());

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

    //解析通用注解,填充到AnnotatedGenericBeanDefinition,解析的注解为Lazy,Primary,DependsOn,Role,Description
    AnnotationConfigUtils.processCommonDefinitionAnnotations(abd);

    //限定符处理,不是特指@Qualifier注解,也有可能是Primary,或者是Lazy,或者是其他(理论上是任何注解,这里没有判断注解的有效性),如果在外面,以类似这种
    //AnnotationConfigApplicationContext annotationConfigApplicationContext = new AnnotationConfigApplicationContext(Appconfig.class);常规方式去初始化spring,
    //qualifiers永远都是空的,包括上面的name和instanceSupplier都是同样的道理
    //但是spring提供了其他方式去注册bean,就可能会传入了
    if (qualifiers != null) {
        //可以传入qualifier数组,所以需要循环处理
        for (Class<? extends Annotation> qualifier : qualifiers) {
            //Primary注解优先
            if (Primary.class == qualifier) {
                abd.setPrimary(true);
            }
            //Lazy注解
            else if (Lazy.class == qualifier) {
                abd.setLazyInit(true);
            }
            //其他,AnnotatedGenericBeanDefinition有个Map<String,AutowireCandidateQualifier>属性,直接push进去
            else {
                abd.addQualifier(new AutowireCandidateQualifier(qualifier));
            }
        }
    }

    for (BeanDefinitionCustomizer customizer : definitionCustomizers) {
        customizer.customize(abd);
    }

    //这个方法用处不大,就是把AnnotatedGenericBeanDefinition数据结构和beanName封装到一个对象中
    BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(abd, beanName);

    definitionHolder = AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);

    //注册,最终会调用DefaultListableBeanFactory中的registerBeanDefinition方法去注册,
    //DefaultListableBeanFactory维护着一系列信息,比如beanDefinitionNames,beanDefinitionMap
    //beanDefinitionNames是一个List<String>,用来保存beanName
    //beanDefinitionMap是一个Map,用来保存beanName和beanDefinition
    BeanDefinitionReaderUtils.registerBeanDefinition(definitionHolder, this.registry);
}

在这里又要说明下,以常规方式去注册配置类,此方法中除了第一个参数,其他参数都是默认值。

  1. 通过AnnotatedGenericBeanDefinition的构造方法,获得配置类的BeanDefinition,这里是不是似曾相似,在注册ConfigurationClassPostProcessor类的时候,也是通过构造方法去获得BeanDefinition的,只不过当时是通过RootBeanDefinition去获得,现在是通过AnnotatedGenericBeanDefinition去获得。
  2. 判断需不需要跳过注册,Spring中有一个@Condition注解,如果不满足条件,就会跳过这个类的注册。
  3. 然后是解析作用域,如果没有设置的话,默认为单例。
  4. 获得BeanName。
  5. 解析通用注解,填充到AnnotatedGenericBeanDefinition,解析的注解为Lazy,Primary,DependsOn,Role,Description。
  6. 限定符处理,不是特指@Qualifier注解,也有可能是Primary,或者是Lazy,或者是其他(理论上是任何注解,这里没有判断注解的有效性)。
  7. 把AnnotatedGenericBeanDefinition数据结构和beanName封装到一个对象中(这个不是很重要,可以简单的理解为方便传参)。
  8. 注册,最终会调用DefaultListableBeanFactory中的registerBeanDefinition方法去注册:
public static void registerBeanDefinition(
        BeanDefinitionHolder definitionHolder, BeanDefinitionRegistry registry)
        throws BeanDefinitionStoreException {

    //获取beanName
    // Register bean definition under primary name.
    String beanName = definitionHolder.getBeanName();

    //注册bean
    registry.registerBeanDefinition(beanName, definitionHolder.getBeanDefinition());

            //Spring支持别名
    // Register aliases for bean name, if any.
    String[] aliases = definitionHolder.getAliases();
    if (aliases != null) {
        for (String alias : aliases) {
            registry.registerAlias(beanName, alias);
        }
    }
}

这个registerBeanDefinition是不是又有一种似曾相似的感觉,没错,在上面注册Spring内置的Bean的时候,已经解析过这个方法了,这里就不重复了,此时,再观察下beanDefinitionMap beanDefinitionNames两个变量,除了Spring内置的Bean,还有传进来的Bean,这里的Bean当然就是配置类了:
到这里注册配置类也分析完毕了。

大家可以看到其实到这里,Spring还没有进行扫描,只是实例化了一个工厂,注册了一些内置的Bean和传进去的配置类,真正的大头是在第三行代码:

refresh();

进入refresh方法,refresh方法中有一个finishBeanFactoryInitialization小方法,这个方法是用来实例化懒加载单例Bean的,也就是Bean都是在这里被创建出来的(当然我这里说的的是绝大部分情况是这样的):

finishBeanFactoryInitialization(beanFactory);

再进入finishBeanFactoryInitialization这方法,里面有一个beanFactory.preInstantiateSingletons()方法:

//初始化所有的非懒加载单例
beanFactory.preInstantiateSingletons();

尝试再点进去,这个时候你会发现这是一个接口,好在它只有一个实现类,所以可以来到了他的唯一实现,实现类就是org.springframework.beans.factory.support.DefaultListableBeanFactory,这里面是一个循环,Bean就是循环被创建出来的,找到其中的getBean方法:

getBean(beanName);

这里有一个分支,如果Bean是FactoryBean,如何如何,如果Bean不是FactoryBean如何如何,好在不管是不是FactoryBean,最终还是会调用getBean方法,所以可以毫不犹豫的点进去,点进去之后,你会发现,这是一个门面方法,直接调用了doGetBean方法:

return doGetBean(name, null, null, false);

再进去,不断的深入,接近要寻找的东西。
这里面的比较复杂,下一步要进入

if (mbd.isSingleton()) {
    //getSingleton中的第二个参数类型是ObjectFactory<?>,是一个函数式接口,不会立刻执行,而是在
    //getSingleton方法中,调用ObjectFactory的getObject,才会执行createBean
    sharedInstance = getSingleton(beanName, () -> {
        try {
            return createBean(beanName, mbd, args);
        }
        catch (BeansException ex) {
            destroySingleton(beanName);
            throw ex;
        }
    });
    bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
}

这里面的createBean方法,再点进去啊,但是又点不进去了,这是接口啊,但是别慌,这个接口又只有一个实现类,所以说 没事,就是干,这个实现类为org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory。

这个实现的方法里面又做了很多事情,就不去看了,就是带着大家找到那几个生命周期的回调到底定义在哪里就OK了。

Object beanInstance = doCreateBean(beanName, mbdToUse, args);//创建bean,核心
if (logger.isDebugEnabled()) {
    logger.debug("Finished creating instance of bean '" + beanName + "'");
}
return beanInstance;

再继续深入doCreateBean方法,这个方法又做了一堆一堆的事情,但是值得开心的事情就是 已经找到了要寻找的东西了。

首先是创建实例,位于:

instanceWrapper = createBeanInstance(beanName, mbd, args);//创建bean的实例。核心

其次是填充属性,位于:

populateBean(beanName, mbd, instanceWrapper);//填充属性,炒鸡重要

在填充属性下面有一行代码:

exposedObject = initializeBean(beanName, exposedObject, mbd);

继续深入进去。
aware系列接口的回调

invokeAwareMethods(beanName, bean);
private void invokeAwareMethods(final String beanName, final Object bean) {
    if (bean instanceof Aware) {
        if (bean instanceof BeanNameAware) {
            ((BeanNameAware) bean).setBeanName(beanName);
        }
        if (bean instanceof BeanClassLoaderAware) {
            ClassLoader bcl = getBeanClassLoader();
            if (bcl != null) {
                ((BeanClassLoaderAware) bean).setBeanClassLoader(bcl);
            }
        }
        if (bean instanceof BeanFactoryAware) {
            ((BeanFactoryAware) bean).setBeanFactory(AbstractAutowireCapableBeanFactory.this);
        }
    }
}

BeanPostProcessor的postProcessBeforeInitialization方法

if (mbd == null || !mbd.isSynthetic()) {
            wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
        }
    @Override
    public Object applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName)
            throws BeansException {

    Object result = existingBean;
    for (BeanPostProcessor processor : getBeanPostProcessors()) {
        Object current = processor.postProcessBeforeInitialization(result, beanName);
        if (current == null) {
            return result;
        }
        result = current;
    }
    return result;
}

afterPropertiesSet init-method

invokeInitMethods(beanName, wrappedBean, mbd);

这里面调用了两个方法,一个是afterPropertiesSet方法,一个是init-method方法:

((InitializingBean) bean).afterPropertiesSet();
invokeCustomInitMethod(beanName, bean, mbd);

BeanPostProcessor的postProcessAfterInitialization方法

if (mbd == null || !mbd.isSynthetic()) {
            wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
        }
	public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName)
        throws BeansException {

    Object result = existingBean;
    for (BeanPostProcessor processor : getBeanPostProcessors()) {
        Object current = processor.postProcessAfterInitialization(result, beanName);
        if (current == null) {
            return result;
        }
        result = current;
    }
    return result;
}

这就是广为流传的Spring Bean的生命周期。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
提供的码资涵盖了安卓应用、小程序、Python应用和Java应用等多个领域,每个领域都包含了丰富的实例和项目。这些码都是基于各自平台的最新技术和标准编写,确保了在对应环境下能够无缝运行。同时,码中配备了详细的注释和文档,帮助用户快速理解代码结构和实现逻辑。 适用人群: 这些码资特别适合大学生群体。无论你是计算机相关专业的学生,还是对其他领域编程感兴趣的学生,这些资都能为你提供宝贵的学习和实践机会。通过学习和运行这些码,你可以掌握各平台开发的基础知识,提升编程能力和项目实战经验。 使用场景及目标: 在学习阶段,你可以利用这些码资进行课程实践、课外项目或毕业设计。通过分析和运行码,你将深入了解各平台开发的技术细节和最佳实践,逐步培养起自己的项目开发和问题解决能力。此外,在求职或创业过程中,具备跨平台开发能力的大学生将更具竞争力。 其他说明: 为了确保码资的可运行性和易用性,特别注意了以下几点:首先,每份码都提供了详细的运行环境和依赖说明,确保用户能够轻松搭建起开发环境;其次,码中的注释和文档都非常完善,方便用户快速上手和理解代码;最后,我会定期更新这些码资,以适应各平台技术的最新发展和市场需求。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值