Spring IOC 源码一

前言
createBean的方式
getBean
  • getSingleton
  •  createBean
  • initializeBean

总结



前言

    

   停更三个多月了,哈哈哈。前几天大佬要我给他们小组做个ioc的分享,才想起来,之前一直想梳理一篇ioc的内容,隔了这么久,源码又有点生疏了。今天是1024程序员节,带大家再复习一下ioc。

1.createBean的方式


在讲IOC原理之前,我们先看看spring 创建bean有哪些方式,对于后面大家理解ioc源码有一定的帮助

1.1  <bean/>标签

        这是我们接触spring时最开始的用法。


 /**
     * <bean/>--》Spring bean
     */
    private static void method1() {
        ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring.xml");
        User user = applicationContext.getBean("user", User.class);
        System.out.println(user);
    }

spring.xml

Spring IOC 源码一

1.2 @Bean

这种在configuration配置类中最常见。

public class BeanConfig {

    @Bean
    public User user(){
        return new User();
    }
}
    /**
     * @Bean --》Spring bean
     */
    private static void method2() {
        AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(BeanConfig.class);
        User user = applicationContext.getBean("user", User.class);
        System.out.println(user);
    }

1.3 @Component

    这种和@Bean很类似


先定义bean

@Component
public class User {
    private String name;
    private String age;
}

再配置扫描bean的类路径

    @ComponentScan("com.windy.createBean")
    public class BeanConfig {

    }


获取bean

    /**
     * @Component-->Spring bean
     */
    private static void method3() {
        AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(BeanConfig.class);
        User user = applicationContext.getBean("user", User.class);
        System.out.println(user);
    }


@Bean和@Component的区别是,一个配置类中通过 @Bean方式定义bean,一个在bean的类上加上@Componet注解,然后在配置类上配置包扫描路径。

上面三种方式都是声明式的定义bean,这也是我们经常用的。
        spring还有一种编程式定义bean的方式。这是最接近底层源码的一种方式。类似aop,transaction。spring都提供了两种方式来让大家使用。

1.4 beanDefinition

我们知道spring 的ioc主要分为两个阶段,1.beanDefinition ->容器的初始化阶段2.getBean的阶段。
       容器的初始化阶段又分为

资源的定位:用外部资源来描述bean对象;

装载:BeanDefinitionReader 读取、解析 Resource 资源,也就是将用户定义的 Bean 表示成 IoC 容器的内部数据结构:BeanDefinition;

注册:将第二步解析好的 BeanDefinition注册到一个 IOC 容器内部的一个HashMap 容器中。

这里就不带大家看这部分的源码了。大家感兴趣可以自己看看。


    /**
     * beanDefinition -->bean
     */
    private static void method4() {
        AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext();
        AbstractBeanDefinition beanDefinition = BeanDefinitionBuilder.genericBeanDefinition().getBeanDefinition();
        beanDefinition.setBeanClass(User.class);
        applicationContext.registerBeanDefinition("user",beanDefinition);
        //refresh能否去掉?
        applicationContext.refresh();
        User user = applicationContext.getBean("user", User.class);
        System.out.println(user);
    }


这里application.refresh()能否去掉?



答案:不能。如果去掉了,这里就获取不到user bean对象了。


我们可以注意到这里获取AnnotationConfigApplicationContext是无参构造,而前面声明式获取bean里面都有一个配置类。我们对比一下二者的区别。


声明式:

    public AnnotationConfigApplicationContext(String... basePackages) {
        this();
        scan(basePackages);
        refresh();
    }


编程式:

    public AnnotationConfigApplicationContext() {
        StartupStep createAnnotatedBeanDefReader = this.getApplicationStartup().start("spring.context.annotated-bean-reader.create");
        this.reader = new AnnotatedBeanDefinitionReader(this);
        createAnnotatedBeanDefReader.end();
        this.scanner = new ClassPathBeanDefinitionScanner(this);
    }


    对比二者构造方式的不同,我们可以看到编程式无参构造少了一个refresh方法。这个refresh方法便是spring最核心的方法。这里就不再重复介绍refresh做了啥。前面讲springboot源码有详细介绍。SpringBoot启动原理这里借用之前画的图带大家再复习一下。


Spring IOC 源码一

