前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Spring 源码分析(二)之 Spring IOC 容器源码分析

Spring 源码分析(二)之 Spring IOC 容器源码分析

作者头像
zoro
发布2019-04-11 15:21:40
5211
发布2019-04-11 15:21:40
举报
文章被收录于专栏:Java开发者

Spring 源码分析(二)之 Spring IOC 容器源码分析

在之前介绍了Spring IOC 容器在项目中的作用

  • 将对象的构建统一解决
  • 并自动维护对象的依赖关系,从而降低实现成本
  • ...

源码介绍之前,看几个问题:

  • Bean的承载对象是什么?
  • Bean的定义如何存储的?
  • Bean工厂是如何生产bean的?
  • Bean的依赖关系由谁来解决?
  • Bean工厂和ApplicationContext的区别?
Bean的构建过程

spring.xml文件中保存了我们对Bean的描述配置,BeanFactory会读取这些配置然后生成对应的Bean。

这些配置信息最后由BeanDefinition来承载。

BeanDefinition(Bean定义)

IOC实现中,我们在xml中的描述的Bean信息最后都将保存至BeanDefinition对象中,其中xml bean与BeanDefinition是一对一的关系。

xml bean的属性配置与BeanDefinition对应关系

XML-Bean

BeanDefinition

class

beanClassName

scope

SCOPE_SINGLETON、SCOPE_PROTOTYPE

lazy-init

AbstractBeanDefinition.lazyInit

constructor-arg

AbstractBeanDefinition.ConstructorArgument

property

AbstractBeanDefinition.propertyValues

factory-method

AbstractBeanDefinition.factoryMethondName

destroy-method

AbstractBeanDefinition.destroyMethodName

init-method

AbstractBeanDefinition.initMethodName

autowire

AbstractBeanDefinition.autowireMode

id

name

BeanDefinition.java

代码语言:javascript
复制
public interface BeanDefinition extends AttributeAccessor, BeanMetadataElement {
    String SCOPE_SINGLETON = "singleton";
    String SCOPE_PROTOTYPE = "prototype";
    int ROLE_APPLICATION = 0;
    int ROLE_SUPPORT = 1;
    int ROLE_INFRASTRUCTURE = 2;
    ...
}

AbstractBeanDefinition.java

代码语言:javascript
复制
public abstract class AbstractBeanDefinition extends BeanMetadataAttributeAccessor implements BeanDefinition, Cloneable {
    public static final String SCOPE_DEFAULT = "";
    public static final int AUTOWIRE_NO = 0;
    public static final int AUTOWIRE_BY_NAME = 1;
    public static final int AUTOWIRE_BY_TYPE = 2;
    public static final int AUTOWIRE_CONSTRUCTOR = 3;
    /** @deprecated */
    @Deprecated
    public static final int AUTOWIRE_AUTODETECT = 4;
    public static final int DEPENDENCY_CHECK_NONE = 0;
    public static final int DEPENDENCY_CHECK_OBJECTS = 1;
    public static final int DEPENDENCY_CHECK_SIMPLE = 2;
    public static final int DEPENDENCY_CHECK_ALL = 3;
    public static final String INFER_METHOD = "(inferred)";
    private volatile Object beanClass;
    private String scope;
    private boolean abstractFlag;
    private boolean lazyInit;
    private int autowireMode;
    private int dependencyCheck;
    private String[] dependsOn;
    private boolean autowireCandidate;
    private boolean primary;
    private final Map<String, AutowireCandidateQualifier> qualifiers;
    private boolean nonPublicAccessAllowed;
    private boolean lenientConstructorResolution;
    private String factoryBeanName;
    private String factoryMethodName;
    private ConstructorArgumentValues constructorArgumentValues;
    private MutablePropertyValues propertyValues;
    private MethodOverrides methodOverrides;
    private String initMethodName;
    private String destroyMethodName;
    private boolean enforceInitMethod;
    private boolean enforceDestroyMethod;
    private boolean synthetic;
    private int role;
    private String description;
    private Resource resource;
    ...
}

