暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

Spring源码分析(二)bean的创建过程

Java艺术 2021-09-09
796
欢迎将文章分享到朋友圈
如需转载,请在后台回复“转载”获取授权


转载是一种动力 分享是一种美德


一直在摸索spring框架,看了《Spring技术内幕》和《Spring源码深度解析》,而这两本书在讲Spring IOC容器的时候都是讲xml配置方式的,但我觉得基于注解的方式没有读取解析xml文件会更简单。

Spring源码分析(二)bean的创建过程


spring版本:4.3.18


上一篇有说到过BeanDefinition,主要关注的是其扩展接口AnnotateBeanDefinition和其子类AnnotateGenericBeanDefinition。本篇先超前介绍spring是如果通过BeanDefinition来创建一个bean的。


>>>>

BeanDefinition的注册


AnnotationConfigApplicationContext是GenericApplicationContext的子类,所以是使用内置DefaultListableBeanFactory工厂类完成bean的注册和创建的。


public GenericApplicationContext() {
        this.beanFactory = new DefaultListableBeanFactory();
    }

复制


使用AnnotationConfigApplicationContext的任一构造方法【AnnotationConfigApplicationContext(DefaultListableBeanFactory beanFactory)除外】实例化AnnotationConfigApplicationContext都会调用其无参构造方法,最终父类的GenericApplicationContext都会被调用,在父类的构造方法中创建了DefaultListableBeanFactory实例,这就是AnnotationConfigApplicationContext使用的bean工厂。


@Override
    public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition)
            throws BeanDefinitionStoreException {
        
......
        
//如果当前bean工厂中存在beanName对应的BeanDefinition,那么oldBeanDefinition不为空。
        BeanDefinition oldBeanDefinition;
        oldBeanDefinition = 
this.beanDefinitionMap.get(beanName);

        
if (oldBeanDefinition != null) {
            ......
            
//将新的替换旧的
            
this.beanDefinitionMap.put(beanName, beanDefinition);
        }
        
else {
            
//private final Set<String> alreadyCreated = Collections.newSetFromMap(new ConcurrentHashMap<String, Boolean>(256));
            
//alreadyCreated保存的是已经至少创建过一次的bean的名称
            
//hasBeanCreationStarted就是判断alreadyCreated是否是空的,没有存储任何beanName。
            
if (hasBeanCreationStarted()) {
                
//保证线程安全
                synchronized (
this.beanDefinitionMap) {
                    
//beanDefinitionMap就是工厂用来保存描述bean的beanDefinition对象的。使用beanName作为beanDefinition
                    
this.beanDefinitionMap.put(beanName, beanDefinition);
                    List<String> updatedDefinitions = new ArrayList<String>(
this.beanDefinitionNames.size() + 1);
                    updatedDefinitions.addAll(
this.beanDefinitionNames);
                    updatedDefinitions.add(beanName);
                    
//将beanDefinitionNames指向新的beanName列表
                    
this.beanDefinitionNames = updatedDefinitions;
                    
if (this.manualSingletonNames.contains(beanName)) {
                        Set<String> updatedSingletons = new LinkedHashSet<String>(
this.manualSingletonNames);
                        updatedSingletons.remove(beanName);
                        
//manualSingletonNames保存的是单例bean的名称     
                        
this.manualSingletonNames = updatedSingletons;
                    }
                }
            }
            
else {
                
// 如果alreadyCreated为空,则说明仍在启动注册阶段
                
this.beanDefinitionMap.put(beanName, beanDefinition);
                
this.beanDefinitionNames.add(beanName);
                
this.manualSingletonNames.remove(beanName);
            }
            
this.frozenBeanDefinitionNames = null;
        }
        
if (oldBeanDefinition != null || containsSingleton(beanName)) {
            resetBeanDefinition(beanName);
        }
    }

复制


在下一篇介绍AnnotationConfigApplicationContext的启动流程会详细介绍何时调用这个registerBeanDefinition方法,被注解为bean的类何时被读取并创建BeanDefinition。