1.5 factoryBean

     factoryBean 和beanFactory的区别?

    一个是以Bean结尾,落脚点在bean,一个是以factory结尾,落脚点是factory 。factoryBean在很多源码中都有看到过它的身影。如前面介绍的FeignClient的创建。


    /**
     * factoryBean
     *也可以用声明式 @Component等
     */
    private static void method5() {
        AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext();
        AbstractBeanDefinition beanDefinition = BeanDefinitionBuilder.genericBeanDefinition().getBeanDefinition();
        /**
         * 会生成2个bean 对象
         *
         * 1:@user:WindyFactoryBean
         * 2: user:person
         */
        beanDefinition.setBeanClass(WindyFactoryBean.class);
        applicationContext.registerBeanDefinition("user",beanDefinition);
        //refresh能否去掉?
        applicationContext.refresh();
        WindyFactoryBean user1 = applicationContext.getBean("&user", WindyFactoryBean.class);
        WindyFactoryBean.Person user2 = applicationContext.getBean("
user", WindyFactoryBean.Person.class);
        System.out.println(user1);
        System.out.println(user2);
    }


当使用factoryBean创建对象时,会生成两个bean对象,一个是factoryBean对象 ,beanName会有一个@符号。还有一个是factoryBean包裹的bean。

       关于factoryBean的源码后面讲IOC时一并再讲。


1.6 supplier

前面两种编程式创建Bean,都是通过registerBeanDefinition的方式把bean交给Spring容器管理。还有一种通过registerBean直接把创建好的bean交给Spring。
    /**
     * supplier 方式
     */
    private static void method6() {
        AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext();
        //applicationContext.registerBean(User.class);
        applicationContext.registerBean(User.class, new Supplier<User>() {
            @Override
            public User get() {
                User user = new User();
                user.setName("windy");
                return user;
            }
        });
        //refresh能否去掉?
        applicationContext.refresh();
        User user = applicationContext.getBean("user", User.class);
        System.out.println(user.getName());
    }


supplier是jDK 8 提供的一种函数式编程方式。当前这里也可以直接传入创建好的bean.
     通过看源码,其实registerBean最终也是调用的registerBeanDefinition
    public <T> void registerBean(@Nullable String beanName, Class<T> beanClass,
            @Nullable Supplier<T> supplier, BeanDefinitionCustomizer... customizers) {

        ClassDerivedBeanDefinition beanDefinition = new ClassDerivedBeanDefinition(beanClass);
        if (supplier != null) {
            beanDefinition.setInstanceSupplier(supplier);
        }
        for (BeanDefinitionCustomizer customizer : customizers) {
            customizer.customize(beanDefinition);
        }

        String nameToUse = (beanName != null ? beanName : beanClass.getName());
        registerBeanDefinition(nameToUse, beanDefinition);
    }


2.getBean


在讲ioc源码前,我们先简单看下整个ioc会有哪些步骤。


Spring IOC 源码一


简单跑一下demo工程


Spring IOC 源码一


可以看到ioc的基本流程如下。


Spring IOC 源码一


接下来具体讲解该整个流程。


 main 方法

    public static void main(String[] args) {

        //创建一个spring容器
        AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(IocConfig.class);
        HelloService helloService = applicationContext.getBean("helloService", HelloService.class);
        helloService.sayHello();
    }
当执行applicationContext.getBean(“helloService”, HelloService.class)时,到底发生了什么,我们直接点进去看源码。

贴的代码有部分删除


   
    protected <T> T doGetBean(final String name, @Nullable final Class<T> requiredType,
            @Nullable final Object[] args, boolean typeCheckOnly) throws BeansException {
        //
        final String beanName = transformedBeanName(name);
        Object bean;

        // Eagerly check singleton cache for manually registered singletons.
        //
        Object sharedInstance = getSingleton(beanName);
        if (sharedInstance != null && args == null) {
            if (logger.isDebugEnabled()) {
                if (isSingletonCurrentlyInCreation(beanName)) {
                    logger.debug("Returning eagerly cached instance of singleton bean '" + beanName +
                            "' that is not fully initialized yet - a consequence of a circular reference");
                }
                else {
                    logger.debug("Returning cached instance of singleton bean '" + beanName + "'");
                }
            }
            bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
        }

        else {

            /**
             * containsBeanDefinition 中存在 beanName 相对应的 BeanDefinition
             */
            try {
                /**
                 * 合并父类相关属性
                 */
                final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
                checkMergedBeanDefinition(mbd, beanName, args);

                // Guarantee initialization of beans that the current bean depends on.
                /**
                 * 获取依赖。
                 * 在初始化 bean 时解析 depends-on 标签时设置
                 */
                String[] dependsOn = mbd.getDependsOn();
                if (dependsOn != null) {
                    // 迭代依赖
                    for (String dep : dependsOn) {
                        // 检验依赖的bean 是否已经注册给当前 bean
                        // 获取其他传递依赖bean
                        if (isDependent(beanName, dep)) {
                            throw new BeanCreationException(mbd.getResourceDescription(), beanName,
                                    "Circular depends-on relationship between '" + beanName + "' and '" + dep + "'");
                        }
                        //没有注册到依赖bean中
                        // 注册到依赖bean中
                        registerDependentBean(dep, beanName);
                        try {
                            // 调用 getBean 初始化依赖bean
                            getBean(dep);
                        }
                        catch (NoSuchBeanDefinitionException ex) {
                            throw new BeanCreationException(mbd.getResourceDescription(), beanName,
                                    "'" + beanName + "' depends on missing bean '" + dep + "'", ex);
                        }
                    }
                }

                // Create bean instance.
                if (mbd.isSingleton()) {
                    //
                    sharedInstance = getSingleton(beanName, () -> {
                        try {
                            /**
                             * beanName:bean 的名字
                             * mbd:已经合并了父类属性的(如果有的话)BeanDefinition
                             * args:用于构造函数或者工厂方法创建 bean 实例对象的参数
                             */
                             //
                            return createBean(beanName, mbd, args);
                        }
                        catch (BeansException ex) {
                            // Explicitly remove instance from singleton cache: It might have been put there
                            // eagerly by the creation process, to allow for circular reference resolution.
                            // Also remove any beans that received a temporary reference to the bean.
                            destroySingleton(beanName);
                            throw ex;
                        }
                    });
                    bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
                }

            
        }

        return (T) bean;
    }


❶处transformedBeanName主要是统一格式化处理beanName

比如前面factoryBean demo中通过applicationContext.getBean(“&user“, WindyFactoryBean.class)获取factoryBean,我们传入的name是&user,在这里会转成user,可能有人问,变成user,那和factoryBean包裹的bean的name不就一样了。这个时候你忘了一个细节,所有bean的信息都维护在BeanDefinition里,后面代码会判断是否是factoryBean.


2.1 getSingleton(

   我们知道spring会维护单例bean的生命周期,当getBean时会先从单例池里判断是否已经创建过了。

  #DefaultSingletonBeanRegistry.class
  public Object getSingleton(String beanName) {
        return getSingleton(beanName, true);
    }

接着

注意这里传入了一个true,这个方法在正在ioc过程中会调用几次。true表示允许对象提前暴露,主要用在处理循环依赖。

  #DefaultSingletonBeanRegistry.class
protected Object getSingleton(String beanName, boolean allowEarlyReference) {
        //
        Object singletonObject = this.singletonObjects.get(beanName);
        // 缓存中的 bean 为空,且当前 bean 正在创建
        if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
            //加锁保证 二级缓存添加和三级缓存删除操作的原子性,同时二级缓存和三级缓存就没有必要用concurrentHashMap了
            synchronized (this.singletonObjects) {  
                // 从 earlySingletonObjects 获取
                singletonObject = this.earlySingletonObjects.get(beanName);
                // earlySingletonObjects 中没有,且允许提前创建
                if (singletonObject == null && allowEarlyReference) {
                    // 从 singletonFactories 中获取对应的 ObjectFactory
                    /**
                     * allowEarlyReference:从字面意思上面理解就是允许提前拿到引用。
                     * 其实真正的意思是是否允许从 singletonFactories 缓存中通过 getObject() 拿到对象,为什么会有这样一个字段呢?
                     * 原因就在于 singletonFactories 才是 Spring 解决 singleton bean 的诀窍所在
                     */
                    ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
                    // ObjectFactory 不为空,则创建 bean
                    if (singletonFactory != null) {
                        singletonObject = singletonFactory.getObject();//类似回调覆盖 执行lambda 表达式   AOP
                        this.earlySingletonObjects.put(beanName, singletonObject);//三级缓存升到二级缓存
                        this.singletonFactories.remove(beanName);
                    }
                }
            }
        }
        return singletonObject;
    }


    我们知道spring主要通过map来管理单例bean的,在创建单例bean的时候涉及到三级缓存:

Spring IOC 源码一


一级缓存 singletonObjects:bean name –> bean instance
二级缓存earlySingletonObjects:bean name –> bean instance,不一定完整
三级缓存 singletonFactories :bean name –> ObjectFactory

可以注意到除了一级缓存用的是concurrentHashMap外,其他两个缓存都是用的hashmap,原因在注释中已说明。


这里我们第一次获取bean,此时bean还标识为创建中,所以第一个判断条件不满足,直接返回null。

2.2 getSingleton(

接下来调用重载的getSingleton方法创建Bean,不同于第步中的getSingleton


#DefaultSingletonBeanRegistry.class
public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) {
        Assert.notNull(beanName, "Bean name must not be null");
        //全局加锁
        synchronized (this.singletonObjects) {
            // 从缓存中检查一遍
            //因为 singleton 模式其实就是复用已经创建的 bean 所以这步骤必须检查
            Object singletonObject = this.singletonObjects.get(beanName);
            //  为空,开始加载过程
            if (singletonObject == null) {
                if (this.singletonsCurrentlyInDestruction) {
                    throw new BeanCreationNotAllowedException(beanName,
                            "Singleton bean creation not allowed while singletons of this factory are in destruction " +
                            "(Do not request a bean from a BeanFactory in a destroy method implementation!)");
                }
            
                //加载前置处理,将bean的状态修改为正在创建中
                beforeSingletonCreation(beanName);
                boolean newSingleton = false;
                boolean recordSuppressedExceptions = (this.suppressedExceptions == null);
                if (recordSuppressedExceptions) {
                    this.suppressedExceptions = new LinkedHashSet<>();
                }
                try {
                    // 初始化 bean
                    // 这个过程其实是调用 createBean() 方法
                    singletonObject = singletonFactory.getObject();
                    newSingleton = true;
                }
                finally {
                    if (recordSuppressedExceptions) {
                        this.suppressedExceptions = null;
                    }
                    // 后置处理,将bean的状态从正在创建中移除
                    afterSingletonCreation(beanName);
                }
                // 加入缓存中
                if (newSingleton) {
                    /**
                     * 一级缓存添加
                     */
                    addSingleton(beanName, singletonObject);
                }
            }
            return singletonObject;
        }
    }
      


❶ 依旧从一级缓存singletonObjects中获取bean,此时也还是null.

beforeSingletonCreation


  #DefaultSingletonBeanRegistry.class
    protected void beforeSingletonCreation(String beanName) {
        if (!this.inCreationCheckExclusions.contains(beanName) && !this.singletonsCurrentlyInCreation.add(beanName)) {
            throw new BeanCurrentlyInCreationException(beanName);
        }
    }


这里会将beanName维护在Set<String> singletonsCurrentlyInCreation =Collections.newSetFromMap(new ConcurrentHashMap<>(16))集合中,我们在回头看第二步getSingleton(❷),当下次再调用getSingleton(❷)这个方法时,第一个条件singletonObject == null && isSingletonCurrentlyInCreation(beanName)则为真了,我们接着往下看。

❸singletonFactory.getObject()

这是一个函数回调接口实际上调用的是doGetBean中的createBean方法。


3.CreateBean


    #AbstractAutowireCapableBeanFactory.class
    @Override
    protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
            throws BeanCreationException {

        RootBeanDefinition mbdToUse = mbd;
        Class<?> resolvedClass = resolveBeanClass(mbd, beanName);
        if (resolvedClass != null && !mbd.hasBeanClass() && mbd.getBeanClassName() != null) {
            mbdToUse = new RootBeanDefinition(mbd);
            mbdToUse.setBeanClass(resolvedClass);
        }
        // Prepare method overrides.
        // 验证和准备覆盖方法
        try {
            mbdToUse.prepareMethodOverrides();
        }

        try {
            // Give BeanPostProcessors a chance to return a proxy instead of the target bean instance.
            //给 BeanPostProcessors 一个机会用来返回一个代理类而不是真正的类实例,如aop
            Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
            //如果代理对象不为空,则直接返回代理对象,
            //这一步骤有非常重要的作用,Spring 后续实现 AOP 就是基于这个地方判断的。
            if (bean != null) {
                return bean;
            }
        }
        
        try {
            //执行真正创建 bean 的过程
            Object beanInstance = doCreateBean(beanName, mbdToUse, args);
            return beanInstance;
        }
        
    }


3.1 resolveBeforeInstantiation

实例化的前置处理

    
    #AbstractAutowireCapableBeanFactory.class
    protected Object resolveBeforeInstantiation(String beanName, RootBeanDefinition mbd) {
        Object bean = null;
        if (!Boolean.FALSE.equals(mbd.beforeInstantiationResolved)) {
            // Make sure bean class is actually resolved at this point.
            if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
                Class<?> targetType = determineTargetType(beanName, mbd);
                if (targetType != null) {
                    //实例化前置处理
                    bean = applyBeanPostProcessorsBeforeInstantiation(targetType, beanName);
                    if (bean != null) {
                        //初始化后置处理
                        bean = applyBeanPostProcessorsAfterInitialization(bean, beanName);
                    }
                }
            }
            mbd.beforeInstantiationResolved = (bean != null);
        }
        return bean;
    }


applyBeanPostProcessorsBeforeInstantiation

    @Nullable
    protected Object applyBeanPostProcessorsBeforeInstantiation(Class<?> beanClass, String beanName) {
        for (BeanPostProcessor bp : getBeanPostProcessors()) {
            if (bp instanceof InstantiationAwareBeanPostProcessor) {
                InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
                Object result = ibp.postProcessBeforeInstantiation(beanClass, beanName);
                if (result != null) {
                    return result;
                }
            }
        }
        return null;
    }


  这是spring的一个扩展接口,如果有我们有实现InstantiationAwareBeanPostProcessor类,则会调用
该前置处理是针对所有的bean,如果我们定义InstantiationAwareBeanPostProcessor,要确定好影响范围。

如:

Spring IOC 源码一


可以看到如果返回不为空,则接着做实例化后置处理后直接返回,就不会走ioc后续的流程了。

前面一篇讲aop有讲过

public abstract class AbstractAutoProxyCreator extends ProxyProcessorSupport
        implements SmartInstantiationAwareBeanPostProcessor, BeanFactoryAware {
        
    @Override
    public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) {
        //构建我们的缓存key
        Object cacheKey = getCacheKey(beanClass, beanName);

        if (!StringUtils.hasLength(beanName) || !this.targetSourcedBeans.contains(beanName)) {
            //如果被解析过直接返回
            //
            if (this.advisedBeans.containsKey(cacheKey)) {
                return null;
            }
             /**
             * 判断是不是基础的Bean(Advice、PointCut、Advisor、AopInfrastructureBean)是就直接跳过
             * 判断是不是应该跳过 (AOP解析直接解析出我们的切面信息(并且把我们的切面信息进行缓存),而事务在这里是不会解析的)
             */
             //
            if (isInfrastructureClass(beanClass) || shouldSkip(beanClass, beanName)) {
                this.advisedBeans.put(cacheKey, Boolean.FALSE);
                return null;
            }
        }

        //
        TargetSource targetSource = getCustomTargetSource(beanClass, beanName);
        if (targetSource != null) {
            if (StringUtils.hasLength(beanName)) {
                this.targetSourcedBeans.add(beanName);
            }
            Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(beanClass, beanName, targetSource);
            Object proxy = createProxy(beanClass, beanName, specificInterceptors, targetSource);
            this.proxyTypes.put(cacheKey, proxy.getClass());
            return proxy;
        }

        return null;
    }
如果我们 实现TargetSource接口,来提前生成aop,则不会走createBean后续步骤了。

3.2 doCreateBean

接下来是真正创建bean的步骤。


protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final @Nullable Object[] args)
            throws BeanCreationException {

        // Instantiate the bean.
        // BeanWrapper是对Bean的包装,其接口中所定义的功能很简单包括设置获取被包装的对象,获取被包装bean的属性描述器
        BeanWrapper instanceWrapper = null;
        // 单例模型,则从未完成的 FactoryBean 缓存中删除
        if (mbd.isSingleton()) {
            instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
        }
        // 使用合适的实例化策略来创建新的实例:工厂方法、构造函数自动注入、简单初始化
        if (instanceWrapper == null) {
            instanceWrapper = createBeanInstance(beanName, mbd, args);
        }
        // 包装的实例对象
        final Object bean = instanceWrapper.getWrappedInstance();
        // 包装的实例对象的类型
        Class<?> beanType = instanceWrapper.getWrappedClass();
        if (beanType != NullBean.class) {
            mbd.resolvedTargetType = beanType;
        }


        // 如果有后置处理,则允许后置处理修改 BeanDefinition
        synchronized (mbd.postProcessingLock) {
            if (!mbd.postProcessed) {
                try {
                    // applyMergedBeanDefinitionPostProcessors
                    //调用属性合并后置处理器, 进行属性合并
                    //这里会进行 一些注解 的扫描
                    //CommonAnnotationBeanPostProcessor -> @PostConstruct @PreDestroy @Resource
                    //AutowiredAnnotationBeanPostProcessor -> @Autowired @Value
                    applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
                }
                mbd.postProcessed = true;
            }
        }

        // 解决单例模式的循环依赖
        // 单例模式 & 运行循环依赖&当前单例 bean 是否正在被创建
        boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
                isSingletonCurrentlyInCreation(beanName));

        if (earlySingletonExposure) {
            // 提前将创建的 bean 实例加入到三级缓存singletonFactories
            // 这里是为了后期避免循环依赖
            addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
        }

        Object exposedObject = bean;
        try {
            //对 bean 进行填充,将各个属性值注入,其中,可能存在依赖于其他 bean 的属性
            // 则会递归初始依赖 bean
            populateBean(beanName, mbd, instanceWrapper);
            //调用初始化方法
            exposedObject = initializeBean(beanName, exposedObject, mbd);
        }
        
        /**
         * 循环依赖处理
         * Spring 循环依赖的场景有两种:
         * 构造器的循环依赖
         * field 属性的循环依赖
         * 对于构造器的循环依赖,Spring 是无法解决的,只能抛出 BeanCurrentlyInCreationException 异常表示循环依赖
         */

        if (earlySingletonExposure) {
            // 获取 earlySingletonReference
            Object earlySingletonReference = getSingleton(beanName, false);
            // 只有在存在循环依赖的情况下,earlySingletonReference 才不会为空
            if (earlySingletonReference != null) {
                // 如果 exposedObject 没有在初始化方法中被改变,也就是没有被增强
                if (exposedObject == bean) {
                    exposedObject = earlySingletonReference;
                }
                // 处理依赖
                else if (!this.allowRawInjectionDespiteWrapping && hasDependentBean(beanName)) {
                    String[] dependentBeans = getDependentBeans(beanName);
                    Set<String> actualDependentBeans = new LinkedHashSet<>(dependentBeans.length);
                    for (String dependentBean : dependentBeans) {
                        if (!removeSingletonIfCreatedForTypeCheckOnly(dependentBean)) {
                            actualDependentBeans.add(dependentBean);
                        }
                    }
                    
                }
            }
        }

        // Register bean as disposable.
        try {
            // 注册 bean
            registerDisposableBeanIfNecessary(beanName, bean, mbd);
        }
        return exposedObject;
    }


