【spring源码】注解篇-@Scope源码解析

251 阅读13分钟

回顾【spring源码-5】bean的实例化(2)主逻辑 - 掘金 (juejin.cn)

这个类是干嘛用的,简单说就是默认Bean是单例的,可以用它标识一个Bean是多例的。

一、使用示例

实体类添加@Component注解把实体类交给spring管理,默认是单例的

@Component
public class User {

	private String name = "xxj";
	private Integer age = 100;


	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public Integer getAge() {
		return age;
	}

	public void setAge(Integer age) {
		this.age = age;
	}

	@Override
	public String toString() {
		return "User{" +
				"name='" + name + '\'' +
				", age=" + age +
				'}';
	}
}
@Test
public void test2(){
    AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(AnnoConfig.class);
    User user1 = applicationContext.getBean("user", User.class);
    User user2 = applicationContext.getBean("user", User.class);
    System.out.println(user1 == user2);
}
true

注解参数

参数名类型参数值
value、scopeNameString""(默认)、singleton、prototype、...(自定义)
proxyModeEnum(ScopedProxyMode)DEFAULT(默认)、NO、INTERFACES、TARGET_CLASS

给上述User实体类添加注解并设置参数,输出结果如下

valueproxyMode输出结果
示例1""(默认)DEFAULT(默认)/NOtrue
示例2singletonDEFAULT(默认)/NOtrue
示例3prototypeDEFAULT(默认)/NOfalse
示例4""(默认)TARGET_CLASStrue
示例5singletonTARGET_CLASStrue
示例6prototypeTARGET_CLASStrue

二、@Scope源码解析

package org.springframework.context.annotation;

import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

import org.springframework.beans.factory.config.ConfigurableBeanFactory;
import org.springframework.core.annotation.AliasFor;

/**
 *  当与@Component一起用作类型级注释时, @Scope指示用于注释类型实例的范围名称。
    当与@Bean一起用作方法级注释时, @Scope指示用于从方法返回的实例的范围的名称。
    注意: @Scope注释仅在具体 bean 类(对于带注释的组件)或工厂方法(对于@Bean方法)进行内省。与 XML bean 定义相反,没有 bean 定义继承的概念,并且类级别的继承层次结构与元数据目的无关。
    在这种情况下,范围意味着实例的生命周期,例如singleton 、 prototype等。 Spring 中开箱即用的范围可以使用ConfigurableBeanFactory和WebApplicationContext接口中提供的SCOPE_*常量来引用。
    要注册其他自定义范围,请参阅CustomScopeConfigurer 。
    自从:
    2.5
    也可以看看:
    org.springframework.stereotype.Component , Bean
    作者:
    马克·费舍尔、克里斯·比姆斯、萨姆·布兰宁
 */
@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Scope {

	/**
	    scopeName的别名。
        也可以看看:
        scopeName
	 */
	@AliasFor("scopeName")
	String value() default "";

	/**
	 指定用于带注释的组件/bean 的范围的名称。
     默认为空字符串 ( "" ),这意味着SCOPE_SINGLETON 。
     自从:4.2
     也可以看看:
     ConfigurableBeanFactory.SCOPE_PROTOTYPE , ConfigurableBeanFactory.SCOPE_SINGLETON , org.springframework.web.context.WebApplicationContext.SCOPE_REQUEST , org.springframework.web.context.WebApplicationContext.SCOPE_SESSION , value
	 */
	@AliasFor("value")
	String scopeName() default "";

	/**
    	指定组件是否应配置为作用域代理,如果是,则代理是否应基于接口或基于子类。
        默认为ScopedProxyMode.DEFAULT ,这通常表示不应创建作用域代理,除非在组件扫描指令级别配置了不同的默认值。
        类似于 Spring XML 中的<aop:scoped-proxy/>支持。
        也可以看看:
        ScopedProxyMode
	 */
	ScopedProxyMode proxyMode() default ScopedProxyMode.DEFAULT;

}

2.1 @ComponentScan扫描注册BD

