Spring源码分析(五)Bean生命周期源码解析3:获取Bean实例(DependsOn、单例/原型/其他Scope Bean)

继续上一节分析实例化所有非懒加载单例Bean流程,本节主要包含内容:

  • DependsOn注解的源码分析
  • 单例Bean、原型Bean、其他Scope Bean的源码分析

org.springframework.beans.factory.support.DefaultListableBeanFactory#preInstantiateSingletons

public void preInstantiateSingletons() throws BeansException {
    if (logger.isTraceEnabled()) {...}

    // 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.
    List<String> beanNames = new ArrayList<>(this.beanDefinitionNames);

    // Trigger initialization of all non-lazy singleton beans...
    for (String beanName : beanNames) {
        RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
        if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
            //FactoryBean逻辑,上节讲过了
            //这里会实例化FactoryBean本身,如果实现了SmartFactoryBean接口,并且isEagerInit=true
            //也会立即初始化FactoryBean.getObject的对象
            if (isFactoryBean(beanName)) {...}
            else {
                //这次走进getBean看下都干了啥
                getBean(beanName);
            }
        }
    }

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

本节主要讲getBean方法,getBean方法主要有三种用法,前两种之前都说过,再说一下第三种:
在这里插入图片描述

@Component
@Scope("prototype")
public class OrderService {
    private User user;
    //两个构造方法:
    public OrderService() {
        System.out.println(0);
    }
    public OrderService(User user) {
        System.out.println(1);
        this.user = user;
    }
    public void test() {
        System.out.println("OrderService test");
    }

}

OrderService有两个构造方法,而org.springframework.context.support.AbstractApplicationContext#getBean(java.lang.String, java.lang.Object…)方法的作用就是,指定使用显式带参数的构造函数来创建Bean
在这里插入图片描述

入口getBean

回过来继续看源码:
org.springframework.beans.factory.support.AbstractBeanFactory#getBean(java.lang.String)