❶createBeanInstance


protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) {
        // 解析 bean,将 bean 类名解析为 class 引用
        Class<?> beanClass = resolveBeanClass(mbd, beanName);

        // 如果存在 Supplier 回调,则使用给定的回调方法初始化策略
        Supplier<?> instanceSupplier = mbd.getInstanceSupplier();
        if (instanceSupplier != null) {
            return obtainFromSupplier(instanceSupplier, beanName);
        }

        // 如果工厂方法不为空,则使用工厂方法初始化策略
        if (mbd.getFactoryMethodName() != null)  {
            return instantiateUsingFactoryMethod(beanName, mbd, args);
        }

        // Shortcut when re-creating the same bean...
        boolean resolved = false;
        boolean autowireNecessary = false;
        if (args == null) {
            synchronized (mbd.constructorArgumentLock) {
                // 如果已缓存的解析的构造函数或者工厂方法不为空,则可以利用构造函数解析
                if (mbd.resolvedConstructorOrFactoryMethod != null) {
                    resolved = true;
                    autowireNecessary = mbd.constructorArgumentsResolved;
                }
            }
        }
        // 已经解析好了,直接注入即可
        if (resolved) {
            if (autowireNecessary) {
                // 自动注入,调用构造函数自动注入
                return autowireConstructor(beanName, mbd, null, null);
            }
            else {
                // 使用默认构造函数构造
                return instantiateBean(beanName, mbd);
            }
        }

        // Need to determine the constructor...
        // 确定解析的构造函数
        // 主要是检查已经注册的 SmartInstantiationAwareBeanPostProcessor
        Constructor<?>[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName);
        if (ctors != null ||
                mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_CONSTRUCTOR ||
                mbd.hasConstructorArgumentValues() || !ObjectUtils.isEmpty(args))  {
            // 构造函数自动注入
            return autowireConstructor(beanName, mbd, ctors, args);
        }

        // No special handling: simply use no-arg constructor.
        //使用默认构造函数注入
        return instantiateBean(beanName, mbd);
    }