>>>>

getBean的调用栈


调用AnnotationConfigApplicationContext的getBean方法最终会调用其内置bean工厂DefaultListableBeanFactory的getBean方法。


 UserBean userBean = (UserBean) applicationContext.getBean("userBean");
 userBean = applicationContext.getBean(UserBean.class);

复制


AnnotationConfigApplicationContext并没有重写getBean方法,所以这里getBean调用的是其父类AbstractApplicationContext的getBean方法。



前面说了,AnnotationConfigApplicationContext是应用上下文,它管理bean的生命周期,但是它并不是真正的bean工厂。AbstractApplicationContext类中的getBeanFactory方法获取到的就是AnnotationConfigApplicationContext的内置 bean工厂DefaultListableBeanFactory。

@Override
public abstract ConfigurableListableBeanFactory getBeanFactory() throws IllegalStateException;

复制


发现在AnnotationConfigApplicationContext的父类GenericApplicationContext重写了该方法。

【GenericApplicationContext类】
    @Override
    public final ConfigurableListableBeanFactory getBeanFactory() {
        return this.beanFactory;
    }

复制


this.beanFactory就是DefaultListableBeanFactory。

private final DefaultListableBeanFactory beanFactory;

复制


最终getBean调用的是DefaultListableBeanFactory的getBean方法。


DefaultListableBeanFactory类实现BeanFactory的其它父类未实现的getBean方法。



DefaultListableBeanFactory的父父类AbstractBeanFactory类实现了BeanFactory接口的三个getBean方法。


>>>>

doGetBean方法


前面的所有getBean方法最终都是调用AbstractBeanFactory类的doGetBean方法的。doGetBean方法比较长,已经在源码中给出了注释。为了好看我将日记相关的代码去掉了。


