Spring源码解析(四) -- getBean(String name, Class<T> requiredType)

前言

  早在分析beanFactoryPostProcessor的时候,就出现了BeanFactory.getBean方法,因为每一个beanFactoryPostProcessor也是spring管理的bean,也是要经过spring实例化和初始化才能够使用的,只是当时该方法还不是要分析的重点。

  这里多提一句 在初始化过程中容易被忽略的一个方法

public void refresh() throws BeansException, IllegalStateException {
        synchronized (this.startupShutdownMonitor) {
            // Prepare this context for refreshing.
            prepareRefresh();

            // Tell the subclass to refresh the internal bean factory.
            ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

            // Prepare the bean factory for use in this context.
            prepareBeanFactory(beanFactory);

            try {
                // Allows post-processing of the bean factory in context subclasses.
                postProcessBeanFactory(beanFactory);

                // Invoke factory processors registered as beans in the context.
                invokeBeanFactoryPostProcessors(beanFactory);

                // Register bean processors that intercept bean creation.
                registerBeanPostProcessors(beanFactory);

                // Initialize message source for this context.
                initMessageSource();

                // Initialize event multicaster for this context.
                initApplicationEventMulticaster();

                // Initialize other special beans in specific context subclasses.
                onRefresh();

                // Check for listener beans and register them.
                registerListeners();

这一步是注册listener,一般可以监听spring的context容器启动完成等情况的,一般开发者也不太会用到

1 查询缓存

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

这部分是先查询该bean是否在之前有过缓存,有就直接使用了,还有一种情况是该bean是一个beanFactory那么就调用beanFactory的getObject方法

2 从父容器中初始化bean

// Fail if we're already creating this bean instance:
            // We're assumably within a circular reference.
            if (isPrototypeCurrentlyInCreation(beanName)) {
                throw new BeanCurrentlyInCreationException(beanName);
            }

            // Check if bean definition exists in this factory.
            BeanFactory parentBeanFactory = getParentBeanFactory();
            if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
                // Not found -> check parent.
                String nameToLookup = originalBeanName(name);
                if (args != null) {
                    // Delegation to parent with explicit args.
                    return (T) parentBeanFactory.getBean(nameToLookup, args);
                }
                else {
                    // No args -> delegate to standard getBean method.
                    return parentBeanFactory.getBean(nameToLookup, requiredType);
                }
            }

代码的作用比较清晰

3 开始实例化

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

                // Guarantee initialization of beans that the current bean depends on.
                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(dep, beanName);
                        getBean(dep);
                    }
                }

  先说一说这个BeanDefinition,BD只是一个接口,常用的实现类是

public abstract class AbstractBeanDefinition extends BeanMetadataAttributeAccessor
        implements BeanDefinition, Cloneable 

  比如在容器启动的最开始通过BeanDefinitionReader读取的最原始的bd就都是AbstractBeanDefinition

  到这里也能够看到 会把 AbstractBeanDefinition 变成了 RootBeanDefinition 

  注意这里的mergedBeanDefinition,根据文档beanDefinition也是有继承关系的。注意不是真的类的继承关系,我写的代码测试B继承A,但是还是两个BeanDefinition。

 mergedBeanDefinitions 是在 AbstractBeanFactory里的
private final Map<String, RootBeanDefinition> mergedBeanDefinitions =
            new ConcurrentHashMap<String, RootBeanDefinition>(256);

  而保存所有的beanDefinition是在 DefaultListableBeanFactory的 

/** Map of bean definition objects, keyed by bean name */
    private final Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<String, BeanDefinition>(256);

  总之一句话,一个beanDefinition会经过转换变成mergedBeanDefinition,尽管大多数的beanDefinition还是保持着原样。那么什么情况下会出现需要mergedBeanDefinition呢?如下这种,当然绝大多数没人这么用。