如果我们不做其他处理,默认使用无参构造函数初始化对象。


❷applyMergedBeanDefinitionPostProcessors

这里会有一些注解的扫描,详见@Autowied原理


❸addSingletonFactory


提前将创建的 bean 实例加入到singletonFactories 中,注意添加的是一个函数式接口,() -> getEarlyBeanReference(beanName, mbd, bean)。


    protected Object getEarlyBeanReference(String beanName, RootBeanDefinition mbd, Object bean) {
        Object exposedObject = bean;
        if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
            for (BeanPostProcessor bp : getBeanPostProcessors()) {
                if (bp instanceof SmartInstantiationAwareBeanPostProcessor) {
                    SmartInstantiationAwareBeanPostProcessor ibp = (SmartInstantiationAwareBeanPostProcessor) bp;
                    exposedObject = ibp.getEarlyBeanReference(exposedObject, beanName);
                }
            }
        }
        return exposedObject;
    }

继续看addSingletonFactory


    #DefaultSingletonBeanRegistry.class
    protected void addSingletonFactory(String beanName, ObjectFactory<?> singletonFactory) {
        Assert.notNull(singletonFactory, "Singleton factory must not be null");
        synchronized (this.singletonObjects) {
            if (!this.singletonObjects.containsKey(beanName)) {
                this.earlySingletonObjects.remove(beanName);
                this.singletonFactories.put(beanName, singletonFactory);
                this.registeredSingletons.add(beanName);
            }
        }
    }