@ComponentScan扫描类时,如果有@Scope注解,会判断注解的参数值:

  1. proxyMode值是 DEFAULT(默认)/NO,会创建一个User类BD并注册。
  2. proxyMode值是 TARGET_CLASS 就额外创建一个新的BD并注册,也就是说一共会有两个BD
    2.1 新BD的beanName = scopedTarget.原BD的beanName
    2.2 新BD的Class类型是 ScopedProxyFactoryBean.class,注意这个类实现了FactoryBean接口
    2.3 新BD的scope属性值是空字符串 "",这个""会在doGetBean方法中 获取根据beanName获取BD的时候变成 "singleton",也就是说新BD是单例的。

可以看出,当proxyMode值是 TARGET_CLASS 时,无论value是何值,最终都会生成一个新的代理BD代替原BD,并且永远是单例的。

2.1.1 扫描注册BD

/**
	在指定的基础包中执行扫描,返回注册的 bean 定义。
    此方法不会注册注释配置处理器,而是将其留给调用者。
    参数:
    basePackages – 用于检查带注释的类的包
    返回:
    出于工具注册目的而注册的 bean 集(如果有)(绝不为null )

 */
protected Set<BeanDefinitionHolder> doScan(String... basePackages) {
    Assert.notEmpty(basePackages, "At least one base package must be specified");
    Set<BeanDefinitionHolder> beanDefinitions = new LinkedHashSet<>();
    for (String basePackage : basePackages) {
        // 扫描到有注解的类并封装成BeanDefinition对象
        // 获取到有注解的类(候选的类),现在还没有注册
        Set<BeanDefinition> candidates = findCandidateComponents(basePackage);
        // 当前bd信息不完整,循环填充bd信息并注册bd
        for (BeanDefinition candidate : candidates) {
            /**
             * 获取 @scope 注解信息
             */
            ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(candidate);
            /**
             * 给BD 设置 scope 属性值 = @scope 注解的value值
             */
            candidate.setScope(scopeMetadata.getScopeName());
            String beanName = this.beanNameGenerator.generateBeanName(candidate, this.registry);
            if (candidate instanceof AbstractBeanDefinition) {
                //支持了@Lazy @DependOn注解
                postProcessBeanDefinition((AbstractBeanDefinition) candidate, beanName);
            }
            if (candidate instanceof AnnotatedBeanDefinition) {
                // 填充注解信息
                AnnotationConfigUtils.processCommonDefinitionAnnotations((AnnotatedBeanDefinition) candidate);
            }
            if (checkCandidate(beanName, candidate)) {
                BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(candidate, beanName);
                /**
                 * 根据 scopeMetadata 属性判断是否需要重新生成 beanDefinition,
                 * 		如果需要生成 applyScopedProxyMode() 返回新的BD
                 * 		否则返回第二个入参也就是原BD
                 */
                definitionHolder = AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);
                beanDefinitions.add(definitionHolder);
                //BeanDefinition注册
                registerBeanDefinition(definitionHolder, this.registry);
            }
        }
    }
    return beanDefinitions;
}
public class AnnotationScopeMetadataResolver implements ScopeMetadataResolver {

	private final ScopedProxyMode defaultProxyMode;

	protected Class<? extends Annotation> scopeAnnotationType = Scope.class;


	/**
	 * Construct a new {@code AnnotationScopeMetadataResolver}.
	 * @see #AnnotationScopeMetadataResolver(ScopedProxyMode)
	 * @see ScopedProxyMode#NO
	 */
	public AnnotationScopeMetadataResolver() {
		this.defaultProxyMode = ScopedProxyMode.NO;
	}

	/**
	 * Construct a new {@code AnnotationScopeMetadataResolver} using the
	 * supplied default {@link ScopedProxyMode}.
	 * @param defaultProxyMode the default scoped-proxy mode
	 */
	public AnnotationScopeMetadataResolver(ScopedProxyMode defaultProxyMode) {
		Assert.notNull(defaultProxyMode, "'defaultProxyMode' must not be null");
		this.defaultProxyMode = defaultProxyMode;
	}