【AbstractBeanFactory类】
protected <T> T doGetBean(
            final String name, final Class<T> requiredType, final Object[] args, boolean typeCheckOnly)
            throws BeansException {

        //根据传递进来的参数name获取beanName,
        //一般情况下name就是beanName,如果是要获取BeanFactory对象的话,name是包含'&'字符的,所以需要先去掉'&'。
        //最后调用canonicalName方法(确定原始名称,将别名解析为规范名称。)
        final String beanName = transformedBeanName(name);
        Object bean;

        // 检查手动注册的单例缓存。
        Object sharedInstance = getSingleton(beanName);
        if (sharedInstance != null && args == null) {
            bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
        }

        else {
            // isPrototypeCurrentlyInCreation返回指定的原型bean是否当前正在创建。如何当前正在创建则抛出BeanCurrentlyInCreationException异常。应该是避免多线程调用的。
            if (isPrototypeCurrentlyInCreation(beanName)) {
                throw new BeanCurrentlyInCreationException(beanName);
            }

            // 获取父bean工厂,检查父bean工厂中是否存在这个bean。
            BeanFactory parentBeanFactory = getParentBeanFactory();
            if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
                //originalBeanName方法确定原始bean名称,将本地定义的别名解析为规范名称。如果name包含‘&’符号,则originalBeanName返回的name也包含&符号
                String nameToLookup = originalBeanName(name);
                if (args != null) {
                    return (T) parentBeanFactory.getBean(nameToLookup, args);
                }
                else {
                    return parentBeanFactory.getBean(nameToLookup, requiredType);
                }
            }

            if (!typeCheckOnly) {
                markBeanAsCreated(beanName);
            }

            try {
                final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
                checkMergedBeanDefinition(mbd, beanName, args);

                // 确保初始化当前bean所依赖的bean已经创建。
                String[] dependsOn = mbd.getDependsOn();
                if (dependsOn != null) {
                    for (String dep : dependsOn) {
                        if (isDependent(beanName, dep)) {
                            throw new BeanCreationException(mbd.getResourceDescription(), beanName,
                                    "Circular depends-on relationship between '" + beanName + "' and '" + dep + "'");
                        }
                        //registerDependentBean为给定的bean注册依赖bean(在给定的bean被销毁之前被销毁)。
                        //这个方法和isDependent方法是配合使用确保依赖死循环的。
                        registerDependentBean(dep, beanName);
                        try {
                            //调用getBean方法让依赖的bean创建(如果没创建才会创建),最终还是调用doGetBean方法。
                            //如果依赖的bean又依赖其它bean那就先确保依赖的bean的依赖bean先创建,递归。
                            //所以前面的registerDependentBean方法和isDependent方法是解决无限递归调用的。
                            getBean(dep);
                        }
                        catch (NoSuchBeanDefinitionException ex) {
                            throw new BeanCreationException(mbd.getResourceDescription(), beanName,
                                    "'" + beanName + "' depends on missing bean '" + dep + "'", ex);
                        }
                    }
                }

                // 从这里开始创建bean实例

                //如果BeanDefinition中描述这个bean是单例的
                if (mbd.isSingleton()) {
                    //ObjectFactory,将bean的创建过程交给ObjectFactory完成。所以bean的创建是由对象工厂ObjectFactory创建的。
                    sharedInstance = getSingleton(beanName, new ObjectFactory<Object>() {
                        @Override
                        public Object getObject() throws BeansException {
                            try {
//调用AbstractBeanFactory的createBean方法最终是调用其子类AbstractAutowireCapableBeanFactory的createBean方法创建bean。
                                return createBean(beanName, mbd, args);
                            }
                            catch (BeansException ex) {
                                //异常则销毁这个bean
                                destroySingleton(beanName);
                                throw ex;
                            }
                        }
                    });

                    //获取给定bean实例的对象,对于FactoryBean,可能是bean实例本身,
                    //也可能是它创建的对象,由beanName是否包含'&'符合决定。
                    //如果该bean是一个FactoryBean且name没有'&'符号,那么就是调用该bean的getObject方法获取目标对象,
                    //如果该bean的is单例方法返回true那么目标对象将会被factoryBeanObjectCache所缓存。
                    //更多具体的就需要自己看源码了。
                    bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
                }

                else if (mbd.isPrototype()) {
                    // 不是单例,不用判断工厂中是否存在这个bean,直接创建一个新的实例。
                    Object prototypeInstance = null;
                    try {
                        beforePrototypeCreation(beanName);
                        // 与前面如果是单例的时候ObjectFactory的getObject方法中调用的createBean方法是同一个方法,不重复描述了。
                        prototypeInstance = createBean(beanName, mbd, args);
                    }
                    finally {
                        //before、after这些就是调用些通知了,具体是啥自己去看源码。
                        afterPrototypeCreation(beanName);
                    }
                    //跟isSingleton的情况下注释相同
                    bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
                }

                else {
                    String scopeName = mbd.getScope();
                    final Scope scope = this.scopes.get(scopeName);
                    if (scope == null) {
                        throw new IllegalStateException("No Scope registered for scope name '" + scopeName + "'");
                    }
                    try {
                        //其它如scope="request"的时候
                        Object scopedInstance = scope.get(beanName, new ObjectFactory<Object>() {
                            @Override
                            public Object getObject() throws BeansException {
                                beforePrototypeCreation(beanName);
                                try {
                                    //还是调用createBean方法创建对象
                                    return createBean(beanName, mbd, args);
                                }
                                finally {
                                    afterPrototypeCreation(beanName);
                                }
                            }
                        });
                        //跟isSingleton的情况下注释相同
                        bean = getObjectForBeanInstance(scopedInstance, name, beanName, mbd);
                    }
                    catch (IllegalStateException ex) {
                        
......
                    }
                }
            }
            
catch (BeansException ex) {
                cleanupAfterBeanCreationFailure(beanName);
                
throw ex;
            }
        }

        
// 如果getBean同时传入了requiredType和beanName
        
//则需要检查所需的类型是否与实际bean实例的类型匹配。
        