放入三级缓存。三级缓存singletonFactories是解决循环依赖的关键所在。

同时这段代码发生在 createBeanInstance() 方法之后,也就是说这个 bean 其实已经被创建出来了,但是它还不是很完美(没有进行属性填充和初始化)

,但是对于其他依赖它的对象而言已经足够了(可以根据对象引用定位到堆中对象),能够被认出来了。


3.3 populateBean 属性填充


protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) {
    
        /**
         * 在设置属性之前给 InstantiationAwareBeanPostProcessors 最后一次改变 bean 的机会
         */
        boolean continueWithPropertyPopulation = true;
    
        // 是否持有 InstantiationAwareBeanPostProcessor
        if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
            for (BeanPostProcessor bp : getBeanPostProcessors()) {
                if (bp instanceof InstantiationAwareBeanPostProcessor) {
                    InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
                    if (!ibp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) {
                        continueWithPropertyPopulation = false;
                        break;
                    }
                }
            }
        }
        // 如果后续处理器发出停止填充命令,则终止后续操作
        if (!continueWithPropertyPopulation) {
            return;
        }
        // bean 的属性值
        PropertyValues pvs = (mbd.hasPropertyValues() ? mbd.getPropertyValues() : null);

        if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_NAME ||
                mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_TYPE) {
            // 将 PropertyValues 封装成 MutablePropertyValues 对象
            // MutablePropertyValues 允许对属性进行简单的操作,
            // 并提供构造函数以支持Map的深度复制和构造。
            MutablePropertyValues newPvs = new MutablePropertyValues(pvs);

            // Add property values based on autowire by name if applicable.
            // 根据名称自动注入
            if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_NAME) {
                autowireByName(beanName, mbd, bw, newPvs);
            }

            // Add property values based on autowire by type if applicable.
            // 根据类型自动注入
            if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_TYPE) {
                autowireByType(beanName, mbd, bw, newPvs);
            }

            pvs = newPvs;
        }
        // 是否已经注册了 InstantiationAwareBeanPostProcessors
        boolean hasInstAwareBpps = hasInstantiationAwareBeanPostProcessors();
        // 是否需要进行依赖检查
        boolean needsDepCheck = (mbd.getDependencyCheck() != RootBeanDefinition.DEPENDENCY_CHECK_NONE);

        if (hasInstAwareBpps || needsDepCheck) {
            if (pvs == null) {
                pvs = mbd.getPropertyValues();
            }
            // 从 bw 对象中提取 PropertyDescriptor 结果集
            // PropertyDescriptor:可以通过一对存取方法提取一个属性
            PropertyDescriptor[] filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
            if (hasInstAwareBpps) {
                for (BeanPostProcessor bp : getBeanPostProcessors()) {
                    if (bp instanceof InstantiationAwareBeanPostProcessor) {
                        // 对所有需要依赖检查的属性进行后处理
                        InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
                        pvs = ibp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName);
                        if (pvs == null) {
                            return;
                        }
                    }
                }
            }
            if (needsDepCheck) {
                // 依赖检查,对应 depends-on 属性
                checkDependencies(beanName, mbd, filteredPds, pvs);
            }
        }

        if (pvs != null) {
            // 将属性应用到 bean 中
            applyPropertyValues(beanName, mbd, bw, pvs);
        }
    }