	/**
	 * Set the type of annotation that is checked for by this
	 * {@code AnnotationScopeMetadataResolver}.
	 * @param scopeAnnotationType the target annotation type
	 */
	public void setScopeAnnotationType(Class<? extends Annotation> scopeAnnotationType) {
		Assert.notNull(scopeAnnotationType, "'scopeAnnotationType' must not be null");
		this.scopeAnnotationType = scopeAnnotationType;
	}

	/**
	 * 解析 @Scope 注解的信息
	 * 
	 * @param definition the target bean definition
	 * @return
	 */
	@Override
	public ScopeMetadata resolveScopeMetadata(BeanDefinition definition) {
		ScopeMetadata metadata = new ScopeMetadata();
		if (definition instanceof AnnotatedBeanDefinition) {
			AnnotatedBeanDefinition annDef = (AnnotatedBeanDefinition) definition;
			/**
			 * 获取 BD 的@Scope 注解
			 */
			AnnotationAttributes attributes = AnnotationConfigUtils.attributesFor(
					annDef.getMetadata(), this.scopeAnnotationType);
			if (attributes != null) {
				/**
				 * @Scope 的 value 值 和 proxyMode 值 (proxyMode是个枚举类型)
				 */
				metadata.setScopeName(attributes.getString("value"));
				ScopedProxyMode proxyMode = attributes.getEnum("proxyMode");
				if (proxyMode == ScopedProxyMode.DEFAULT) {
					/**
					 * 如果是 ScopedProxyMode.DEFAULT 就设置成 defaultProxyMode(默认是 ScopedProxyMode.NO)
					 */
					proxyMode = this.defaultProxyMode;
				}
				metadata.setScopedProxyMode(proxyMode);
			}
		}
		return metadata;
	}

}
static BeanDefinitionHolder applyScopedProxyMode(ScopeMetadata metadata, BeanDefinitionHolder definition, BeanDefinitionRegistry registry) {

    ScopedProxyMode scopedProxyMode = metadata.getScopedProxyMode();
    /**
     * 如果是No 就直接返回,这个值默认就是NO
     */
    if (scopedProxyMode.equals(ScopedProxyMode.NO)) {
        return definition;
    }
    /**
     * 如果是ScopedProxyMode.TARGET_CLASS 就 createScopedProxy()
     */
    boolean proxyTargetClass = scopedProxyMode.equals(ScopedProxyMode.TARGET_CLASS);
    return ScopedProxyCreator.createScopedProxy(definition, registry, proxyTargetClass);
}
final class ScopedProxyCreator {

	private ScopedProxyCreator() {
	}


	public static BeanDefinitionHolder createScopedProxy(
			BeanDefinitionHolder definitionHolder, BeanDefinitionRegistry registry, boolean proxyTargetClass) {

		return ScopedProxyUtils.createScopedProxy(definitionHolder, registry, proxyTargetClass);
	}