BeanDefinitionRegistry(Bean注册器) 在上面没有看到xml bean中的id、name属性对应在bean定义中,原因是id其作为当前bean的存储key注册到BeanDefinitionRegistry注册器中。name作为别名key注册到AliasRegistry注册中心。其最后都是指向对象的BeanDefinition。

BeanDefinitionRegistry.java

代码语言:javascript
复制
public interface BeanDefinitionRegistry extends AliasRegistry {
    void registerBeanDefinition(String var1, BeanDefinition var2) throws BeanDefinitionStoreException;

    void removeBeanDefinition(String var1) throws NoSuchBeanDefinitionException;

    BeanDefinition getBeanDefinition(String var1) throws NoSuchBeanDefinitionException;

    boolean containsBeanDefinition(String var1);

    String[] getBeanDefinitionNames();

    int getBeanDefinitionCount();

    boolean isBeanNameInUse(String var1);
}

AliasRegistry.java

代码语言:javascript
复制
public interface AliasRegistry {
    void registerAlias(String var1, String var2);

    void removeAlias(String var1);

    boolean isAlias(String var1);

    String[] getAliases(String var1);
}

BeanDefinitionReader(Bean定义读取) 前面知道了BeanDefinition存储了xml bean信息,而BeanDefinitionRegistry基于id和name保存bean的定义,下面是xml bean到BeanDefinition然后注册到BeanDefinitionRegistry整个过程。

分为3步:

1、BeanDefinitionReader读取spring.xml

2、读取后创建BeanDefinition

3、创建好后注册到BeanDefinitionRegister

BeanDefinitionReader.java

代码语言:javascript
复制
public interface BeanDefinitionReader {
    //获取注册器
    BeanDefinitionRegistry getRegistry();
    //获取资源装载器
    ResourceLoader getResourceLoader();
    //获取bean类加载器
    ClassLoader getBeanClassLoader();

    BeanNameGenerator getBeanNameGenerator();
    //基于资源装载Bean定义并注册到注册器
    int loadBeanDefinitions(Resource var1) throws BeanDefinitionStoreException;
    
    int loadBeanDefinitions(Resource... var1) throws BeanDefinitionStoreException;
    //基于资源路径装载Bean定义并注册到注册器
    int loadBeanDefinitions(String var1) throws BeanDefinitionStoreException;

    int loadBeanDefinitions(String... var1) throws BeanDefinitionStoreException;
}

装载过程demo

代码语言:javascript
复制
package com.demo.spring;

import org.springframework.beans.factory.support.BeanDefinitionReader;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.beans.factory.support.SimpleBeanDefinitionRegistry;
import org.springframework.beans.factory.xml.XmlBeanDefinitionReader;
import org.springframework.core.io.DefaultResourceLoader;
import org.springframework.core.io.Resource;

import java.util.Arrays;

/**
 * com.demo.spring
 *
 * @author Zyy
 * @date 2019/2/13 11:34
 */
public class BeanDefinitionReaderTest {

    public static void main(String[] args) {
        //创建一个简单注册器
        BeanDefinitionRegistry registry = new SimpleBeanDefinitionRegistry();
        //创建bean定义读取器
        BeanDefinitionReader reader = new XmlBeanDefinitionReader(registry);
        //创建资源读取器
        DefaultResourceLoader resourceLoader = new DefaultResourceLoader();
        //获取资源
        Resource resource = resourceLoader.getResource("spring.xml");
        //装载类定义
        reader.loadBeanDefinitions(resource);
        //打印构建bean名称
        System.out.println(Arrays.toString(registry.getBeanDefinitionNames()));
    }
}

运行结果