postProcessAfterInstantiation在属性填充前,最后一次更改bean的机会。即实例化后置处理。这也是spring的扩展接口。

然后对 bean 进行填充,将各个属性值注入,其中,可能存在依赖于其他 bean 的属性,则会递归初始依赖 bean。 详见@Autowied原理

下篇讲循环依赖处理。

3.4 initializeBean 实例化


#AbstractAutowireCapableBeanFactory.class
protected Object initializeBean(final String beanName, final Object bean, @Nullable RootBeanDefinition mbd) {
        //Aware织入
        invokeAwareMethods(beanName, bean);

        /**
         * BeanPostProcessor 的作用:在 Bean 完成实例化后,
         * 如果我们需要对其进行一些配置、增加一些自己的处理逻辑,那么请使用 BeanPostProcessor。
         */
        Object wrappedBean = bean;
        if (mbd == null || !mbd.isSynthetic()) {
            //初始化前置处理
            wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
        }

        try {
            //初始化方法
            invokeInitMethods(beanName, wrappedBean, mbd);
        }
        
        if (mbd == null || !mbd.isSynthetic()) {
            //初始化后置处理
            wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
        }

        return wrappedBean;
    }

❶Aware织入


#AbstractAutowireCapableBeanFactory.class

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);
            }
        }
    }