	public static String getTargetBeanName(String originalBeanName) {
		return ScopedProxyUtils.getTargetBeanName(originalBeanName);
	}

}
public static BeanDefinitionHolder createScopedProxy(BeanDefinitionHolder definition,BeanDefinitionRegistry registry, boolean proxyTargetClass) {

		String originalBeanName = definition.getBeanName();
		BeanDefinition targetDefinition = definition.getBeanDefinition();
		/**
		 * 定义一个新的 DB 名称 = scopedTarget.旧名称
		 */
		String targetBeanName = getTargetBeanName(originalBeanName);

		/**
		 * 创建一个单例的 DB 是ScopedProxyFactoryBean 类型的,这个类继承了 FactoryBean
		 */
		// Create a scoped proxy definition for the original bean name,
		// "hiding" the target bean in an internal target definition.
		RootBeanDefinition proxyDefinition = new RootBeanDefinition(ScopedProxyFactoryBean.class);
		proxyDefinition.setDecoratedDefinition(new BeanDefinitionHolder(targetDefinition, targetBeanName));
		proxyDefinition.setOriginatingBeanDefinition(targetDefinition);
		proxyDefinition.setSource(definition.getSource());
		proxyDefinition.setRole(targetDefinition.getRole());

		/**
		 * 设置新名字 = scopedTarget.旧名称
		 */
		proxyDefinition.getPropertyValues().add("targetBeanName", targetBeanName);

		/**
		 * 如果 @Scope 注解的 scopedProxyMode 值不是 ScopedProxyMode.TARGET_CLASS(前面判断好传进来的)
		 * 		就把新DB的proxyTargetClass设置成 false
		 */
		if (proxyTargetClass) {
			targetDefinition.setAttribute(AutoProxyUtils.PRESERVE_TARGET_CLASS_ATTRIBUTE, Boolean.TRUE);
			// ScopedProxyFactoryBean's "proxyTargetClass" default is TRUE, so we don't need to set it explicitly here.
			// ScopedProxyFactoryBean的“proxyTargetClass”默认为TRUE,所以我们不需要在这里显式设置它
		}
		else {
			proxyDefinition.getPropertyValues().add("proxyTargetClass", Boolean.FALSE);
		}

		// Copy autowire settings from original bean definition.
		proxyDefinition.setAutowireCandidate(targetDefinition.isAutowireCandidate());
		proxyDefinition.setPrimary(targetDefinition.isPrimary());
		if (targetDefinition instanceof AbstractBeanDefinition) {
			proxyDefinition.copyQualifiersFrom((AbstractBeanDefinition) targetDefinition);
		}

		// The target bean should be ignored in favor of the scoped proxy.
		targetDefinition.setAutowireCandidate(false);
		targetDefinition.setPrimary(false);

		/**
		 * 把旧的 DB 注册到工厂
		 */
		// Register the target bean as separate bean in the factory.
		registry.registerBeanDefinition(targetBeanName, targetDefinition);

		// Return the scoped proxy definition as primary bean definition
		// (potentially an inner bean).
		/**
		 * 把新的 DB 返回
		 */
		return new BeanDefinitionHolder(proxyDefinition, originalBeanName, definition.getAliases());
	}

2.1.2 ScopedProxyFactoryBean

public class ScopedProxyFactoryBean extends ProxyConfig implements FactoryBean<Object>, BeanFactoryAware, AopInfrastructureBean {

	/** The TargetSource that manages scoping. */
	private final SimpleBeanTargetSource scopedTargetSource = new SimpleBeanTargetSource();

	/** The name of the target bean. */
	@Nullable
	private String targetBeanName;

	/** The cached singleton proxy. */
	@Nullable
	private Object proxy;


	/**
	 * Create a new ScopedProxyFactoryBean instance.
	 */
	public ScopedProxyFactoryBean() {
		setProxyTargetClass(true);
	}


	/**
	 * Set the name of the bean that is to be scoped.
	 */
	public void setTargetBeanName(String targetBeanName) {
		this.targetBeanName = targetBeanName;
		this.scopedTargetSource.setTargetBeanName(targetBeanName);
	}

	@Override
	public void setBeanFactory(BeanFactory beanFactory) {
		if (!(beanFactory instanceof ConfigurableBeanFactory)) {
			throw new IllegalStateException("Not running in a ConfigurableBeanFactory: " + beanFactory);
		}
		ConfigurableBeanFactory cbf = (ConfigurableBeanFactory) beanFactory;

		this.scopedTargetSource.setBeanFactory(beanFactory);

		ProxyFactory pf = new ProxyFactory();
		pf.copyFrom(this);
		pf.setTargetSource(this.scopedTargetSource);

		Assert.notNull(this.targetBeanName, "Property 'targetBeanName' is required");
		Class<?> beanType = beanFactory.getType(this.targetBeanName);
		if (beanType == null) {
			throw new IllegalStateException("Cannot create scoped proxy for bean '" + this.targetBeanName +
					"': Target type could not be determined at the time of proxy creation.");
		}
		if (!isProxyTargetClass() || beanType.isInterface() || Modifier.isPrivate(beanType.getModifiers())) {
			pf.setInterfaces(ClassUtils.getAllInterfacesForClass(beanType, cbf.getBeanClassLoader()));
		}

		// Add an introduction that implements only the methods on ScopedObject.
		ScopedObject scopedObject = new DefaultScopedObject(cbf, this.scopedTargetSource.getTargetBeanName());
		pf.addAdvice(new DelegatingIntroductionInterceptor(scopedObject));

		// Add the AopInfrastructureBean marker to indicate that the scoped proxy
		// itself is not subject to auto-proxying! Only its target bean is.
		pf.addInterface(AopInfrastructureBean.class);

		this.proxy = pf.getProxy(cbf.getBeanClassLoader());
	}