<bean id="baseUser" class="com.yh.stu.spring.sourcestu._01ioc.ch1_base.mergebd.BaseUser">
    </bean>
    <bean id="user" class="com.yh.stu.spring.sourcestu._01ioc.ch1_base.mergebd.User" parent="baseUser"/>

 

  而接下来的实例化一个bean就是使用mergedBeanDefinition。

  这里做的第二件事是实例化该bean所依赖的bean。注意这里的dependon并不是指@Autowired这种依赖注入,而是大概这种方式

<bean id="cat" class="com.lyc.cn.day08.Cat" p:name="美美" depends-on="dog"/>
<bean id="helloApi" class="com.feng.spring.chapter2.helloworld.HelloApi">
</bean>
<bean id="decorator"  
    class="cn.javass.spring.chapter3.bean.HelloApiDecorator"  
    depends-on="helloApi">  
    <property name="helloApi"><ref bean="helloApi"/></property>  
</bean>  

  同样的上面说的mergedBeanDefinition也不是指两个类之间的继承关系,而是这种通过配置文件配出来的两个bean的关系

<bean id="parentBean" abstract="true">
        <property name="name" value="我是父亲"/>
    </bean>
    <bean id="sunBean" class="com.lyc.cn.day08.SunBean" parent="parentBean">
        <property name="age" value="18"/>
    </bean>

  接下来就是正式的实例化过程了

4 AbstractAutowireCapableBeanFactory.createBean

第一部分 准备工作

  if (logger.isDebugEnabled()) {
            logger.debug("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<?> 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.
            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);
        }

  特别注意,// Give BeanPostProcessors a chance to return a proxy instead of the target bean instance. 大多数情况下Spring的动态代理并不是在这里完成的,除非在配置文件里显式的配了

TargetSources,才会走到这里

第二部分 开始实例化

 AbstractAutowireCapableBeanFactory.doCreateBean 

// Instantiate the bean.
        BeanWrapper instanceWrapper = null;
        if (mbd.isSingleton()) {
            instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
        }
        if (instanceWrapper == null) {
            instanceWrapper = createBeanInstance(beanName, mbd, args);
        }

  真正进行实例化的代码就在 createBeanInstance 里,

  beanInstance = getInstantiationStrategy().instantiate(mbd, beanName, parent); 对于绝大部分bean来说都是通过反射,利用class拿到构造方法,再用构造方法实例化对象,这里不再展开。

  回到doCreateBean继续分析

缓存需要依赖注入的元信息

// Allow post-processors to modify the merged bean definition.
        synchronized (mbd.postProcessingLock) {
            if (!mbd.postProcessed) {
                try {
                    applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
                }
                catch (Throwable ex) {
                    throw new BeanCreationException(mbd.getResourceDescription(), beanName,
                            "Post-processing of merged bean definition failed", ex);
                }
                mbd.postProcessed = true;
            }
        }

  applyMergedBeanDefinitionPostProcessors 的是就是这样的,那么  MergedBeanDefinitionPostProcessor的实现类有哪些呢?还真有一个比较有名的AutowiredAnnotationBeanPostProcessor。AutowiredAnnotationBeanPostProcessor是能够处理@Autowired和@Value这样的注解的。这也和之前介绍BeanPostProcessor里提到的呼应起来了,BeanPostProcessor有两个最特别的子类

  1  InstantiationAwareBeanPostProcessor

  2  MergedBeanDefinitionPostProcessor

protected void applyMergedBeanDefinitionPostProcessors(RootBeanDefinition mbd, Class<?> beanType, String beanName) {
        for (BeanPostProcessor bp : getBeanPostProcessors()) {
            if (bp instanceof MergedBeanDefinitionPostProcessor) {
                MergedBeanDefinitionPostProcessor bdp = (MergedBeanDefinitionPostProcessor) bp;
                bdp.postProcessMergedBeanDefinition(mbd, beanType, beanName);
            }
        }
    }

  我们来看看 AutowiredAnnotationBeanPostProcessor的 postProcessMergedBeanDefinition干了啥。

@Override
    public void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName) {
        if (beanType != null) {
            InjectionMetadata metadata = findAutowiringMetadata(beanName, beanType, null);
            metadata.checkConfigMembers(beanDefinition);
        }
    }