如我们常见的ApplicationContextAware,织入applicationContext对象。

❷applyBeanPostProcessorsBeforeInitialization初始化前置处理

    
    #AbstractAutowireCapableBeanFactory.class
    #List<BeanPostProcessor> beanPostProcessors = new ArrayList<>();
    @Override
    public Object applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName)
            throws BeansException {

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

这也是spring的扩展之一


❸invokeInitMethods调用初始化方法

#AbstractAutowireCapableBeanFactory.class

protected void invokeInitMethods(String beanName, final Object bean, @Nullable RootBeanDefinition mbd)
            throws Throwable {

        // 如果实现了 InitializingBean 接口,则只掉调用bean的 afterPropertiesSet()
        boolean isInitializingBean = (bean instanceof InitializingBean);
        if (isInitializingBean && (mbd == null || !mbd.isExternallyManagedInitMethod("afterPropertiesSet"))) {
            
            // 直接调用 afterPropertiesSet()
            ((InitializingBean) bean).afterPropertiesSet();
            
        }

        // 如果指定了 init-method(),则再调用制定的init-method
        if (mbd != null && bean.getClass() != NullBean.class) {
            String initMethodName = mbd.getInitMethodName();
            if (StringUtils.hasLength(initMethodName) &&
                    !(isInitializingBean && "afterPropertiesSet".equals(initMethodName)) &&
                    !mbd.isExternallyManagedInitMethod(initMethodName)) {
                // 利用反射机制执行
                invokeCustomInitMethod(beanName, bean, mbd);
            }
        }
    }   

❹applyBeanPostProcessorsAfterInitialization初始化后置处理


#AbstractAutowireCapableBeanFactory.class

    @Override
    public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName)
            throws BeansException {

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

这是我们一般扩展用的比较多的一个实现方式。


比如我们实现一个自定义的@Value注解。


1.定义注解

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface MyValue {
    String value();
}

2. 后置处理给属性赋值


@Component
public class HelloBeanPostProcessor implements BeanPostProcessor {
    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        if(bean instanceof HelloService){
            System.out.println("调用了BeanPostProcessor的postProcessAfterInitialization方法");
            Class<?> clzz = bean.getClass();
            for (Field field : clzz.getDeclaredFields()) {
                if (field.isAnnotationPresent(MyValue.class)){
                    String value = field.getAnnotation(MyValue.class).value();
                    field.setAccessible(true);
                    try {
                        field.set(bean,value);
                    } catch (IllegalAccessException e) {
                        e.printStackTrace();
                    }
                }
            }
        }
        return bean;
    }
}

3. 应用

    @MyValue("xxx")
   private String name;
    
   public void sayHello(){
        System.out.println("hello :"+ name);
    }

3.5 bean的依赖处理

