《Spring源码深度解析》读书笔记 - bean的加载

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/u013435893/article/details/81030623

基本流程

完成了XML配置文件的解析,接下来就是对bean加载的探索。

//2.从ioc容器中获取bean实例
MyTestBean myTestBean = (MyTestBean) beanFactory.getBean("myTestBean");

跟踪进Spring的源码

public Object getBean(String name) throws BeansException {
    return this.doGetBean(name, (Class)null, (Object[])null, false);
}

protected <T> T doGetBean(String name, Class<T> requiredType, final Object[] args, boolean typeCheckOnly) throws BeansException {
    // 1. 提取对应的beanName
    final String beanName = this.transformedBeanName(name);
    // 2. 直接尝试从缓存获取或者singletonFactories中的ObjectFactory中获取
    Object sharedInstance = this.getSingleton(beanName);
    Object bean;
    if (sharedInstance != null && args == null) {
        if (this.logger.isDebugEnabled()) {
            if (this.isSingletonCurrentlyInCreation(beanName)) {
                this.logger.debug("Returning eagerly cached instance of singleton bean '" + beanName + "' that is not fully initialized yet - a consequence of a circular reference");
            } else {
                this.logger.debug("Returning cached instance of singleton bean '" + beanName + "'");
            }
        }
        // 3.返回对应的实例,有时候存储诸如BeanFactory的情况并不是直接返回实例本身而是返回指定方法返回的实例
        bean = this.getObjectForBeanInstance(sharedInstance, name, beanName, (RootBeanDefinition)null);
    } else {
        // 4.
        if (this.isPrototypeCurrentlyInCreation(beanName)) {
            throw new BeanCurrentlyInCreationException(beanName);
        }

        BeanFactory parentBeanFactory = this.getParentBeanFactory();
        // 5.如果beanDefinitionMap中也就是在所有已经加载的类中不包括beanName,则尝试从parentBeanFactory中检测
        if (parentBeanFactory != null && !this.containsBeanDefinition(beanName)) {
            String nameToLookup = this.originalBeanName(name);
            // 递归到BeanFactory中寻找
            if (args != null) {
                return parentBeanFactory.getBean(nameToLookup, args);
            }

            return parentBeanFactory.getBean(nameToLookup, requiredType);
        }
        // 如果不是仅仅做类型检查则是创建bean,这里要进行记录
        if (!typeCheckOnly) {
            this.markBeanAsCreated(beanName);
        }

        try {
            // 6.将存储XML配置文件的GernericBeanDefinition转换为RootBeanDefinition,如果指定BeanName是子Bean的话同时会合并父类的相关属性
            final RootBeanDefinition mbd = this.getMergedLocalBeanDefinition(beanName);
            this.checkMergedBeanDefinition(mbd, beanName, args);
            String[] dependsOn = mbd.getDependsOn();
            String[] var11;
            // 7.若存在依赖则需要递归实例化依赖的bean
            if (dependsOn != null) {
                var11 = dependsOn;
                int var12 = dependsOn.length;

                for(int var13 = 0; var13 < var12; ++var13) {
                    String dep = var11[var13];
                    if (this.isDependent(beanName, dep)) {
                        throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Circular depends-on relationship between '" + beanName + "' and '" + dep + "'");
                    }
                    // 缓存依赖调用
                    this.registerDependentBean(dep, beanName);
                    this.getBean(dep);
                }
            }
            // 8.singleton模式的创建
            if (mbd.isSingleton()) {
                sharedInstance = this.getSingleton(beanName, new ObjectFactory<Object>() {
                    public Object getObject() throws BeansException {
                        try {
                            return AbstractBeanFactory.this.createBean(beanName, mbd, args);
                        } catch (BeansException var2) {
                            AbstractBeanFactory.this.destroySingleton(beanName);
                            throw var2;
                        }
                    }
                });
                bean = this.getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
            } else if (mbd.isPrototype()) {
                // prototype模式的创建
                var11 = null;

                Object prototypeInstance;
                try {
                    this.beforePrototypeCreation(beanName);
                    prototypeInstance = this.createBean(beanName, mbd, args);
                } finally {
                    this.afterPrototypeCreation(beanName);
                }

                bean = this.getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
            } else {
                // 指定的scope是实例化bean
                String scopeName = mbd.getScope();
                Scope scope = (Scope)this.scopes.get(scopeName);
                if (scope == null) {
                    throw new IllegalStateException("No Scope registered for scope name '" + scopeName + "'");
                }

                try {
                    Object scopedInstance = scope.get(beanName, new ObjectFactory<Object>() {
                        public Object getObject() throws BeansException {
                            AbstractBeanFactory.this.beforePrototypeCreation(beanName);

                            Object var1;
                            try {
                                var1 = AbstractBeanFactory.this.createBean(beanName, mbd, args);
                            } finally {
                                AbstractBeanFactory.this.afterPrototypeCreation(beanName);
                            }

                            return var1;
                        }
                    });
                    bean = this.getObjectForBeanInstance(scopedInstance, name, beanName, mbd);
                } catch (IllegalStateException var21) {
                    throw new BeanCreationException(beanName, "Scope '" + scopeName + "' is not active for the current thread; consider defining a scoped proxy for this bean if you intend to refer to it from a singleton", var21);
                }
            }
        } catch (BeansException var23) {
            this.cleanupAfterBeanCreationFailure(beanName);
            throw var23;
        }
    }
    // 9.检查需要的类型是否符合bean的实际类型
    if (requiredType != null && bean != null && !requiredType.isAssignableFrom(bean.getClass())) {
        try {
            return this.getTypeConverter().convertIfNecessary(bean, requiredType);
        } catch (TypeMismatchException var22) {
            if (this.logger.isDebugEnabled()) {
                this.logger.debug("Failed to convert bean '" + name + "' to required type '" + ClassUtils.getQualifiedName(requiredType) + "'", var22);
            }

            throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
        }
    } else {
        return bean;
    }
}
  1. 转换对应beanName
    beanFactory.getBean(String name)传入的参数,可能是别名,可能是beanName,也可能是FactoryBean,所以需要进行一系列的解析
  2. 尝试从缓存中加载单例
    单例在Spring的同一个容器内只会被创建一次,后续再获取bean,就直接从单例缓存中获取了。如果获取不成功,则再次尝试从singletonFactories中加载。因为在创建bean的时候会存在依赖注入的情况,而在创建依赖的时候为了避免循环依赖,在Spring中创建bean的原则是不等bean创建完成就会创建bean的ObjectFactory提早曝光加入到缓存中,一旦下一个bean创建时候需要依赖上一个bean则直接使用ObjectFactory
  3. bean的实例化
    如果从缓存中得到了bean的原始状态,则需要对bean进行实例化。这里需要说明:缓存中记录的只是最原始的bean状态,并不一定是我们最终想要的bean。而getObjectForBeanInstance就是完成这个工作的
  4. 原型模式的依赖检查
    只有在单例情况下才会尝试解决循环依赖,如果存在A中有B的属性,B中有A的属性,那么当依赖注入的时候,就会产生A还未创建完的时候因为对于B的创建再次返回创建A,造成循环依赖,也就是情况isPrototypeCurrentlyInCreation(beanName)判断true
  5. 检查parentBeanFactory
    如果缓存没有数据的话直接转到父类工程上去加载
  6. 将存储XML配置文件的GernericBeanDefinition转换为RootBeanDefinition
    因为从XML配置文件中读取到的Bean信息是存储在GernericBeanDefinition中的,但是所有的Bean后续处理都是针对于RootBeanDefinition的,所以这里需要进行一个转换,转换的同时如果父类bean不为空的话,则会一并合并父类的属性
  7. 寻找依赖
    因为bean的初始化过程中很可能会用到某些属性,而某些属性很可能是动态配置的,并且配置成依赖于其他的bean,那么这个时候就有必要先加载依赖的bean,所以,在Spring的加载顺序中,在初始化某一个bean的时候首先会初始化这个bean所对应的依赖
  8. 针对不同的scope进行bean的创建
    Spring中存在着不同的备scope,其中默认的是singleton,但是还有些其他的配置诸如prototype、request之类的。在这个步骤中,Spring会根据不同的配置进行不同的初始化策略
  9. 类型转换
    将生产的bean,转换为参数requiredType的类型。