if (requiredType != null && bean != null && !requiredType.isInstance(bean)) {
            
try {
                
return getTypeConverter().convertIfNecessary(bean, requiredType);
            }
            
catch (TypeMismatchException ex) {
                
...
            }
        }
        
//将bean强转为我们需要的目标类型返回
        
return (T) bean;
    }

复制


>>>>

createBean方法


从doGetBean方法的源码中可以看到,无论bean的scope是单例还是其它,最终都是调用createBean方法创建实际的bean,只不过如果是单例的会被bean工厂缓存下次调用doGetBean就从缓存中获取到了就不需要再次调用createBean方法创建bean了。单例缓存实例上就是保存在一个map对象中。


【DefaultSingletonBeanRegistry类】
private final Map<StringObject> singletonObjects = new ConcurrentHashMap<StringObject>(256);

复制


至于单例是在什么时候被缓存的,可以回头看下doGetBean方法,在mbd.isSingleton的情况下,调用了getSingleton(beanName, new ObjectFactory<Object>(){})方法获取实例,第一个参数是bean的名称,第二个参数是一个ObjectFactory。AbstractBeanFactory是DefaultSingletonBeanRegistry的子类,所以最后调用的是DefaultSingletonBeanRegistry的getSingleton(beanName, new ObjectFactory<Object>()方法。


【DefaultSingletonBeanRegistry类】
    public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) {

        synchronized (this.singletonObjects) {
            Object singletonObject = this.singletonObjects.get(beanName);
            if (singletonObject == null) {
                ......
                boolean newSingleton = false;

                try {
                    //调用ObjectFactory工厂的getObject方法获取到bean
                    singletonObject = singletonFactory.getObject();
                    newSingleton = true;
                }
                catch (IllegalStateException ex) {
                    ......
                }
                catch (BeanCreationException ex) {
                    ......
                }
                finally {
                    ......
                }
                if (newSingleton) {
                    //缓存bean
                    addSingleton(beanName, singletonObject);
                }
            }
            return (singletonObject != NULL_OBJECT ? singletonObject : null);
        }
    }

复制


getSingleton方法中如果从单例缓存中获取不到指定的bean就调用ObjectFactory的getObject方法获取实例,最后将获取到的实例添加到缓存中。


createBean方法的调用栈:

【AbstractBeanFactory类】
protected abstract Object createBean(String beanName, RootBeanDefinition mbd, Object[] args)
            throws BeanCreationException;

复制


【AbstractAutowireCapableBeanFactory类】

    //---------------------------------------------------------------------
    // 实现父类AbstractBeanFactory的抽象方法
    //---------------------------------------------------------------------
    @Override
    protected Object createBean(String beanName, RootBeanDefinition mbd, Object[] args) throws BeanCreationException {
        RootBeanDefinition mbdToUse = mbd;
        Class<?> resolvedClass = resolveBeanClass(mbd, beanName);
        if (resolvedClass != null && !mbd.hasBeanClass() && mbd.getBeanClassName() != null) {
            //在动态解析类的情况下克隆bean定义
            mbdToUse = new RootBeanDefinition(mbd);
            mbdToUse.setBeanClass(resolvedClass);
        }
        // Prepare method overrides.
        try {
            mbdToUse.prepareMethodOverrides();
        }
        catch (BeanDefinitionValidationException ex) {
            ......
        }
        try {
            // 让BeanPostProcessor有机会返回一个代理而不是目标bean实例。可以自行百度BeanPostProcessor的用法。
            //但这里实际是调用所有的InstantiationAwareBeanPostProcessor的postProcessBeforeInstantiation(Class<?> beanClass, String beanName)方法获取一个bean的代理类。
            //InstantiationAwareBeanPostProcessor是BeanPostProcessor的扩展类,但BeanPostProcessor应用在bean new处理之后。
            //spring内部类CommonAnnotationBeanPostProcessor就是InstantiationAwareBeanPostProcessor的实现类,还有很多。
            //BeanPostProcessor的扩展接口还有很多。
            Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
            if (bean != null) {
                return bean;
            }
        }
        catch (Throwable ex) {
            ......
        }
        //如果没有InstantiationAwareBeanPostProcessor创建该bean的代理类,则调用doCreateBean方法创建该bean
        Object beanInstance = doCreateBean(beanName, mbdToUse, args);
        return beanInstance;
    }