代码语言:javascript
复制
[di, driver, com.demo.spring.HelloSpring#0, com.demo.spring.LookUpTest#0, helloSpring, com.demo.spring.DI#1, com.demo.spring.DI#0, helloByName]

如果未给bean设置id则:class+#+索引,来标识id

代码语言:javascript
复制
com.demo.spring.HelloSpring#0

打印一下bean定义信息

spring.xml

代码语言:javascript
复制
 <bean id="di" name="di2" lazy-init="false" class="com.demo.spring.DI" scope="singleton" init-method="init" destroy-method="destroy"/>

打印语句:

代码语言:javascript
复制
System.out.println(registry.getBeanDefinition("di"));
System.out.println(registry.getAliases("di2"));

结果信息:

代码语言:javascript
复制
Generic bean: class [com.demo.spring.DI]; scope=singleton; abstract=false; lazyInit=false; autowireMode=0; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=null; factoryMethodName=null; initMethodName=init; destroyMethodName=destroy; defined in class path resource [spring.xml]
[Ljava.lang.String;@73a28541
BeanFactory(bean工厂)

有了Bean的定义,则下面可以用BeanFactory来进行构建bean。

BeanFactory.java

代码语言:javascript
复制
public interface BeanFactory {

    String FACTORY_BEAN_PREFIX = "&";
    //基于id或name获取一个bean
    Object getBean(String name) throws BeansException;
    //基于bean的类别获取bean(如果出现多个该类的实例,则会报错)但是可以指定primary="true"调整优先级来解决该报错
    <T> T getBean(String name, Class<T> requiredType) throws BeansException;
    
    <T> T getBean(Class<T> requiredType) throws BeansException;
    //基于名词获取一个bean,并覆盖默认的构造参数
    Object getBean(String name, Object... args) throws BeansException;

    <T> T getBean(Class<T> requiredType, Object... args) throws BeansException;

    boolean containsBean(String name);

    boolean isSingleton(String name) throws NoSuchBeanDefinitionException;

    boolean isPrototype(String name) throws NoSuchBeanDefinitionException;
    //指定bean与指定class是否匹配
    boolean isTypeMatch(String name, ResolvableType typeToMatch) throws NoSuchBeanDefinitionException;

    boolean isTypeMatch(String name, Class<?> typeToMatch) throws NoSuchBeanDefinitionException;


    Class<?> getType(String name) throws NoSuchBeanDefinitionException;

    String[] getAliases(String name);

}

测试demo如下:

代码语言:javascript
复制
package com.demo.spring;

import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.beans.factory.xml.XmlBeanDefinitionReader;
import org.springframework.core.io.DefaultResourceLoader;

/**
 * com.demo.spring
 *
 * @author Zyy
 * @date 2019/2/13 12:19
 */
public class BeanFactoryTest {

    public static void main(String[] args) {
        //注册中心
        DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
        //读取器
        XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(beanFactory);
        //设置资源加载器
        reader.setResourceLoader(new DefaultResourceLoader());
        //装载构建bean的定义
        reader.loadBeanDefinitions("spring.xml");
        //打印
        System.out.println(beanFactory.getBean("di"));
        System.out.println(beanFactory.getBean("di2"));
    }
}

当getBean时,看下堆栈信息,如下

代码语言:javascript
复制
 at org.springframework.beans.BeanUtils.instantiateClass(BeanUtils.java:142)
  at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:89)
  at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateBean(AbstractAutowireCapableBeanFactory.java:1147)
  at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1099)
  at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:513)
  at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:483)
  at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:306)
  at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230)
  - locked <0x593> (a java.util.concurrent.ConcurrentHashMap)
  at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:302)
  at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:197)
  at com.demo.spring.BeanFactoryTest.main(BeanFactoryTest.java:25)

看具体调用方法

代码语言:javascript
复制
instantiateClass:142, BeanUtils (org.springframework.beans)
instantiate:89, SimpleInstantiationStrategy (org.springframework.beans.factory.support)
instantiateBean:1147, AbstractAutowireCapableBeanFactory (org.springframework.beans.factory.support)
createBeanInstance:1099, AbstractAutowireCapableBeanFactory (org.springframework.beans.factory.support)
doCreateBean:513, AbstractAutowireCapableBeanFactory (org.springframework.beans.factory.support)
createBean:483, AbstractAutowireCapableBeanFactory (org.springframework.beans.factory.support)
getObject:306, AbstractBeanFactory$1 (org.springframework.beans.factory.support)
getSingleton:230, DefaultSingletonBeanRegistry (org.springframework.beans.factory.support)
doGetBean:302, AbstractBeanFactory (org.springframework.beans.factory.support)
getBean:197, AbstractBeanFactory (org.springframework.beans.factory.support)
main:25, BeanFactoryTest (com.demo.spring)

