• 10、Spring 源码学习 ~ Bean 的加载步骤详解(一)


    Bean 的加载步骤详解(一)

    一、FactoryBean 的使用

    一般情况下,Spring 通过反射机制,利用 bean 的 class 属性指定的实现类,来实例化 bean。但假如实例化的 bean 需要配置文件提供大量的信息,这个时候配置文件的灵活方式是受限的,此时采用编码的方式也许可得到一个简单的方案。Spring 为此提供了一个 FactoryBean 的工厂类接口,用户可以通过实现该接口,来定制实例化 bean 的逻辑。

    Spring 本生提供了 70 多个 FactoryBean 的实现,而且从 Spring 3.0 开始,FactoryBean 可支持泛型,即接口声明改为 FactoryBean 的形式。如下:

    package org.springframework.beans.factory;
    
    import org.springframework.lang.Nullable;
    
    public interface FactoryBean<T> {
    
    	String OBJECT_TYPE_ATTRIBUTE = "factoryBeanObjectType";
    
        //返回由 FactoryBean 创建的 bean 实例,如果 isSingleton 返回 true,则该实例会放到 Spring 容器中的单例缓存池中
    	@Nullable
    	T getObject() throws Exception;
    
        //返回由 FactoryBean 创建的 bean 类型
    	@Nullable
    	Class<?> getObjectType();
    
        //返回 FactoryBean 创建的 bean 实例的作用域,默认是单例 singleton
    	default boolean isSingleton() {
    		return true;
    	}
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21

    中的 class 属性是 FactoryBean 的实现类时,通过 getBean() 方法返回的不是 FactoryBean 本身,而是 FactoryBean#getObject 返回的对象。

    示例:

    Car.java

    package com.luo.spring.guides.helloworld.beanloading.factorybean;
    
    import lombok.Data;
    import lombok.ToString;
    
    /**
     * @author : archer
     * @date : Created in 2022/10/28 10:27
     * @description :
     */
    @Data
    @ToString
    public class Car {
    
        //最大速度
        private int maxSpeed;
        //品牌
        private String brand;
        //价格
        private double price;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21

    CarFactoryBean.java

    package com.luo.spring.guides.helloworld.beanloading.factorybean;
    
    import org.springframework.beans.factory.FactoryBean;
    
    /**
     * @author : archer
     * @date : Created in 2022/10/28 10:28
     * @description :
     */
    public class CarFactoryBean implements FactoryBean<Car> {
    
        private String carInfo;
    
        @Override
        public Car getObject() throws Exception {
            Car car = new Car();
            String[] infos = carInfo.split(",");
            car.setBrand(infos[0]);
            car.setMaxSpeed(Integer.parseInt(infos[1]));
            car.setPrice(Double.parseDouble(infos[2]));
            return car;
        }
    
        @Override
        public Class<?> getObjectType() {
            return Car.class;
        }
    
        @Override
        public boolean isSingleton() {
            return false;
        }
    
        public String getCarInfo() {
            return carInfo;
        }
    
        //接受逗号分隔符设置属性信息,并且顺序固定是 brand,maxSpeed,price
        public void setCarInfo(String carInfo) {
            this.carInfo = carInfo;
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42

    facotryBeanTest.xml

    
    <beans xmlns="http://www.springframework.org/schema/beans"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xsi:schemaLocation="http://www.springframework.org/schema/beans
            http://www.springframework.org/schema/beans/spring-beans.xsd">
    
        <bean id="car" class="com.luo.spring.guides.helloworld.beanloading.factorybean.CarFactoryBean">
            <property name="carInfo" value="超级跑车,400,2000000"/>
        bean>
    
    beans>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    Main.java

    package com.luo.spring.guides.helloworld.beanloading.factorybean;
    
    import com.luo.spring.guides.helloworld.common.TestBean;
    import org.springframework.context.ApplicationContext;
    import org.springframework.context.support.ClassPathXmlApplicationContext;
    
    /**
     * @author : archer
     * @date : Created in 2022/10/28 10:49
     * @description :
     */
    public class Main {
    
        public static void main(String[] args) {
            ApplicationContext bf = new ClassPathXmlApplicationContext("beanloading/factorybean/facotryBeanTest.xml");
    
            //获取 Car 实例
            Car car = (Car) bf.getBean("car");
            System.out.println(car);
    
            //获取 CarFactoryBean 实例
            CarFactoryBean carFactoryBean = (CarFactoryBean) bf.getBean("&car");
            System.out.println(carFactoryBean.getClass());
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25

    输出:

    Car(maxSpeed=400, brand=超级跑车, price=2000000.0)
    class com.luo.spring.guides.helloworld.beanloading.factorybean.CarFactoryBean

    二、缓存中获取单例 bean

    单例 bean 的加载只会在 Spring 的容器中创建一次,后续再获取是直接从缓存中获取。这里首先是从缓存中加载,不存在再去 singleFactories 中加载。这里 Spring 为了避免循环,它创建 bean 的原则是不等 bean 创建完成,就会将创建 bean 的 ObjectFactory 提早曝光加入到缓存中,一旦下个 bean 创建时需要依赖上个 bean,则直接使用 ObjectFactory。

    @Override
    @Nullable
    public Object getSingleton(String beanName) {
        //参数 true 表示允许早期依赖
        return getSingleton(beanName, true);
    }
    
    @Nullable
    protected Object getSingleton(String beanName, boolean allowEarlyReference) {
        // Quick check for existing instance without full singleton lock
        //检查缓存中是否存在实例
        Object singletonObject = this.singletonObjects.get(beanName);
        //缓存还不存在单例 bean 并且当前正在创建中
        if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
            //判断早期依赖中是否存在实例,有则表示 bean 正在加载
            singletonObject = this.earlySingletonObjects.get(beanName);
            if (singletonObject == null && allowEarlyReference) {
                //不存在并且允许早期依赖,则锁定全局变量并进行处理
                synchronized (this.singletonObjects) {
                    // Consistent creation of early reference within full singleton lock
                    //双重判断缓存中是否存在实例,防止上层判断完后准备加锁的时候,另一线程已实例化,并放到缓存中了
                    singletonObject = this.singletonObjects.get(beanName);
                    if (singletonObject == null) {
                        singletonObject = this.earlySingletonObjects.get(beanName);
                        if (singletonObject == null) {
                            //当某些 bean 需要提前初始化的时候,则会调用 addSingleFactory 方法将对应的
                            //ObjectFactory 初始化策略,存储在 singletonFactories中
                            ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
                            if (singletonFactory != null) {
                                //调用预先设定的 getObject 方法
                                singletonObject = singletonFactory.getObject();
                                //记录在缓存中,earlySingletonObjects 与 singletonFactories 互斥
                                this.earlySingletonObjects.put(beanName, singletonObject);
                                this.singletonFactories.remove(beanName);
                            }
                        }
                    }
                }
            }
        }
        return singletonObject;
    }
    
    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.singletonFactories.put(beanName, singletonFactory);
                this.earlySingletonObjects.remove(beanName);
                this.registeredSingletons.add(beanName);
            }
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53

    名词解释:

    • **singletonObjects:**Map 结构,用于保存 BeanName 和创建 bean 实例之间的关系,beanName -> bean instance;
    • **singletonFactories:**Map 结构,用于保存 BeanName 和创建 bean 实例的工厂之间的关系,beanName -> ObjectFactory;
    • **earlySingletonObjects:**Map 结构,用于保存 BeanName 和创建 bean 实例之间的关系
      • 与 singletonObjects 不同之处在于,当一个单例 bean 被放到里面后,那么当 bean 还在创建过程中时,就可以通过 getBean 方法获取到了,其目的是用来检测循环引用。
    • **registeredSingletons:**Set 结构,用来保存当前所有已注册的单例 beanName;

    上述代码大致步骤如下:

    • 1、首先尝试从 singletonObjects 中获取实例
    • 2、若上面获取不到,再尝试从 earlySingletonObjects 中获取实例
    • 3、若还是获取不到并且 allowEarlyReference 为 true (允许循环引用)时,再从 singletonFactories 中获取对应的 ObjectFactory,在调用这个 ObjectFactory 的 getObject 来创建 bean,并放到 earlySingletonObjects 缓存中去,并从 singletonFactories 中 remove 掉这个 ObjectFactory。

    三、从 bean 的实例中获取对象

    在 getBean 的方法中,getObjectForBeanInstance 是个高频率使用的方法。无论是从缓存中还是根据不同的 scope 策略得到 bean 实例后,首先做的都是调这个方法来检测下正确性,即当前 bean 是否是 FactoryBean 类型的 bean,如果是,则调用对应的 FactoryBean 实例中的 getObject() 作为返回值。

    这里返回的只是 bean 最原始的状态。并不一定是我们真正需要的 bean。

    如:假如我们需要对工厂 bean 进行处理,这里得到的是工厂 bean 的初始状态,而我们真正需要的是工厂 bean 中定义的 factory-method 方法中返回的 bean。而 getObjectForBeanInstance 就是完成这个工作的。源码如下:

    protected Object getObjectForBeanInstance(
        Object beanInstance, String name, String beanName, @Nullable RootBeanDefinition mbd) {
    
        // Don't let calling code try to dereference the factory if the bean isn't a factory.
        //如果指定的 name 是工厂相关(以 & 为前缀),则进入代码
        if (BeanFactoryUtils.isFactoryDereference(name)) {
            if (beanInstance instanceof NullBean) {
                return beanInstance;
            }
            //beanInstance 不是 FactoryBean 类型,则验证不通过
            if (!(beanInstance instanceof FactoryBean)) {
                throw new BeanIsNotAFactoryException(beanName, beanInstance.getClass());
            }
            if (mbd != null) {
                mbd.isFactoryBean = true;
            }
            //getBean("&car"); 直接返回 FactoryBean
            return beanInstance;
        }
    
        // Now we have the bean instance, which may be a normal bean or a FactoryBean.
        // If it's a FactoryBean, we use it to create a bean instance, unless the
        // caller actually wants a reference to the factory.
        //现在这个 beanInstance 可能是普通的 bean 实例或者 FactoryBean 对象,
        //如果是普通的 bean,则直接返回
        if (!(beanInstance instanceof FactoryBean)) {
            return beanInstance;
        }
    
        //加载 FactoryBean
        Object object = null;
        if (mbd != null) {
            mbd.isFactoryBean = true;
        }
        else {
            //尝试从缓存中加载 bean
            object = getCachedObjectForFactoryBean(beanName);
        }
        if (object == null) {
            // Return bean instance from factory.
            //到这里已经明确知道 beanInstance 一定是 FactoryBean 类型
            FactoryBean<?> factory = (FactoryBean<?>) beanInstance;
            // Caches object obtained from FactoryBean if it is a singleton.
            //containsBeanDefinition 检测 beanDefinitionMap (即所有已加载的类)中检测是否定义了 beanName
            if (mbd == null && containsBeanDefinition(beanName)) {
                //将存储 XML 配置文件的 GernericBeanDefinition 转换为 RootBeanDefinition,
                //如果指定 beanName 是子 Bean 的话,同时会合并父类的相关属性
                mbd = getMergedLocalBeanDefinition(beanName);
            }
            //是否是用户定义的,而不是程序本身定义的
            boolean synthetic = (mbd != null && mbd.isSynthetic());
            //用户自定义的无需后置处理
            object = getObjectFromFactoryBean(factory, beanName, !synthetic);
        }
        return object;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56

    上述中主要是做一些功能性的判断检查,大致如下:

    • 1、验证 FactoryBean 的正确性
    • 2、非 FactoryBean 不做任何处理
    • 3、对 bean 进行转换
    • 4、将从 Factory 中解析 bean 的工作委托给 getObjectFromFactoryBean。

    即真正核心代码委托给了 getObjectFromFactoryBean,其源码如下:

    //shouldPostProcess 为 true,表示需要后置处理
    protected Object getObjectFromFactoryBean(FactoryBean<?> factory, String beanName, boolean shouldPostProcess) {
        //如果是单例模式
        if (factory.isSingleton() && containsSingleton(beanName)) {
            synchronized (getSingletonMutex()) {
                Object object = this.factoryBeanObjectCache.get(beanName);
                if (object == null) {
                    object = doGetObjectFromFactoryBean(factory, beanName);
                    // Only post-process and store if not put there already during getObject() call above
                    // (e.g. because of circular reference processing triggered by custom getBean calls)
                    Object alreadyThere = this.factoryBeanObjectCache.get(beanName);
                    if (alreadyThere != null) {
                        object = alreadyThere;
                    }
                    else {
                        if (shouldPostProcess) {
                            if (isSingletonCurrentlyInCreation(beanName)) {
                                // Temporarily return non-post-processed object, not storing it yet..
                                return object;
                            }
                            beforeSingletonCreation(beanName);
                            try {
                                //调用 ObjectFactory 的后处理器
                                object = postProcessObjectFromFactoryBean(object, beanName);
                            }
                            catch (Throwable ex) {
                                throw new BeanCreationException(beanName,
                                                                "Post-processing of FactoryBean's singleton object failed", ex);
                            }
                            finally {
                                afterSingletonCreation(beanName);
                            }
                        }
                        if (containsSingleton(beanName)) {
                            this.factoryBeanObjectCache.put(beanName, object);
                        }
                    }
                }
                return object;
            }
        }
        else {
            Object object = doGetObjectFromFactoryBean(factory, beanName);
            if (shouldPostProcess) {
                try {
                    //调用 ObjectFactory 的后处理器
                    object = postProcessObjectFromFactoryBean(object, beanName);
                }
                catch (Throwable ex) {
                    throw new BeanCreationException(beanName, "Post-processing of FactoryBean's object failed", ex);
                }
            }
            return object;
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55

    这个方法里的逻辑就是,保证返回的 bean,如果是单例的,就是全局唯一的,同时加了一些缓存以提高性能,而获取真正实例对象的逻辑在 doGetObjectFromFactoryBean 方法中,当 bean 声明为 FactoryBean 类型时,提取 bean 时,提取的并不是 FactoryBean,而是 FactoryBean 中对应的 getObject 方法返回的 bean,doGetObjectFromFactoryBean 正是实现这个功能的,doGetObjectFromFactoryBean 源码如下:

    private Object doGetObjectFromFactoryBean(FactoryBean<?> factory, String beanName) throws BeanCreationException {
        Object object;
        try {
            //需要权限验证
            if (System.getSecurityManager() != null) {
                AccessControlContext acc = getAccessControlContext();
                try {
                    object = AccessController.doPrivileged((PrivilegedExceptionAction<Object>) factory::getObject, acc);
                }
                catch (PrivilegedActionException pae) {
                    throw pae.getException();
                }
            }
            else {
                //直接调用 getObject 方法返回
                object = factory.getObject();
            }
        }
        catch (FactoryBeanNotInitializedException ex) {
            throw new BeanCurrentlyInCreationException(beanName, ex.toString());
        }
        catch (Throwable ex) {
            throw new BeanCreationException(beanName, "FactoryBean threw exception on object creation", ex);
        }
    
        // Do not accept a null value for a FactoryBean that's not fully
        // initialized yet: Many FactoryBeans just return null then.
        if (object == null) {
            if (isSingletonCurrentlyInCreation(beanName)) {
                throw new BeanCurrentlyInCreationException(
                    beanName, "FactoryBean which is currently in creation returned null from getObject");
            }
            object = new NullBean();
        }
        return object;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36

    处理完 doGetObjectFromFactoryBean 之后,程序还做了一些后置处理,即 shouldPostProcess 为 true 时的逻辑,先看 AbstractAutowireCapableBeanFactory#postProcessObjectFromFactoryBean,源码如下:

    @Override
    protected Object postProcessObjectFromFactoryBean(Object object, String beanName) {
        return applyBeanPostProcessorsAfterInitialization(object, beanName);
    }
    
    @Override
    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;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    对于后处理器的使用,后续会有详细介绍,这里我们先记住 Spring 中获取 bean 的规则:

    尽可能保证所有 bean 初始化后,都会调用注册的 BeanPostProcessor#postProcessAfterInitialization 方法进行处理

    实际开发过程中,可根据此特性设计自己的业务逻辑。

    四、获取单例

    上面我们学习了从缓存中获取单例的过程,那如果缓存中不存在已经加载的单例 bean,那就需要从头开始 bean 的加载过程了,而 Spring 中使用 getSingleton 的重载方法实现 bean 的加载过程。

    public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) {
        Assert.notNull(beanName, "Bean name must not be null");
        //全局变量需要加同步锁
        synchronized (this.singletonObjects) {
            //首先检查对应的 bean 是否已经加载过,因为 singleton 模式其实就是复用已创建的 bean
            //故此步骤是必须的
            Object singletonObject = this.singletonObjects.get(beanName);
            //如果为空,才可以进行 singleton 的 bean 的初始化
            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!)");
                }
                if (logger.isDebugEnabled()) {
                    logger.debug("Creating shared instance of singleton bean '" + beanName + "'");
                }
                beforeSingletonCreation(beanName);
                boolean newSingleton = false;
                boolean recordSuppressedExceptions = (this.suppressedExceptions == null);
                if (recordSuppressedExceptions) {
                    this.suppressedExceptions = new LinkedHashSet<>();
                }
                try {
                    //初始化 bean
                    singletonObject = singletonFactory.getObject();
                    newSingleton = true;
                }
                catch (IllegalStateException ex) {
                    // Has the singleton object implicitly appeared in the meantime ->
                    // if yes, proceed with it since the exception indicates that state.
                    singletonObject = this.singletonObjects.get(beanName);
                    if (singletonObject == null) {
                        throw ex;
                    }
                }
                catch (BeanCreationException ex) {
                    if (recordSuppressedExceptions) {
                        for (Exception suppressedException : this.suppressedExceptions) {
                            ex.addRelatedCause(suppressedException);
                        }
                    }
                    throw ex;
                }
                finally {
                    if (recordSuppressedExceptions) {
                        this.suppressedExceptions = null;
                    }
                    afterSingletonCreation(beanName);
                }
                if (newSingleton) {
                    //加入缓存
                    addSingleton(beanName, singletonObject);
                }
            }
            return singletonObject;
        }
    }
    
    //单例创建的前置处理
    //记录加载状态,this.singletonsCurrentlyInCreation.add(beanName) 将 正在创建的 bean 记录到缓存中,以便对循环依赖进行检测
    protected void beforeSingletonCreation(String beanName) {
        if (!this.inCreationCheckExclusions.contains(beanName) && !this.singletonsCurrentlyInCreation.add(beanName)) {
            throw new BeanCurrentlyInCreationException(beanName);
        }
    }
    
    //单例创建的后置处理
    //将结果记录至缓存并删除加载 bean 过程中所记录的各种辅助状态
    protected void afterSingletonCreation(String beanName) {
        if (!this.inCreationCheckExclusions.contains(beanName) && !this.singletonsCurrentlyInCreation.remove(beanName)) {
            throw new IllegalStateException("Singleton '" + beanName + "' isn't currently in creation");
        }
    }
    
    //
    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);
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85

    上述代码使用的回调方法,使得程序可以在单例创建的前后做一些准备及处理操作,这些准备包括如下内容:

    • 1、检查缓存是否已经加载过
    • 2、若没有加载,则记录 beanName 的正在加载状态
    • 3、加载单例前记录加载状态
    • 4、通过调用参数传入的 ObjectFactory#getObject 实例化bean
    • 5、加载单例后置处理方法调用
    • 6、将结果记录至缓存并删除加载 bean 过程中所记录的各种辅助状态
    • 7、返回处理结果

    上面我们并没有看到真正获取单例 bean 的方法,其真正实现逻辑实是在生成 ObjectFactory 的实例中实现的,如下:

    if (mbd.isSingleton()) {
        sharedInstance = getSingleton(beanName, () -> {
            try {
                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;
            }
        });
        beanInstance = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    从上面可以看出,我们需要具体到 createBean 方法中探寻真正创建 bean 的逻辑。

    五、准备创建 bean

    我们跟踪了很多 Spring 源码后,可以发现一个真正干活的函数,一般是以 do 开头的,我们看下 createBean 方法的具体实现:

    @Override
    protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
        throws BeanCreationException {
    
        if (logger.isTraceEnabled()) {
            logger.trace("Creating instance of bean '" + beanName + "'");
        }
        RootBeanDefinition mbdToUse = mbd;
    
        // Make sure bean class is actually resolved at this point, and
        // clone the bean definition in case of a dynamically resolved Class
        // which cannot be stored in the shared merged bean definition.
        //锁定 class,根据设置的 class 属性或者根据 className 来解析 class
        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();
        }
        catch (BeanDefinitionValidationException ex) {
            throw new BeanDefinitionStoreException(mbdToUse.getResourceDescription(),
                                                   beanName, "Validation of method overrides failed", ex);
        }
    
        try {
            // Give BeanPostProcessors a chance to return a proxy instead of the target bean instance.
            //给 BeanPostProcessors(后置处理器) 一个机会来返回代理(替代真正的实例)
            Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
            if (bean != null) {
                return bean;
            }
        }
        catch (Throwable ex) {
            throw new BeanCreationException(mbdToUse.getResourceDescription(), beanName,
                                            "BeanPostProcessor before instantiation of bean failed", ex);
        }
    
        try {
            //真正创建 bean
            Object beanInstance = doCreateBean(beanName, mbdToUse, args);
            if (logger.isTraceEnabled()) {
                logger.trace("Finished creating instance of bean '" + beanName + "'");
            }
            return beanInstance;
        }
        catch (BeanCreationException | ImplicitlyAppearedSingletonException ex) {
            // A previously detected exception with proper bean creation context already,
            // or illegal singleton state to be communicated up to DefaultSingletonBeanRegistry.
            throw ex;
        }
        catch (Throwable ex) {
            throw new BeanCreationException(
                mbdToUse.getResourceDescription(), beanName, "Unexpected exception during bean creation", ex);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60

    以上代码的具体步骤如下:

    • 1、根据设置的 class 属性或者根据 className 来解析 class
    • 2、对 override 属性进行标记和验证
      • override 属性的作用:Spring 配置中是存在 lookup-method 和 replace-method 的,这两个配置的加载统一存放在 BeanDefinition 中的 methodOverrides 属性里,这里的操作就是针对这两个配置的。
    • 3、应用初始化前的后处理器,解析指定 bean 是否存在初始化前的短路操作
    • 4、创建 bean

    1、处理 override 属性

    查看 AbstractBeanDefinition#prepareMethodOverrides#prepareMethodOverrides 方法:

    public void prepareMethodOverrides() throws BeanDefinitionValidationException {
        // Check that lookup methods exist and determine their overloaded status.
        if (hasMethodOverrides()) {
            
            getMethodOverrides().getOverrides().forEach(this::prepareMethodOverride);
        }
    }
    
    //获取对应类中对应方法名的个数
    protected void prepareMethodOverride(MethodOverride mo) throws BeanDefinitionValidationException {
        int count = ClassUtils.getMethodCountForName(getBeanClass(), mo.getMethodName());
        if (count == 0) {
            throw new BeanDefinitionValidationException(
                "Invalid method override: no method with name '" + mo.getMethodName() +
                "' on class [" + getBeanClassName() + "]");
        }
        else if (count == 1) {
            //当前类中的方法只有一个,设置重载该方法没有被重载,以便后续调用,可以直接使用找到的方法,并且可以提前对方法存在性进行验证
            //标记 MethodOverride 暂未被重写(覆盖),避免参数类型校验的开销
            // Mark override as not overloaded, to avoid the overhead of arg type checking.
            mo.setOverloaded(false);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23

    从这里可以看出 lookup-method 和 replace-method 功能的实现原理,就是在 bean 实例化时,如果检测存在 methodOverrides,就会动态地位当前 bean 生成代理,并使用对应的拦截器为 bean 做增强处理,相关逻辑实现在 bean 的实例化部分,后面会详细介绍。

    2、实例化的前置处理

    @Nullable
    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;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • applyBeanPostProcessorsBeforeInstantiation 是对后处理器中所有的 InstantiationAwareBeanPostProcessor 类型的后处理器进行 postProcessBeforeInstantiation 方法的调用。

    • applyBeanPostProcessorsAfterInitialization 是对所有 BeanPostProcessor 的 postProcessAfterInitialization 方法进行调用。

    1)、实例化前的后处理器应用

    bean 的实例化前调用,也就是将 AbstractBeanDefinition 转换成 BeanWrapper 前的处理。这里是给子类一个修改 BeanDefinition 的机会,当经过这个方法后,bean 可能会成为一个经过处理的代理 bean,可能是通过 cglib 生成的,也可能是其他技术生成的。

    //在实例化之前应用 BeanPostProcessors
    @Nullable
    protected Object applyBeanPostProcessorsBeforeInstantiation(Class<?> beanClass, String beanName) {
        for (InstantiationAwareBeanPostProcessor bp : getBeanPostProcessorCache().instantiationAware) {
            Object result = bp.postProcessBeforeInstantiation(beanClass, beanName);
            if (result != null) {
                return result;
            }
        }
        return null;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    2)、实例化后的后处理器应用
    @Override
    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;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
  • 相关阅读:
    低代码平台选型6大能力:品牌/产品/技术/服务/安全/价值
    fastadmin列表页展示分类名称通用搜索按分类名称搜索
    早期Java Swing的eclipse项目导入idea使用
    两种方法实现pycharm中代码回滚到指定版本(附带截图展示)
    tongweb使用之端口冲突处理办法
    做个清醒的程序员之打造核心竞争力
    接口自动化测试思路和实战(4):数据驱动测试框架
    安装使用electron
    逻辑漏洞笔记
    SpringBoot SpringBoot 运维实用篇 2 配置高级 2.2 临时属性【开发环境】
  • 原文地址:https://blog.csdn.net/lxz352907839/article/details/127736393