复制


resolveBeforeInstantiation方法

protected Object resolveBeforeInstantiation(String beanName, RootBeanDefinition mbd) {
        Object bean = null;
        //如果RootBeanDefinition的beforeInstantiationResolved
        //为true或为null则执行实例化后置处理器。
        //所以每个RootBeanDefinition被第一次调用createBean实例化时都会执行实例化后置处理器,
        //如果所有的后置处理器都返回null那么下一次调用createBean就不会调用这些实例化后置处理器了。
        if (!Boolean.FALSE.equals(mbd.beforeInstantiationResolved)) {
            if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
                Class<?> targetType = determineTargetType(beanName, mbd);
                if (targetType != null) {
                    bean = applyBeanPostProcessorsBeforeInstantiation(targetType, beanName);
                    if (bean != null) {
                        bean = applyBeanPostProcessorsAfterInitialization(bean, beanName);
                    }
                }
            }
            //bean==null则beforeInstantiationResolved设为false
            //bean!=null则beforeInstantiationResolved设为true
            mbd.beforeInstantiationResolved = (bean != null);
        }
        return bean;
    }

复制


resolveBeforeInstantiation方法中根据RootBeanDefinition的beforeInstantiationResolved字段判断是否应用bean实例化后置处理器。beforeInstantiationResolved表示该bean实例化前启用实例化后置处理器。每个RootBeanDefinition被第一次调用createBean实例化时beforeInstantiationResolved都是null的。


public class RootBeanDefinition{
......
volatile Boolean beforeInstantiationResolved;
......
}

复制


下面是CommonAnnotationBeanPostProcessor的postProcessBeforeInstantiation方法源码。所以如果只是想在bean的实例化之前做某些事情的化就可以实现InstantiationAwareBeanPostProcessor,然后postProcessBeforeInstantiation方法直接返回null就行了。当然你还需要注册这个InstantiationAwareBeanPostProcessor到bean工厂。


@Override
public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
     return null;
}

复制


doCreateBean方法

protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final Object[] args)
            throws BeanCreationException 
{
        // BeanWrapper是bean的包装类
        BeanWrapper instanceWrapper = null;
        if (mbd.isSingleton()) {
            //单例先从工厂缓存中移除缓存(移除对象的持有让gc回收)
            instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
        }
        if (instanceWrapper == null) {
            //调用createBeanInstance方法创建bean实例
            instanceWrapper = 
  createBeanInstance(beanName, mbd, args);
        }
        final Object bean = (instanceWrapper != null ? instanceWrapper.getWrappedInstance() : null);
        Class<?> beanType = (instanceWrapper != null ? instanceWrapper.getWrappedClass() : null);
        mbd.resolvedTargetType = beanType;

        // 允许后置处理器修改合并的bean定义。
        synchronized (mbd.postProcessingLock) {
            if (!mbd.postProcessed) {
                try {
                    applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
                }
                catch (Throwable ex) {
                    ......
                }
                mbd.postProcessed = true;
            }
        }
        
......
        
// 初始化bean实例。
        Object exposedObject = bean;
        
try {
            
//用bean定义的属性值填充给定bean包装器中的bean实例。
            populateBean(beanName, mbd, instanceWrapper);
            
if (exposedObject != null) {
                exposedObject = initializeBean(beanName, exposedObject, mbd);
            }
        }
        ......
        
return exposedObject;
    }

复制






具体的属性赋值可以继续往下看,跟进applyPropertyValues方法。





文章转载自Java艺术,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论