	@Override
	public Object getObject() {
		if (this.proxy == null) {
			throw new FactoryBeanNotInitializedException();
		}
		return this.proxy;
	}

	@Override
	public Class<?> getObjectType() {
		if (this.proxy != null) {
			return this.proxy.getClass();
		}
		return this.scopedTargetSource.getTargetClass();
	}

	@Override
	public boolean isSingleton() {
		return true;
	}

}

2.2 Bean的实例化

不清楚Bean实例化可以参考【spring源码-5】bean的实例化(2)主逻辑 - 掘金 (juejin.cn)

2.2.1 preInstantiateSingletons()

@Override
public void preInstantiateSingletons() throws BeansException {
    if (logger.isTraceEnabled()) {
        logger.trace("Pre-instantiating singletons in " + this);
    }

    // Iterate over a copy to allow for init methods which in turn register new bean definitions.
    // While this may not be part of the regular factory bootstrap, it does otherwise work fine.
    // 所有beanName都缓存到beanDefinitionNames了
    List<String> beanNames = new ArrayList<>(this.beanDefinitionNames);

    // Trigger initialization of all non-lazy singleton beans...
    for (String beanName : beanNames) {
        //把父BeanDefinition里面的属性拿到子BeanDefinition中
        RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
        //如果不是抽象的,是单例的,是非懒加载的就实例化
        if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
            //判断bean是否实现了FactoryBean接口
            if (isFactoryBean(beanName)) {
                Object bean = getBean(FACTORY_BEAN_PREFIX + beanName);
                if (bean instanceof FactoryBean) {
                    FactoryBean<?> factory = (FactoryBean<?>) bean;
                    boolean isEagerInit;
                    if (System.getSecurityManager() != null && factory instanceof SmartFactoryBean) {
                        isEagerInit = AccessController.doPrivileged(
                                (PrivilegedAction<Boolean>) ((SmartFactoryBean<?>) factory)::isEagerInit,
                                getAccessControlContext());
                    }
                    else {
                        isEagerInit = (factory instanceof SmartFactoryBean &&
                                ((SmartFactoryBean<?>) factory).isEagerInit());
                    }
                    if (isEagerInit) {
                        getBean(beanName);
                    }
                }
            }
            else {
                //主要从这里进入,看看实例化过程
                getBean(beanName);
            }
        }
    }

    // Trigger post-initialization callback for all applicable beans...
    for (String beanName : beanNames) {
        ...
    }
}

循环BD实例化bean proxyMode= TARGET_CLASS

  • 如果BD是FactoryBean类型的(也就是proxyMode = TARGET_CLASS的时候),第一次走getBean(FACTORY_BEAN_PREFIX + beanName),FACTORY_BEAN_PREFIX 就是 "&",按照上面的例子就是 getBean(&user)

proxyMode=DEFAULT(默认)/NOproxyMode="prototype"

  • 此时BD不是FactoryBean类型的,第一次走getBean(beanName),此时的beanName = "user"

2.2.2 getBean()、doGetBean()