public Object getBean(String name) throws BeansException {
    return doGetBean(name, null, null, false);
}
protected <T> T doGetBean(
        String name, @Nullable Class<T> requiredType, @Nullable Object[] args, boolean typeCheckOnly)
        throws BeansException {

    //1.解析获取Bean的规范名称
    //  传进来的name有多种情况:
    //		name可能是xxx或&xxx,如果name是&xxx,beanName就是xxx
    //		name也可能是别名,那么beanName就是id
    String beanName = transformedBeanName(name);
    Object beanInstance;

    // Eagerly check singleton cache for manually registered singletons.
    //2.单例池获取bean
    //	提前检查单例池缓存,就算是原型bean,也会走一次,可能考虑到大多情况都是单例bean
    Object sharedInstance = getSingleton(beanName);
    if (sharedInstance != null && args == null) {
        if (logger.isTraceEnabled()) {...}
        //getObjectForBeanInstance上一节说过,专门为了特殊处理FactoryBean的情况
        beanInstance = getObjectForBeanInstance(sharedInstance, name, beanName, null);
    }
	//第一次getBean单例池里肯定没有,就会走创建逻辑
    else {
        // Fail if we're already creating this bean instance:
        // We're assumably within a circular reference.
        if (isPrototypeCurrentlyInCreation(beanName)) {...}

        // Check if bean definition exists in this factory.
        BeanFactory parentBeanFactory = getParentBeanFactory();
        // 判断当前容器里是否有beanName对应的BeanDefinition
        // 没有的话就从父工厂里获取、创建
        if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {...}

        if (!typeCheckOnly) {...}

        StartupStep beanCreation = this.applicationStartup.start("spring.beans.instantiate")
                .tag("beanName", name);
        try {
            if (requiredType != null) {...}
            //获取合并之后的BeanDefinition
            RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
            //检查BeanDefinition是否是抽象的,抽象直接报错
            checkMergedBeanDefinition(mbd, beanName, args);

            //3.DependsOn依赖处理
            // Guarantee initialization of beans that the current bean depends on.
            String[] dependsOn = mbd.getDependsOn();
            if (dependsOn != null) {
                //dependsOn表示当前beanName所依赖的
                //	要求当前Bean创建之前dependsOn所依赖的Bean都必须创建好了
                for (String dep : dependsOn) {
                    //beanName是不是被dep依赖了,如果是则出现了循环依赖
                    if (isDependent(beanName, dep)) {
                        throw new BeanCreationException(mbd.getResourceDescription(), beanName,
                                "Circular depends-on relationship between '" + beanName + "' and '" + dep + "'");
                    }
                    //dep被beanName依赖了则存入dependentBeanMap中
                    //dep为key,beanName为value
                    registerDependentBean(dep, beanName);
                    try {
                        //创建所依赖的bean
                        getBean(dep);
                    }
                    catch (NoSuchBeanDefinitionException ex) {...}
                }
            }

            // Create bean instance.
            // 4.创建Bean实例
            // 4.1 单例bean处理
            if (mbd.isSingleton()) {
                //传入一个ObjectFactory工厂
                sharedInstance = getSingleton(beanName, () -> {
                    try {
                        // 5.核心创建方法
                        return createBean(beanName, mbd, args);
                    }
                    catch (BeansException ex) {...}
                });
                //无论单例、原型、其他Scope,创建的Bean都有可能是FactoryBean,所以专门处理一下,获取真正的Bean对象(上一节FactoryBean里讲过)
                beanInstance = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
            }
        	//4.2 原型bean处理
            else if (mbd.isPrototype()) {
                // It's a prototype -> create a new instance.
                Object prototypeInstance = null;
                try {
                    //记录当前原型bean正在创建中
                    beforePrototypeCreation(beanName);
                    //创建原型bean,不用放到单例池
                    // 5.核心创建方法
                    prototypeInstance = createBean(beanName, mbd, args);
                }
                finally {
                    //去除当前原型bean正在创建中的标记
                    afterPrototypeCreation(beanName);
                }
                //无论单例、原型、其他Scope,创建的Bean都有可能是FactoryBean,所以专门处理一下,获取真正的Bean对象(上一节FactoryBean里讲过)
                beanInstance = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
            }
        	//4.3 其他scope情况处理
            else {
                String scopeName = mbd.getScope();
                if (!StringUtils.hasLength(scopeName)) {
                    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 {
                    //和单例Bean的代码风格很像,也是传入一个ObjectFactory
        			//先判断当前作用域中是否有这个对象,有直接返回
        			//没有,则利用ObjectFactory创建对象,再放入作用域中保存
                    Object scopedInstance = scope.get(beanName, () -> {
                        //标记正在创建中
                        beforePrototypeCreation(beanName);
                        try {
                            // 5.核心创建方法
                            return createBean(beanName, mbd, args);
                        }
                        finally {
                            //去除创建中标记
                            afterPrototypeCreation(beanName);
                        }
                    });
                    //无论单例、原型、其他Scope,创建的Bean都有可能是FactoryBean,所以专门处理一下,获取真正的Bean对象(上一节FactoryBean里讲过)
                    beanInstance = getObjectForBeanInstance(scopedInstance, name, beanName, mbd);
                }
                catch (IllegalStateException ex) {...}
            }
        }
        catch (BeansException ex) {...}
        finally {...}
    }
    return adaptBeanInstance(name, beanInstance, requiredType);
}

1. 解析获取Bean的规范名称

应用场景

@Bean设置别名:

@ComponentScan("com.yth")
public class AppConfig {
    
    @Bean({"user1", "user2", "user3"})
    public User user() {
        return new User();
    }
}

xml方式设置别名:

//多个别名之间,可用空格、逗号、分号,或者三者混合
<bean id="user" name="user1 user2 user3" class="com.yth.service.User"/>

Spring底层针对别名,存了一个aliasMap:key是别名,value是beanName

源码分析

org.springframework.beans.factory.support.AbstractBeanFactory#transformedBeanName

getBean传进来的name可能有多种情况(别名、&xxx、beanName),不管什么情况,通过该方法都会找到对应Bean的规范名称

protected String transformedBeanName(String name) {
    //BeanFactoryUtils.transformedBeanName处理&xxxx这种想要获取BeanFactory本身的情况
    //canonicalName处理别名的情况
    return canonicalName(BeanFactoryUtils.transformedBeanName(name));
}

org.springframework.beans.factory.BeanFactoryUtils#transformedBeanName

public static String transformedBeanName(String name) {
    Assert.notNull(name, "'name' must not be null");
    if (!name.startsWith(BeanFactory.FACTORY_BEAN_PREFIX)) {
        return name;
    }
	//FACTORY_BEAN_PREFIX = "&";
    return transformedBeanNameCache.computeIfAbsent(name, beanName -> {
        do {
            beanName = beanName.substring(BeanFactory.FACTORY_BEAN_PREFIX.length());
        }
        //由此可见&&&&&&&&这个也行
        while (beanName.startsWith(BeanFactory.FACTORY_BEAN_PREFIX));
        return beanName;
    });
}

org.springframework.core.SimpleAliasRegistry#canonicalName

public String canonicalName(String name) {
    String canonicalName = name;
    // Handle aliasing...
    String resolvedName;
    do {
        //aliasMap,key是别名,value是beanName
        //这里做了do while,考虑到一种复杂情况,给别名起别名...
        resolvedName = this.aliasMap.get(canonicalName);
        if (resolvedName != null) {
            canonicalName = resolvedName;
        }
    }
    while (resolvedName != null);
    return canonicalName;
}

2. 单例池获取bean

org.springframework.beans.factory.support.DefaultSingletonBeanRegistry#getSingleton(java.lang.String)

public Object getSingleton(String beanName) {
    return getSingleton(beanName, true);
}

protected Object getSingleton(String beanName, boolean allowEarlyReference) {
    // Quick check for existing instance without full singleton lock
    // singletonObjects就是单例池,
    Object singletonObject = this.singletonObjects.get(beanName);
    // 后面逻辑暂时不用关注,以后讲循环依赖会说
    if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {...}
    return singletonObject;
}

singletonObjects就是单例池
在这里插入图片描述

3. DependsOn依赖处理

应用场景

@Component
//告诉Spring,如果想要创建OrderService对象,则需要先把beanName为user的对象创建出来
@DependsOn("user")
public class OrderService {
    public void test() {
        System.out.println("OrderService test");
    }
}

@Component
public class User {
    public User() {
        System.out.println(1);
    }
}

在这里插入图片描述

@Autowired也表示一种依赖关系

源码分析

if (dependsOn != null) {
    //dependsOn表示当前beanName所依赖的
    //	要求当前Bean创建之前dependsOn所依赖的Bean都必须创建好了
    for (String dep : dependsOn) {
        //3.1 beanName是不是被dep依赖了,如果是则出现了循环依赖
        if (isDependent(beanName, dep)) {
            throw new BeanCreationException(mbd.getResourceDescription(), beanName,
                    "Circular depends-on relationship between '" + beanName + "' and '" + dep + "'");
        }
        //3.2 存储依赖关系
        //dep被beanName依赖了则存入dependentBeanMap中
        //dep为key,beanName为value
        registerDependentBean(dep, beanName);
        try {
            //创建所依赖的bean
            getBean(dep);
        }
        catch (NoSuchBeanDefinitionException ex) {...}
    }
}

3.1 判断DependsOn是否出现循环依赖

DependsOn注解引发的循环依赖是没法解决的,直接抛异常。
org.springframework.beans.factory.support.DefaultSingletonBeanRegistry#isDependent(java.lang.String, java.lang.String)

//判断dependentBeanName是不是依赖了beanName,true:是
protected boolean isDependent(String beanName, String dependentBeanName) {
    synchronized (this.dependentBeanMap) {
        return isDependent(beanName, dependentBeanName, null);
    }
}

private boolean isDependent(String beanName, String dependentBeanName, @Nullable Set<String> alreadySeen) {
    if (alreadySeen != null && alreadySeen.contains(beanName)) {
        //依赖关系形成的链条又走到了"自己",说明之前已经处理过了,不依赖,直接结束。
        return false;
    }
    //获取当前beanName的规范beanName
    String canonicalName = canonicalName(beanName);
    //获取当前beanName被哪些Bean依赖了
    Set<String> dependentBeans = this.dependentBeanMap.get(canonicalName);
    if (dependentBeans == null) {
        return false;
    }
    if (dependentBeans.contains(dependentBeanName)) {
        //dependentBeanName是被当前beanName依赖的Bean
        //dependentBeans是依赖当前beanName的Bean
        //包含说明出现循环依赖
        return true;
    }
    for (String transitiveDependency : dependentBeans) {
        if (alreadySeen == null) {
            alreadySeen = new HashSet<>();
        }
        alreadySeen.add(beanName);
        //递归处理,判断依赖当前beanName的bean会不会依赖dependentBeanName
        if (isDependent(transitiveDependency, dependentBeanName, alreadySeen)) {
            return true;
        }
    }
    return false;
}

有点绕,看个图:
在这里插入图片描述
在这里插入图片描述

3.2 存储@DependsOn依赖关系

org.springframework.beans.factory.support.DefaultSingletonBeanRegistry#registerDependentBean

注意传进来的入参,beanName是依赖dep的
在这里插入图片描述

public void registerDependentBean(String beanName, String dependentBeanName) {
    //此时beanName其实是dep,dependentBeanName为beanName
    //dependentBeanName依赖beanName
    String canonicalName = canonicalName(beanName);

    synchronized (this.dependentBeanMap) {
        //dependentBeanMap,表示某个Bean被哪些Bean依赖了
        Set<String> dependentBeans =
                this.dependentBeanMap.computeIfAbsent(canonicalName, k -> new LinkedHashSet<>(8));
        if (!dependentBeans.add(dependentBeanName)) {
            //添加失败,则说明dependentBeans已经存在了,之前处理过了
            return;
        }
    }

    synchronized (this.dependenciesForBeanMap) {
        //dependenciesForBean,表示某个Bean依赖了哪些Bean
        Set<String> dependenciesForBean =
                this.dependenciesForBeanMap.computeIfAbsent(dependentBeanName, k -> new LinkedHashSet<>(8));
        dependenciesForBean.add(canonicalName);
    }
}

两个map,双向存储:

  • dependentBeanMap,表示某个Bean被哪些Bean依赖了
  • dependenciesForBean,表示某个Bean依赖了哪些Bean

4. 创建Bean实例

4.1 单例Bean处理

// Create bean instance.
// 4.创建Bean
// 4.1 单例bean处理
if (mbd.isSingleton()) {
    //lambda表达式,传入一个ObjectFactory工厂
    //getSingleton:先从单例池获取Bean,获取不到则利用ObjectFactory工厂创建Bean,再放到单例池
    sharedInstance = getSingleton(beanName, () -> {
        try {
            return createBean(beanName, mbd, args);
        }
        catch (BeansException ex) {...}
    });
    //无论单例、原型、其他Scope,创建的Bean都有可能是FactoryBean,所以专门处理一下,获取真正的Bean对象
    //上一节FactoryBean里讲过
    beanInstance = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
}

org.springframework.beans.factory.support.DefaultSingletonBeanRegistry#getSingleton(java.lang.String, org.springframework.beans.factory.ObjectFactory<?>)

public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) {
    Assert.notNull(beanName, "Bean name must not be null");
    synchronized (this.singletonObjects) {
        //先从单例池获取
        Object singletonObject = this.singletonObjects.get(beanName);
        if (singletonObject == null) {
            if (this.singletonsCurrentlyInDestruction) {...}
            if (logger.isDebugEnabled()) {...}
            //记录当前单例Bean正在创建中(和循环依赖有关,以后讲。)
            beforeSingletonCreation(beanName);
            boolean newSingleton = false;
            boolean recordSuppressedExceptions = (this.suppressedExceptions == null);
            if (recordSuppressedExceptions) {...}
            try {
                //核心在这,工厂创建单例bean
                singletonObject = singletonFactory.getObject();
                newSingleton = true;
            }
            catch (IllegalStateException ex) {...}
            catch (BeanCreationException ex) {...}
            finally {
                if (recordSuppressedExceptions) {...}
                //去除创建中标记
                afterSingletonCreation(beanName);
            }
            // 添加到单例池
            if (newSingleton) {
                addSingleton(beanName, singletonObject);
            }
        }
        return singletonObject;
    }
}
protected void addSingleton(String beanName, Object singletonObject) {
    synchronized (this.singletonObjects) {
        //添加到单例池
        this.singletonObjects.put(beanName, singletonObject);
        //下面这些和循环依赖有关,以后讲
        this.singletonFactories.remove(beanName);
        this.earlySingletonObjects.remove(beanName);
        this.registeredSingletons.add(beanName);
    }
}