逐个点进去查看

代码语言:javascript
复制
org.springframework.beans.factory.support.AbstractBeanFactory#getBean(java.lang.String)

@Override
public Object getBean(String name) throws BeansException {
    return doGetBean(name, null, null, false);
}

AbstractBeanFactory#getBean中继续调用doGetBean,查看doGetBean,由于其中代码太多,删除检查判断,只保留核心代码

代码语言:javascript
复制
org.springframework.beans.factory.support.AbstractBeanFactory#doGetBean

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

    final String beanName = transformedBeanName(name);
    Object bean;

    // Eagerly check singleton cache for manually registered singletons.
    //从单例缓存中获取
    Object sharedInstance = getSingleton(beanName);
    if (sharedInstance != null && args == null) {
        bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
    } else {
        
        // 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);
            }
        }

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

        try {
            
            // Create bean instance.
            //mbd -> RootBeanDefinition
            //判断是否单例
            if (mbd.isSingleton()) {
                sharedInstance = getSingleton(beanName, new ObjectFactory<Object>() {
                    @Override
                    public Object getObject() throws BeansException {
                        try {
                            return createBean(beanName, mbd, args);
                        }
                        catch (BeansException ex) {
                            ...
                        }
                    }
                });
                bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
            } else if (mbd.isPrototype()) {
                // It's a prototype -> create a new instance.
                Object prototypeInstance = null;
                try {
                    beforePrototypeCreation(beanName);
                    prototypeInstance = createBean(beanName, mbd, args);
                }
                finally {
                    afterPrototypeCreation(beanName);
                }
                bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
            }

            else {
                String scopeName = mbd.getScope();
                final Scope scope = this.scopes.get(scopeName);
                if (scope == null) {
                    throw new IllegalStateException("No Scope registered for scope name '" + scopeName + "'");
                }
                try {
                    Object scopedInstance = scope.get(beanName, new ObjectFactory<Object>() {
                        @Override
                        public Object getObject() throws BeansException {
                            beforePrototypeCreation(beanName);
                            try {
                                return createBean(beanName, mbd, args);
                            }
                            finally {
                                afterPrototypeCreation(beanName);
                            }
                        }
                    });
                    bean = getObjectForBeanInstance(scopedInstance, name, beanName, mbd);
                }
                catch (IllegalStateException ex) {
                    ...
                }
            }
        }
        catch (BeansException ex) {
            ...
        }
    }

    return (T) bean;
}

其中

代码语言:javascript
复制
Object sharedInstance = getSingleton(beanName);


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

protected Object getSingleton(String beanName, boolean allowEarlyReference) {
        Object singletonObject = this.singletonObjects.get(beanName);
        //如果取到的为null且判断是正在创建
        if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
            //则锁住map
            synchronized (this.singletonObjects) {
                //从正在创建的earlySingletonObjects这个map中去取
                singletonObject = this.earlySingletonObjects.get(beanName);
                //如果还是取不到
                if (singletonObject == null && allowEarlyReference) {
                    //从工厂获取
                    ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
                    //如果获取到
                    if (singletonFactory != null) {
                        singletonObject = singletonFactory.getObject();
                        //获取到则放到缓存中
                        this.earlySingletonObjects.put(beanName, singletonObject);
                        //从工厂中移除
                        this.singletonFactories.remove(beanName);
                    }
                }
            }
        }
        return (singletonObject != NULL_OBJECT ? singletonObject : null);
    }

其中singletonObjects、earlySingletonObjects、singletonFactories均是一个map

代码语言:javascript
复制
private final Map<String, Object> singletonObjects = new ConcurrentHashMap<String, Object>(256);

private final Map<String, Object> earlySingletonObjects = new HashMap<String, Object>(16);

private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap<String, ObjectFactory<?>>(16);

对于其中的

代码语言:javascript
复制
bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);

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

if (!(beanInstance instanceof FactoryBean) || BeanFactoryUtils.isFactoryDereference(name)) {
        return beanInstance;
    }