@SuppressWarnings("unchecked")
protected <T> T doGetBean(
        String name, @Nullable Class<T> requiredType, @Nullable Object[] args, boolean typeCheckOnly)
        throws BeansException {

    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.isTraceEnabled()) {
            if (isSingletonCurrentlyInCreation(beanName)) {
                logger.trace("Returning eagerly cached instance of singleton bean '" + beanName +
                        "' that is not fully initialized yet - a consequence of a circular reference");
            }
            else {
                logger.trace("Returning cached instance of singleton bean '" + beanName + "'");
            }
        }
        //该方法是FactoryBean入口
        bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
    }

    else {
        // 如果singletonObjects缓存里面没有
        // Fail if we're already creating this bean instance:
        // We're assumably within a circular reference.
        // 如果是scope 是Prototype的(多例的),校验是否有出现循环依赖,如果有则直接报错
        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 (parentBeanFactory instanceof AbstractBeanFactory) {
                return ((AbstractBeanFactory) parentBeanFactory).doGetBean(
                        nameToLookup, requiredType, args, typeCheckOnly);
            }
            else if (args != null) {
                // Delegation to parent with explicit args.
                return (T) parentBeanFactory.getBean(nameToLookup, args);
            }
            else if (requiredType != null) {
                // No args -> delegate to standard getBean method.
                return parentBeanFactory.getBean(nameToLookup, requiredType);
            }
            else {
                return (T) parentBeanFactory.getBean(nameToLookup);
            }
        }

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

        try {
            //父子BeanDefinition合并
            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);
                    try {
                        //实例化
                        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 {
                        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;
                    }
                });
                //该方法是FactoryBean接口的调用入口
                bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
            }
			// 多例
            else if (mbd.isPrototype()) {
                /**
                 * @Scope 注解的 value值是 prototype 进这
                 */
                // It's a prototype -> create a new instance.
                Object prototypeInstance = null;
                try {
                    beforePrototypeCreation(beanName);
                    prototypeInstance = createBean(beanName, mbd, args);
                }
                finally {
                    afterPrototypeCreation(beanName);
                }
                //该方法是FactoryBean接口的调用入口
                bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
            }
        	// 其他
            else {
                /**
                 * refresh
                 */
                String scopeName = mbd.getScope();
                if (!StringUtils.hasLength(scopeName)) {
                    /**
                     * 如果 scope 值不符合标准就抛异常
                     */
                    throw new IllegalStateException("No scope name defined for bean ´" + beanName + "'");
                }
                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, () -> {
                        /**
                         * 先把beanName放入缓存
                         */
                        beforePrototypeCreation(beanName);
                        try {
                            return createBean(beanName, mbd, args);
                        }
                        finally {
                            afterPrototypeCreation(beanName);
                        }
                    });
                    bean = getObjectForBeanInstance(scopedInstance, name, beanName, mbd);
                }
                catch (IllegalStateException ex) {
                    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",
                            ex);
                }
            }
        }
        catch (BeansException ex) {
            cleanupAfterBeanCreationFailure(beanName);
            throw ex;
        }
    }

    // Check if required type matches the type of the actual bean instance.
    if (requiredType != null && !requiredType.isInstance(bean)) {
        try {
            T convertedBean = getTypeConverter().convertIfNecessary(bean, requiredType);
            if (convertedBean == null) {
                throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
            }
            return convertedBean;
        }
        catch (TypeMismatchException ex) {
            if (logger.isTraceEnabled()) {
                logger.trace("Failed to convert bean '" + name + "' to required type '" +
                        ClassUtils.getQualifiedName(requiredType) + "'", ex);
            }
            throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
        }
    }
    return (T) bean;
}

proxyMode= TARGET_CLASS

  • 第一次进来,name = "&user",name经过处理(去掉"&")后得到 beanName = "user",根据"user"拿到的是上面新BD,就是代理BD,此时缓存没有bean,scope = "singleton",所以走单例逻辑得到实例对象(这种情况是个代理对象),然后第一次走getObjectForBeanInstance()
  • 第二次进来,就是测试代码中的 User user1 = applicationContext.getBean("user", User.class); 先从缓存拿,缓存有第一次进来创建的对象,拿到之后第二次调用getObjectForBeanInstance()
  • 第三次进来,就是测试代码中的 User user2 = applicationContext.getBean("user", User.class); 先从缓存拿,缓存有第一次进来创建的对象,拿到之后第三次调用getObjectForBeanInstance()

proxyMode=DEFAULT(默认)/NOproxyMode="prototype"

  • 第一次进来,name = "user",name经过处理beanName 还是 "user",根据"user"拿到BD,就是非代理的原BD,scope就是我们设置的"prototype",走多例的逻辑创建对象,然后第一次走getObjectForBeanInstance()

单例、多例逻辑的区别:单例在创建对象完成后调用了getSingleton()这个方法会将对象放入单例缓存中,doGetBean()会先去单例缓存获取,所以,单例的Bean之后获取的都是同一个对象,而多例的bean之后都会创建一个新的对象。