4.2 原型Bean处理

//4.2 原型bean处理
else if (mbd.isPrototype()) {
    // It's a prototype -> create a new instance.
    Object prototypeInstance = null;
    try {
        //记录(标记)当前原型bean正在创建中
        beforePrototypeCreation(beanName);
        //创建原型bean,仅仅创建,也没存储到任何地方
        prototypeInstance = createBean(beanName, mbd, args);
    }
    finally {
        //去除当前原型bean正在创建中的标记
        afterPrototypeCreation(beanName);
    }
    //无论单例、原型、其他Scope,创建的Bean都有可能是FactoryBean,所以专门处理一下,获取真正的Bean对象
    //上一节FactoryBean里讲过
    beanInstance = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
}

beforePrototypeCreation/afterPrototypeCreation利用ThreadLocal做了一个记录标记正在创建中:
在这里插入图片描述

protected void beforePrototypeCreation(String beanName) {
    Object curVal = this.prototypesCurrentlyInCreation.get();
    if (curVal == null) {
        this.prototypesCurrentlyInCreation.set(beanName);
    }
    else if (curVal instanceof String) {
        Set<String> beanNameSet = new HashSet<>(2);
        beanNameSet.add((String) curVal);
        beanNameSet.add(beanName);
        this.prototypesCurrentlyInCreation.set(beanNameSet);
    }
    else {
        Set<String> beanNameSet = (Set<String>) curVal;
        beanNameSet.add(beanName);
    }
}