截取上面doCreateBean部分代码

    
    #AbstractAutowireCapableBeanFactory.class#doCreateBean
    if (earlySingletonExposure) {
        // 获取 earlySingletonReference
        Object earlySingletonReference = getSingleton(beanName, false);
        // 只有在存在循环依赖的情况下,earlySingletonReference 才不会为空
        if (earlySingletonReference != null) {
            // 如果 exposedObject 没有在初始化方法中被改变,也就是没有被增强
            if (exposedObject == bean) {
                exposedObject = earlySingletonReference;
            }
            // 处理依赖
            else if (!this.allowRawInjectionDespiteWrapping && hasDependentBean(beanName)) {
                String[] dependentBeans = getDependentBeans(beanName);
                Set<String> actualDependentBeans = new LinkedHashSet<>(dependentBeans.length);
                for (String dependentBean : dependentBeans) {
                    if (!removeSingletonIfCreatedForTypeCheckOnly(dependentBean)) {
                        actualDependentBeans.add(dependentBean);
                    }
                }
                
            }
        }

这里调用前面分析的getSingleton

  #DefaultSingletonBeanRegistry.class
protected Object getSingleton(String beanName, boolean allowEarlyReference) {
        //
        Object singletonObject = this.singletonObjects.get(beanName);
        // 缓存中的 bean 为空,且当前 bean 正在创建
        if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
            //加锁保证 二级缓存添加和三级缓存删除操作的原子性,同时二级缓存和三级缓存就没有必要用concurrentHashMap了
            synchronized (this.singletonObjects) {  
                // 从 earlySingletonObjects 获取
                singletonObject = this.earlySingletonObjects.get(beanName);
                // earlySingletonObjects 中没有,且允许提前创建
                if (singletonObject == null && allowEarlyReference) {
                    // 从 singletonFactories 中获取对应的 ObjectFactory
                    /**
                     * allowEarlyReference:从字面意思上面理解就是允许提前拿到引用。
                     * 其实真正的意思是是否允许从 singletonFactories 缓存中通过 getObject() 拿到对象,为什么会有这样一个字段呢?
                     * 原因就在于 singletonFactories 才是 Spring 解决 singleton bean 的诀窍所在
                     */
                    ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
                    // ObjectFactory 不为空,则创建 bean
                    if (singletonFactory != null) {
                        singletonObject = singletonFactory.getObject();//类似回调覆盖 执行lambda 表达式   AOP
                        this.earlySingletonObjects.put(beanName, singletonObject);//三级缓存升到二级缓存
                        this.singletonFactories.remove(beanName);
                    }
                }
            }
        }
        return singletonObject;
    }

因为bean已经实例化完成,所以不需要提前暴露。此时传入的值allowEarlyReference是false,

所以当从二级缓存中没有拿到singletonObject 后,不会继续从三级缓存中获取因为第二个判断条件是false .所以到最后二级缓存没有对象。


创建bean的过程是个函数回调 的过程,创建好bean后回到getSingleton)的第步,此时返回的bean是经过完整ioc返回的完整的bean

#DefaultSingletonBeanRegistry.class
public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) {
        Assert.notNull(beanName, "Bean name must not be null");
        //全局加锁
        synchronized (this.singletonObjects) {
            // 从缓存中检查一遍
            //因为 singleton 模式其实就是复用已经创建的 bean 所以这步骤必须检查
            Object singletonObject = this.singletonObjects.get(beanName);
            //  为空,开始加载过程
            if (singletonObject == null) {
                if (this.singletonsCurrentlyInDestruction) {
                    throw new BeanCreationNotAllowedException(beanName,
                            "Singleton bean creation not allowed while singletons of this factory are in destruction " +
                            "(Do not request a bean from a BeanFactory in a destroy method implementation!)");
                }
            
                //加载前置处理,将bean的状态修改为正在创建中
                beforeSingletonCreation(beanName);
                boolean newSingleton = false;
                boolean recordSuppressedExceptions = (this.suppressedExceptions == null);
                if (recordSuppressedExceptions) {
                    this.suppressedExceptions = new LinkedHashSet<>();
                }
                try {
                    // 初始化 bean
                    // 这个过程其实是调用 createBean() 方法
                    singletonObject = singletonFactory.getObject();
                    newSingleton = true;
                }
                finally {
                    if (recordSuppressedExceptions) {
                        this.suppressedExceptions = null;
                    }
                    // 后置处理,将bean的状态从正在创建中移除
                    afterSingletonCreation(beanName);
                }
                // 加入缓存中
                if (newSingleton) {
                    /**
                     * 一级缓存添加
                     */
                    addSingleton(beanName, singletonObject);
                }
            }
            return singletonObject;
        }
    }
      

接下来看第❹步addSingleton

    protected void addSingleton(String beanName, Object singletonObject) {
        synchronized (this.singletonObjects) {
            this.singletonObjects.put(beanName, singletonObject);
            this.singletonFactories.remove(beanName);
            this.earlySingletonObjects.remove(beanName);
            this.registeredSingletons.add(beanName);
        }
    }

最终只有一级缓存singletonObjects中保存完整的bean对象。


4.总结


可以得出结论,当没有循环依赖产生时,整个ioc的过程只有一级缓存singletonObjects和三级缓存起了作用,二级缓存earlySingletonObjects自始至终都是空的。AOP源码分析那章也做了分析。一文弄懂AOP源码


(篇幅和时间关系,后续再将详细讲循环依赖解决和factoryBean的源码)。


最后祝所以程序员1024节日快乐。




Spring IOC 源码一
关注我的你,是最香哒!














原文始发于微信公众号(小李的源码图):Spring IOC 源码一

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/145419.html

(0)
青莲明月的头像青莲明月

相关推荐

发表回复

登录后才能评论
极客之音——专业性很强的中文编程技术网站,欢迎收藏到浏览器,订阅我们!