其中如果是FactoryBean,则调用getObject()来获取我们自定义的bean,例如

代码语言:javascript
复制
<!-- FactoryBean创建 自定义创建bean-->
<bean id="driver" class="com.demo.spring.DriverFactoryBean" >
   <property name="jdbcUrl" value="jdbc:mysql://192.168.5.104:3306"></property>
</bean>

其中返回的不是DriverFactoryBean,而是返回Driver

代码语言:javascript
复制
public Class<?> getObjectType() {
    return Driver.class;
}

总结:

1、调用BeanFactory.getBean()会触发Bean的实例化。

2、DefaultSingletonBeanRegistry中缓存了单例Bean。

3、Bean的创建于初始化是由AbstractAutowireCapableBeanFactory完成的。

另外:

IOC容器只存放单例Bean,IOC容器在初始化的时候,会将所以Bean初始化在singletonObjects这个ConcurrentHashMap中。 在获取bean的时候,首先会去singletonObjects中去取,如果scope是单例则可以获取bean,如果是多例,则取不到bean,需要从mergedBeanDefinitions这个ConcurrentHashMap中获取RootBeanDefinition,这个里面包含bean的基础信息,然后判断scope是prototype(多例),则每次都会创建一个新的实例。

对于@Autowire、@Resource等注解,在启动SpringIOC容器时,容器会装载一个AutowiredAnnotationBeanPostProcessor 后置处理器,当容易扫描到@Autowire、@Resource等注解时,就会在IOC容器中自动查找需要的Bean,并装配给该对象的属性,在使用@Autowire时,首先在容器中查询对应类型的bean,如果查询不止一个,则根据名称来查,如果名称没有则抛异常,可以将required=false来解决,如果正好查询到一个,则就将该bean装配给@Autowire指定的变量。

对于bean之间相互引用的情况,比如A依赖B,B依赖A,这种情况时,先去实例化A,然后发现依赖B,接着去实例化B,如果此时发现B依赖A,容器会获取A的一个早期引用(early reference),将这个早期引用的A注入给B,然后B实例化完了,则实例化A也就完成了。当然对于这种循环引用的代码应该规避,这种不是正常的场景。

涉及的类:

BeanDefinition

DefaultResourceLoader

XmlBeanDefinitionReader

BeanDefinitionRegistry

BeanFactory

DefaultListableBeanFactory

AutowireCapableBeanFactory

AbstractAutowireCapableBeanFactory

SingletonBeanRegistry

DefaultSingletonBeanRegistry

整个流程:

代码语言:javascript
复制
run->getBean->BeanFactory->doGetBean->AbstructBeanFactory
->getSingleton(从缓存中获取,如果是单例,为空则创建并缓存,如果是多例则直接创建)
->DefaultSingleonBeanRegistry->createBean->AbstractAutowireCapableBeanFactory
->createBeanInstance->newInstance->Constructor->反射实例化Bean
BeanFactory 与 ApplicationContext区别

看下结构图

ApplicationContext.java

ApplicationContext.png

从图中可以看到ApplicationContext是由BeanFactory接口派生出来的,具有BeanFactory所以功能。除此之外,还具有以下功能:

1、MessageSource,提供国际化的消息访问

2、资源访问,入url和文件

3、事件传播,实现了ApplicationListener接口的bean

4、载入多个上下文(有继承关系),使每个上下文都专注于一个特定的层次,比如应用web层

类似的

DefaultListableBeanFactory.java

DefaultListableBeanFactory.png


github地址 : https://github.com/zhaoyybalabala/spring-test

如有问题,欢迎提问:)

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2019.02.15 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • Spring 源码分析(二)之 Spring IOC 容器源码分析
相关产品与服务
容器服务
腾讯云容器服务(Tencent Kubernetes Engine, TKE)基于原生 kubernetes 提供以容器为核心的、高度可扩展的高性能容器管理服务,覆盖 Serverless、边缘计算、分布式云等多种业务部署场景,业内首创单个集群兼容多种计算节点的容器资源管理模式。同时产品作为云原生 Finops 领先布道者,主导开源项目Crane,全面助力客户实现资源优化、成本控制。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档