protected void beforePrototypeCreation(String beanName) {
    Object curVal = this.prototypesCurrentlyInCreation.get();
    if (curVal == null) {
        this.prototypesCurrentlyInCreation.set(beanName);
    }
    else if (curVal instanceof String) {
        Set<String> beanNameSet = new HashSet<>(2);
        beanNameSet.add((String) curVal);
        beanNameSet.add(beanName);
        this.prototypesCurrentlyInCreation.set(beanNameSet);
    }
    else {
        Set<String> beanNameSet = (Set<String>) curVal;
        beanNameSet.add(beanName);
    }
}

4.3 其他Scope Bean处理

使用场景

可以利用@Scope注解可设置Bean的作用域, SpringWeb封装了一下:@RequestScope、@SessionScope、@ApplicationScope…
在这里插入图片描述

源码分析

//4.3 其他scope情况处理
else {
    String scopeName = mbd.getScope();
    if (!StringUtils.hasLength(scopeName)) {
        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 {
        //和单例Bean的代码风格很像,也是传入一个ObjectFactory
        //先判断当前作用域中是否有这个对象,有直接返回
        //没有,则利用ObjectFactory创建对象,再放入作用域中保存
        Object scopedInstance = scope.get(beanName, () -> {
            //标记正在创建中
            beforePrototypeCreation(beanName);
            try {
                return createBean(beanName, mbd, args);
            }
            finally {
                //去除创建中标记
                afterPrototypeCreation(beanName);
            }
        });
        //无论单例、原型、其他Scope,创建的Bean都有可能是FactoryBean,所以专门处理一下,获取真正的Bean对象
        //上一节FactoryBean里讲过
        beanInstance = getObjectForBeanInstance(scopedInstance, name, beanName, mbd);
    }
    catch (IllegalStateException ex) {
        throw new ScopeNotActiveException(beanName, scopeName, ex);
    }
}

比如request域,底层就是利用request.getAttribute(“beanName”)先判断有没有对象,没有再调用ObjectFactory.getObject创建,然后再request.setAttribute保存:
在这里插入图片描述

get方法在父抽象类中:

public abstract class AbstractRequestAttributesScope implements Scope {

	@Override
	public Object get(String name, ObjectFactory<?> objectFactory) {
		RequestAttributes attributes = RequestContextHolder.currentRequestAttributes();
        //name就是Bean的名字
		Object scopedObject = attributes.getAttribute(name, getScope());
		if (scopedObject == null) {
            //不存在则利用objectFactory创建,然后在放到作用域中
			scopedObject = objectFactory.getObject();
			attributes.setAttribute(name, scopedObject, getScope());
			// Retrieve object again, registering it for implicit session attribute updates.
			// As a bonus, we also allow for potential decoration at the getAttribute level.
			Object retrievedObject = attributes.getAttribute(name, getScope());
			if (retrievedObject != null) {...}
		}
		return scopedObject;
	}
    ...
}

看下attributes.getAttribute实现,我们只关注Servlet的实现
org.springframework.web.context.request.ServletRequestAttributes#getAttribute

public Object getAttribute(String name, int scope) {
    if (scope == SCOPE_REQUEST) {
        if (!isRequestActive()) {...}
        //request,这
        return this.request.getAttribute(name);
    }
    else {
        HttpSession session = getSession(false);
        if (session != null) {
            try {
                //session,这
                Object value = session.getAttribute(name);
                if (value != null) {
                    this.sessionAttributesToUpdate.put(name, value);
                }
                return value;
            }
            catch (IllegalStateException ex) {...}
        }
        return null;
    }
}

set同理:org.springframework.web.context.request.ServletRequestAttributes#setAttribute

public void setAttribute(String name, Object value, int scope) {
    if (scope == SCOPE_REQUEST) {
        if (!isRequestActive()) {
            throw new IllegalStateException(
                    "Cannot set request attribute - request is not active anymore!");
        }
        this.request.setAttribute(name, value);
    }
    else {
        HttpSession session = obtainSession();
        this.sessionAttributesToUpdate.remove(name);
        session.setAttribute(name, value);
    }
}

另外Scope是什么时候注册的?如果引入了Spring-web的包:
org.springframework.web.context.support.WebApplicationContextUtils#registerWebApplicationScopes(org.springframework.beans.factory.config.ConfigurableListableBeanFactory, javax.servlet.ServletContext)
在这里插入图片描述

5. 创建Bean对象

核心方法
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#createBean(java.lang.String, org.springframework.beans.factory.support.RootBeanDefinition, java.lang.Object[])

下节讲。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

犬豪

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值