private InjectionMetadata findAutowiringMetadata(String beanName, Class<?> clazz, PropertyValues pvs) {
        // Fall back to class name as cache key, for backwards compatibility with custom callers.
        String cacheKey = (StringUtils.hasLength(beanName) ? beanName : clazz.getName());
        // Quick check on the concurrent map first, with minimal locking.
        InjectionMetadata metadata = this.injectionMetadataCache.get(cacheKey);
        if (InjectionMetadata.needsRefresh(metadata, clazz)) {
            synchronized (this.injectionMetadataCache) {
                metadata = this.injectionMetadataCache.get(cacheKey);
                if (InjectionMetadata.needsRefresh(metadata, clazz)) {
                    if (metadata != null) {
                        metadata.clear(pvs);
                    }
                    try {
                        metadata = buildAutowiringMetadata(clazz);
                        this.injectionMetadataCache.put(cacheKey, metadata);
                    }
findAutowiringMetadata方法是很长的,这里只截取一段代码看看意思。
buildAutowiringMetadata构造出来一个要注入的元数据对象,同时缓存在 injectionMetadataCache里面,缓存的key就是
String cacheKey = (StringUtils.hasLength(beanName) ? beanName : clazz.getName());
InjectionMetadata 是什么呢,就是一个对象里哪个属性是需要注入的(其他的由Spring管理的对象,而不是基本类型)。
这些缓存信息AutowiredAnnotationBeanPostProcessor在后续代码执行中会用到的。

  再次回到doCreateBean继续分析

解决循环依赖的

// Eagerly cache singletons to be able to resolve circular references
        // even when triggered by lifecycle interfaces like BeanFactoryAware.
        boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
                isSingletonCurrentlyInCreation(beanName));
        if (earlySingletonExposure) {
            if (logger.isDebugEnabled()) {
                logger.debug("Eagerly caching bean '" + beanName +
                        "' to allow for resolving potential circular references");
            }
            addSingletonFactory(beanName, new ObjectFactory<Object>() {
                @Override
                public Object getObject() throws BeansException {
                    return getEarlyBeanReference(beanName, mbd, bean);
                }
            });
        }

  这部分就是解决循环依赖的关键点,把一个实例化好了的bean放进三级缓存里。

属性注入及初始化

  最重要的两个方法,populateBean和initializeBean

  populateBean是解决一个bean属性注入的。

  initializeBean是调用初始化方法的,比如@PostConstruct,配置文件里的init-method,和实现了InitializingBean接口的接口方法

Object exposedObject = bean;
        try {
            populateBean(beanName, mbd, instanceWrapper);
            if (exposedObject != null) {
                exposedObject = initializeBean(beanName, exposedObject, mbd);
            }
        }
        catch (Throwable ex) {
            if (ex instanceof BeanCreationException && beanName.equals(((BeanCreationException) ex).getBeanName())) {
                throw (BeanCreationException) ex;
            }
            else {
                throw new BeanCreationException(
                        mbd.getResourceDescription(), beanName, "Initialization of bean failed", ex);
            }
        }

分析下populateBean

    if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_NAME ||
                mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_TYPE) {
            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;
        }
     //上面的代码现在几乎不会走到,都是为了兼容老代码的,而且像@Autowired等注解也不走到里面
        boolean hasInstAwareBpps = hasInstantiationAwareBeanPostProcessors();
        boolean needsDepCheck = (mbd.getDependencyCheck() != RootBeanDefinition.DEPENDENCY_CHECK_NONE);

        if (hasInstAwareBpps || needsDepCheck) {
            PropertyDescriptor[] filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
            if (hasInstAwareBpps) {
                for (BeanPostProcessor bp : getBeanPostProcessors()) {//循环遍历每一个beanPostProcessor调用他们的postProcessPropertyValues
                    if (bp instanceof InstantiationAwareBeanPostProcessor) {
                        InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
                        pvs = ibp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName);
                        if (pvs == null) {
                            return;
                        }
                    }
                }
            }

  不妨我们还是以AutowiredAnnotationBeanPostProcessor的 方法来举例

public PropertyValues postProcessPropertyValues(
            PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName) throws BeanCreationException {

        InjectionMetadata metadata = findAutowiringMetadata(beanName, bean.getClass(), pvs);
        try {
            metadata.inject(bean, beanName, pvs);
        }
        catch (BeanCreationException ex) {
            throw ex;
        }
        catch (Throwable ex) {
            throw new BeanCreationException(beanName, "Injection of autowired dependencies failed", ex);
        }
        return pvs;
    }

之前在 缓存需要依赖注入的元信息 这个小节交代过了, 实例化后会处理一个bean中的标签@Autowired并缓存起来。

现在就可以直接用了

拿到 InjectionMetadata metadata 后就调用  inject。

对于autowired来说他对应的 方法是这样的

@Override
        protected void inject(Object bean, String beanName, PropertyValues pvs) throws Throwable {
            Field field = (Field) this.member;
            Object value;
            if (this.cached) {
                value = resolvedCachedArgument(beanName, this.cachedFieldValue);
            }
            else {
                DependencyDescriptor desc = new DependencyDescriptor(field, this.required);
                desc.setContainingClass(bean.getClass());
                Set<String> autowiredBeanNames = new LinkedHashSet<String>(1);
                TypeConverter typeConverter = beanFactory.getTypeConverter();
                try {
                    value = beanFactory.resolveDependency(desc, beanName, autowiredBeanNames, typeConverter);//把依赖的值解析出来
                }
                catch (BeansException ex) {
                    throw new UnsatisfiedDependencyException(null, beanName, new InjectionPoint(field), ex);
                }
                synchronized (this) {
                    if (!this.cached) {
                        if (value != null || this.required) {
                            this.cachedFieldValue = desc;
                            registerDependentBeans(beanName, autowiredBeanNames);
                            if (autowiredBeanNames.size() == 1) {
                                String autowiredBeanName = autowiredBeanNames.iterator().next();
                                if (beanFactory.containsBean(autowiredBeanName)) {
                                    if (beanFactory.isTypeMatch(autowiredBeanName, field.getType())) {
                                        this.cachedFieldValue = new ShortcutDependencyDescriptor(
                                                desc, autowiredBeanName, field.getType());
                                    }
                                }
                            }
                        }
                        else {
                            this.cachedFieldValue = null;
                        }
                        this.cached = true;
                    }
                }
            }
            if (value != null) {
                ReflectionUtils.makeAccessible(field);
                field.set(bean, value);//反射方法直接塞进去
            }
        }

  再说明一下另一个常用的自动注入注解@Resource,也是在 populateBean 中生效的

  在CommonAnnotationBeanPostProcessor中方法 buildResourceMetadata中的代码段中

else if (field.isAnnotationPresent(Resource.class)) {
                        if (Modifier.isStatic(field.getModifiers())) {
                            throw new IllegalStateException("@Resource annotation is not supported on static fields");
                        }
                        if (!ignoredResourceTypes.contains(field.getType().getName())) {
                            currElements.add(new ResourceElement(field, field, null));
                        }
                    }

  如果一个字段头顶有@Resource会保存起来,等待后续处理

上面是处理自动注入其他Bean的逻辑,最后还会执行一下属性静态值的注入,所谓的静态值就是配置文件里明确配了的值,这部分值会在装在BeanDefinition的时候就缓存在BD中

   applyPropertyValues(beanName, mbd, bw, pvs); 这部分就不详细说了。

initializeBean

  到了执行初始化方法的时候了,这里说的初始化有三种,@PostConstruct,bean实现了initializingBean接口,和配置了init-method方法,这三种情况的执行。

  先看代码

protected Object initializeBean(final String beanName, final Object bean, RootBeanDefinition mbd) {
        if (System.getSecurityManager() != null) {
            AccessController.doPrivileged(new PrivilegedAction<Object>() {
                @Override
                public Object run() {
                    invokeAwareMethods(beanName, bean);
                    return null;
                }
            }, getAccessControlContext());
        }
        else {
            invokeAwareMethods(beanName, bean);
        }

        Object wrappedBean = bean;
        if (mbd == null || !mbd.isSynthetic()) {
            wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);//就在这里执行的@PostConstruct
        }

        try {
            invokeInitMethods(beanName, wrappedBean, mbd);//先initializingBean接口,而后才是init-method方法
}
catch (Throwable ex) { throw new BeanCreationException( (mbd != null ? mbd.getResourceDescription() : null), beanName, "Invocation of init method failed", ex); } if (mbd == null || !mbd.isSynthetic()) { wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);//大多数后置处理器都是直接return原bean } return wrappedBean; }
调用applyBeanPostProcessorsBeforeInitialization过程中会调用InitDestroyAnnotationBeanPostProcessor.postProcessBeforeInitialization
InitDestroyAnnotationBeanPostProcessor实现了接口 MergedBeanDefinitionPostProcessor 所以呢?在一个Bean实例化成一个空对象的时候,首先就执行过一次
MergedBeanDefinitionPostProcessor的 postProcessMergedBeanDefinition 对元数据进行了缓存,此时就正好拿出来直接使用了
@Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        LifecycleMetadata metadata = findLifecycleMetadata(bean.getClass());
        try {
            metadata.invokeInitMethods(bean, beanName);
        }
        catch (InvocationTargetException ex) {
            throw new BeanCreationException(beanName, "Invocation of init method failed", ex.getTargetException());
        }
        catch (Throwable ex) {
            throw new BeanCreationException(beanName, "Failed to invoke init method", ex);
        }
        return bean;
    }

  最终调用 

private LifecycleMetadata buildLifecycleMetadata(final Class<?> clazz) {
        final boolean debug = logger.isDebugEnabled();
        LinkedList<LifecycleElement> initMethods = new LinkedList<LifecycleElement>();
        LinkedList<LifecycleElement> destroyMethods = new LinkedList<LifecycleElement>();
        Class<?> targetClass = clazz;

        do {
            final LinkedList<LifecycleElement> currInitMethods = new LinkedList<LifecycleElement>();
            final LinkedList<LifecycleElement> currDestroyMethods = new LinkedList<LifecycleElement>();

            ReflectionUtils.doWithLocalMethods(targetClass, new ReflectionUtils.MethodCallback() {
                @Override
                public void doWith(Method method) throws IllegalArgumentException, IllegalAccessException {
                    if (initAnnotationType != null) {
                        if (method.getAnnotation(initAnnotationType) != null) {
                            LifecycleElement element = new LifecycleElement(method);
                            currInitMethods.add(element);
                            if (debug) {
                                logger.debug("Found init method on class [" + clazz.getName() + "]: " + method);
                            }
                        }
                    }
initAnnotationType是在子类中赋值的,
public CommonAnnotationBeanPostProcessor() {
        setOrder(Ordered.LOWEST_PRECEDENCE - 3);
        setInitAnnotationType(PostConstruct.class);
        setDestroyAnnotationType(PreDestroy.class);
        ignoreResourceType("javax.xml.ws.WebServiceContext");
    }

所以,处理PostConstruct的就是CommonAnnotationBeanPostProcessor。并且面试中常问的初始化顺序问题通过源码也能够知道了。

applyBeanPostProcessorsBeforeInitialization先执行,然后 invokeInitMethods才执行。所以PostConstruct最早执行。
<bean id="helloApi" class="com.feng.spring.chapter2.helloworld.HelloApi">
</bean>
<bean id="decorator"  
    class="cn.javass.spring.chapter3.bean.HelloApiDecorator"  
    depends-on="helloApi">  
    <property name="helloApi"><ref bean="helloApi"/></property>  
</bean>  

posted on 2020-10-07 18:02  MaXianZhe  阅读(817)  评论(0编辑  收藏  举报

导航