回顾:
【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、scopeName | String | ""(默认)、singleton、prototype、...(自定义) |
| proxyMode | Enum(ScopedProxyMode) | DEFAULT(默认)、NO、INTERFACES、TARGET_CLASS |
给上述User实体类添加注解并设置参数,输出结果如下
| value | proxyMode | 输出结果 | |
|---|---|---|---|
| 示例1 | ""(默认) | DEFAULT(默认)/NO | true |
| 示例2 | singleton | DEFAULT(默认)/NO | true |
| 示例3 | prototype | DEFAULT(默认)/NO | false |
| 示例4 | ""(默认) | TARGET_CLASS | true |
| 示例5 | singleton | TARGET_CLASS | true |
| 示例6 | prototype | TARGET_CLASS | true |
二、@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注解,会判断注解的参数值:
- 若
proxyMode值是 DEFAULT(默认)/NO,会创建一个User类BD并注册。 - 若
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(默认)/NO , proxyMode="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(默认)/NO , proxyMode="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()的时候就已经完成了代理对象的创建了,之后返回的也一直是这个对象。