2.2.3 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 是以 & 开头的,并且不是 NullBean 而是 FactoryBean 类型的 返回入参 beanInstance(也就是代理对象)
*/
    if (BeanFactoryUtils.isFactoryDereference(name)) {
        if (beanInstance instanceof NullBean) {
            return beanInstance;
        }
        if (!(beanInstance instanceof FactoryBean)) {
            throw new BeanIsNotAFactoryException(beanName, beanInstance.getClass());
        }
        if (mbd != null) {
            mbd.isFactoryBean = true;
        }
        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.
    //如果实例不是FactoryBean类型的
    if (!(beanInstance instanceof FactoryBean)) {
        return beanInstance;
    }

    //如果代码能走下来,则说明 beanName不是以&开头,并且beanInstance是FactoryBean类型的
    Object object = null;
    if (mbd != null) {
        mbd.isFactoryBean = true;
    }
    else {
        //从缓存里面拿FactoryBean类型的实例
        object = getCachedObjectForFactoryBean(beanName);
    }
    if (object == null) {
        // Return bean instance from factory.
        FactoryBean<?> factory = (FactoryBean<?>) beanInstance;
        // Caches object obtained from FactoryBean if it is a singleton.
        if (mbd == null && containsBeanDefinition(beanName)) {
            mbd = getMergedLocalBeanDefinition(beanName);
        }
        boolean synthetic = (mbd != null && mbd.isSynthetic());
        
        object = getObjectFromFactoryBean(factory, beanName, !synthetic);
    }
    return object;
}

这个方法作用是处理FactoryBean。

  • 如果是FactoryBean,name 是以"&"开头的,例如name = "&user",就返回入参 beanInstance。
  • 如果是FactoryBean,name 不是以"&"开头的,例如name = "user",先从缓存factoryBeanObjectCache根据"user"获取,第一次肯定没有,调用 getObjectFromFactoryBean() 获取这个方法会调用到 beanInstance 的 getObject方法,得到实例然后放入缓存,下次再来就直接从缓存获取并返回。

proxyMode= TARGET_CLASS

  • 第一次进来,name = "&user",返回入参 beanInstance。
  • 第二次进来,name = "user",缓存factoryBeanObjectCache没有,就创建放入缓存并返回。
  • 第三次进来,name = "user",缓存factoryBeanObjectCache有,直接返回。

可以看出,user1 和 user2 虽然是两次获取的,但实际上是同一个代理对象。所以user1 == user2 是true,也就是当proxyMode= TARGET_CLASS 时,无论value是何值,User都是单例的

proxyMode=DEFAULT(默认)/NO

  • 第一次进来,name = "user",此时BD不是代理BD,Class就是User.class, 所以什么都不干直接返回,之后再进来也一样。

2.2.4 getObjectFromFactoryBean()

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) {
                //调用getObject方法
                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 {
                            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)) {
                        //把实例缓存到factoryBeanObjectCache map中,这个是单独缓存FactoryBean类型实例的map
                        this.factoryBeanObjectCache.put(beanName, object);
                    }
                }
            }
            return object;
        }
    }
    else {
        Object object = doGetObjectFromFactoryBean(factory, beanName);
        if (shouldPostProcess) {
            try {
                object = postProcessObjectFromFactoryBean(object, beanName);
            }
            catch (Throwable ex) {
                throw new BeanCreationException(beanName, "Post-processing of FactoryBean's object failed", ex);
            }
        }
        return object;
    }
}
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;
}

最终会在doGetObjectFromFactoryBean() 中调用到 factory.getObject()这个factory是新BD的代理对象也就是 ScopedProxyFactoryBean.class 见2.1.2,最终返回proxy,那这个proxy 又是在本类中setBeanFactory()中创建的,这个方法是继承了 BeanFactoryAware接口,还记得这个接口么,他就是bean实例化的后置处理,看这个堆栈是不是就想起来了,就是在对象创建完并且依赖注入之后调用的initializeBean(),也就是在第一次调用doGetBean()的时候就已经完成了代理对象的创建了,之后返回的也一直是这个对象。

image.png