FactoryBean

一般情况下,Spring通过反射机制利用bean的class属性指定实现类来实例化bean。
除此之外,Spring还提供了一个org.springframework.bean.factory.FactoryBean的工厂类接口,用户可以通过实现该接口定制实例化bean的逻辑。FactoryBean接口对于Spring来说很重要,它隐藏了实例化一些复杂bean的细节。

public interface FactoryBean<T> {
    // 返回由FactoryBean创建的bean实例
    // 如果isSingleton()返回true,则该实例会放到Spring容器中单实例缓存池中
    T getObject() throws Exception;

    // 返回FactoryBean创建的bean类型
    Class<?> getObjectType();

    // 返回由FactoryBean创建的bean实例的作用域是singleton还是prototype
    boolean isSingleton();
}

当配置文件中<bean>的class属性配置的实现类是FactoryBean时,通过getBean()方法返回的不是FactoryBean本身,而是FactoryBean.getObject()方法所返回的对象,相当于FactoryBean.getObject()代理了getBean()方法

public class Car {
    private int maxSpeed;
    private String brand;
    private double price;
    // get/set
}

如果使用传统方式配置Car的时候,Car的每个属性分别对应一个<property>元素标签
如果用FactoryBean的方式实现就会灵活一些

public class CarFactoryBean implements FactoryBean<Car> {
    private String carInfo;
    public Car getObject() throws Exception {
        Car car = new Car();
        String[] infos = carInfo.split(",");
        car.setBrand(infos[0]);
        car.setMaxSpeed(Integer.valueOf(infos[1]));
        car.setPrice(Double.valueOf(infos[2]));
        return car;
    }
    public Class<Car> getObjectType() {
        return Car.class;
    }
    public boolean isSingleton() {
        return false;
    }
    public String getCarInfo() {
        return this.carInfo;
    }
    public void setCarInfo(String carInfo) {
        this.carInfo = carInfo;
    }
} 

有了这个CarFactoryBean后,就可以如下配置了

<bean id="car" class="com.whyalwaysmea.factorybean.CarFactoryBean"  >
    <property name="carInfo" value="超级跑车,400,20000000" />
</bean>

当调用getBean("car")时,Spring通过反射机制发现CarFactoryBean实现了FactoryBean的接口,这时Spring容器就调用接口方法CarFactoryBean.getObject()方法返回。
如果希望获取CarFacoryBean的实例,则调用getBean("&car")

猜你喜欢

转载自blog.csdn.net/u013435893/article/details/81030623