Spring源码解析-BeanFactory、ListableBeanFactory、ApplicationContext

726 阅读24分钟

一、BeanFactory

  • 1.访问(接入)spring bean 的 根接口,这是一个Bean容器的最基本的客户端视图。 (The root interface for accessing a Spring bean container)

  • 2.该接口由包含许多bean定义的对象实现,每个bean定义由String名称唯一标识。

  • 3.根据bean定义,工厂将返回包含对象的独立实例(Prototype设计模式)或单个共享实例(Singleton设计模式),返回哪种类型的实例取决于bean工厂配置:API是相同的。

  • 4.BeanFactory是应用程序组件的中心注册中心,并集中应用程序组件的配置。

  • 5.Spring的依赖注入功能是使用BeanFactory接口及其子接口实现的。

  • 6.通常最好依靠依赖注入(“推push”配置 configuration) 通过设置器(stters )或构造器(constructors)配置应用程序对象,而不是 use any form of "pull" configuration like aBeanFactory lookup

    1. 预加载bean定义功能:BeanFactory将加载存储在配置源(如XML文档)中的bean定义,并使用org.springframework.beans包配置bean,存储Bean定义方式:LDAP(LDAP全称是Lightweight Directory Access Protocol,轻量目录访问协议)、RDBMS(关系数据库管理系统(Relational Database Management System:RDBMS)、XML、属性文件等。
    1. 如果在这个工厂实例中没有找到 bean,将询问直接的母厂。 此工厂实例中的Bean应该覆盖任何父工厂中的同名 bean。 BeanFactory采用的是延迟加载的方式,什么时候根据id获取对象了,什么时候才真正地创建对象。
    1. Bean 工厂实现应尽可能支持标准的 Bean 生命周期接口。全套初始化方法及其标准顺序是:
  • BeanNameAware的{@code setBeanName}

  • BeanClassLoaderAware 的 {@code setBeanClassLoader}

  • BeanFactoryAware 的 {@code setBeanFactory}

  • ResourceLoaderAware 的 {@code setResourceLoader}(仅适用于在应用程序上下文中运行)

  • ApplicationEventPublisherAware的{@code setApplicationEventPublisher}(仅适用于在应用程序上下文中运行)

  • MessageSourceAware 的 {@code setMessageSource}(仅适用于在应用程序上下文中运行时)

  • ApplicationContextAware 的 {@code setApplicationContext}(仅适用于在应用程序上下文中运行时)

  • ServletContextAware 的 {@code setServletContext}(仅适用于在 Web 应用程序上下文中运行时)

  • BeanPostProcessors 的 {@code postProcessBeforeInitialization} 方法

  • InitializingBean 的 {@code afterPropertiesSet}

  • 自定义初始化方法定义

  • BeanPostProcessors的{@code postProcessAfterInitialization}方法

  • 10.Spring中,所有的Bean都是由BeanFactory(也就是IOC容器)来进行管理的Bean。但对FactoryBean而言,这个Bean不是简单的Bean,而是一个能生产或者修饰对象生成的工厂Bean,它的实现与设计模式中的工厂模式和修饰器模式类似 .

  • ListableBeanFactory接口是BeanFactory接口的一个扩展 BeanFactory 和其他的接口相比较,ListableBeanFactory、ConfigurableBeanFactory 是有特定目标的:

 such as 
 {@link ListableBeanFactory} and 
 {@link org.springframework.beans.factory.config.ConfigurableBeanFactory}
  即:ListableBeanFactoryConfigurableBeanFactory 可用于特定目的

Spring的Bean容器最顶层的接口,定义了Ioc容器的基本规范。实现这个接口的Ioc容器都会持有一些BeanDefinition和一个唯一的字符串形式的名字。--《Spring之1:的BeanFactory和FactoryBean》 BeanDefinition描述了一个bean实例,该实例具有属性值、构造函数参数值和具体实现提供的进一步信息。

应用场景

FactoryBean 通常是用来创建比较复杂的bean,一般的bean 直接用xml配置即可,但如果一个bean的创建过程中涉及到很多其他的bean 和复杂的逻辑,用xml配置比较困难,这时可以考虑用FactoryBean。

应用案例

如果大家有看过Mybatis的SessionFactoryBean和Activiti初始化引擎的ProcessEngineFactoryBean两个类就应该了解FactoryBean的具体使用。

很多开源项目在集成Spring 时都使用到FactoryBean,比如 MyBatis3 提供 mybatis-spring项目中的 org.mybatis.spring.SqlSessionFactoryBean

    <bean id="tradeSqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
        <property name="dataSource" ref="trade" />
        <property name="mapperLocations" value="classpath*:mapper/trade/*Mapper.xml" />
        <property name="configLocation" value="classpath:mybatis-config.xml" />
        <property name="typeAliasesPackage" value="com.bytebeats.mybatis3.domain.trade" />
    </bean>

org.mybatis.spring.SqlSessionFactoryBean 如下:

 
package org.mybatis.spring;

public class SqlSessionFactoryBean implements FactoryBean<SqlSessionFactory>, InitializingBean, ApplicationListener<ApplicationEvent> {
private static final Log LOGGER = LogFactory.getLog(SqlSessionFactoryBean.class);
        ......
}
 

我们希望通过该通用bean产生一个我们希望的bean,而这个需求FactoryBean就可以办到,只需要拦截你需要代理的bean,然后转换成你希望的bean再注册。 Rpc服务器端的bean注册,以及Rpc客户端的服务调用,都可以通过一个第三方bean来产生我们真正需要的bean。

BeanFactory体系结构

image.png

二、ListableBeanFactory

  • 它可以枚举所有的bean实例,而不是尝试按客户端请求的名称逐个查找bean。预加载所有bean定义(例如基于xml的工厂) 。

  • 理论上讲,即使此类的实现类同时也实现了HierarchicalBeanFactory,此接口中方法返回值也不应该考虑其父BeanFactory中的Bean,但是你可以通过BeanFactoryUtils工具类来获取哪些在父BeanFactory中的bean

  • 通常情况下,所有的Bean都是通过外部的配置文件配置的,除了getBeanDefinitionCount和containsBeanDefinition外,此接口中其他方法的实现可能不会太高效,因此,不建议经常调用。

ListableBeanFactory源码

public interface ListableBeanFactory extends BeanFactory {

/**
  * 查看是否包含指定名字的Bean * 
  不支持向上或向下查找 * 
  不支持查找非配置文件定义的单例Bean 
  */
    boolean containsBeanDefinition(String var1);
    
    
    /**
    查看此BeanFactory中包含的Bean数量 
    * 不支持向上或向下查找 
    * 不支持查找非配置文件定义的单例Bean
    */
    int getBeanDefinitionCount();
   
    String[] getBeanDefinitionNames();

    String[] getBeanNamesForType(Class<?> var1);

    String[] getBeanNamesForType(Class<?> var1, boolean var2, boolean var3);

    <T> Map<String, T> getBeansOfType(Class<T> var1) throws BeansException;

    <T> Map<String, T> getBeansOfType(Class<T> var1, boolean var2, boolean var3) throws BeansException;

    Map<String, Object> getBeansWithAnnotation(Class<? extends Annotation> var1) throws BeansException;

    <A extends Annotation> A findAnnotationOnBean(String var1, Class<A> var2);
}

ListableBeanFactory结构图

image.png

HierarchicalBeanFactory

HierarchicalBeanFactory继承BeanFactory并扩展使其支持层级结构。getParentBeanFactory()方法或者父级BeanFactory,containsLocalBean(String name)方法查看当前BeanFactory是否包含给定名字的Bean,不会递归想父级查找。 允许以可配置的方式设置父类的bean工厂 相应{@code setParentBeanFactory}方法可以在ConfigurableBeanFactory接口中找到。

ResourceLoader:

Spring提供资源的根接口。在Spring Ioc中,资源被Resource引用,获得Resource对象,说明获得了资源的访问。Resource提供资源的抽象,具体资源可是从URL,classpath,file等地方获得。

ResourcePatternResolver:

ResourcePatternResolver是对ResourceLoader的扩展,其支持模式匹配的资源。如:classpath*:表示匹配路径下所有的资源。

DefaultResourceLoader:

  • ResourceLoader的默认实现,可以单独使用,也可以通过扩展使其支持特殊的资源,如:FileSystemResourceLoader,ClassPathXmlApplicationContext等。

  • 该类是ResourceLoader接口的实现,AbstractApplicationContext还继承自DefaultResourceLoader类(AbstractApplicationContext还了实现ConfigurableApplicationContext接口)

DefaultResouceLoader 结构图

image.png

DefaultResouceLoader 源码

public class DefaultResourceLoader implements ResourceLoader {
   //加载资源的类加载器
   @Nullable
   private ClassLoader classLoader;
   # 用于存储注册的协议解析器
   private final Set<ProtocolResolver> protocolResolvers = new LinkedHashSet(4);
   # 缓存已加载的资源
   private final Map<Class<?>, Map<Resource, ?>> resourceCaches = new ConcurrentHashMap(4);

//不指定默认的类资源加载器时,会调用默认的类加载器进行初始化classLoader,否则就会使用我们传入的类加载器初始化classLoader
   public DefaultResourceLoader() {
       this.classLoader = ClassUtils.getDefaultClassLoader();
   }

//使用我们传入的类加载器初始化classLoader
   public DefaultResourceLoader(@Nullable ClassLoader classLoader) {
       this.classLoader = classLoader;
   }
   
   
   

   public void setClassLoader(@Nullable ClassLoader classLoader) {
       this.classLoader = classLoader;
   }

   @Nullable
   public ClassLoader getClassLoader() {
       return this.classLoader != null ? this.classLoader : ClassUtils.getDefaultClassLoader();
   }

   public void addProtocolResolver(ProtocolResolver resolver) {
       Assert.notNull(resolver, "ProtocolResolver must not be null");
       this.protocolResolvers.add(resolver);
   }

   public Collection<ProtocolResolver> getProtocolResolvers() {
       return this.protocolResolvers;
   }

   public <T> Map<Resource, T> getResourceCache(Class<T> valueType) {
       return (Map)this.resourceCaches.computeIfAbsent(valueType, (key) -> {
           return new ConcurrentHashMap();
       });
   }

   public void clearResourceCaches() {
       this.resourceCaches.clear();
   }

   public Resource getResource(String location) {
       Assert.notNull(location, "Location must not be null");
       Iterator var2 = this.getProtocolResolvers().iterator();

       Resource resource;
       do {
           if (!var2.hasNext()) {
               if (location.startsWith("/")) {
                   return this.getResourceByPath(location);
               }

               if (location.startsWith("classpath:")) {
                   return new ClassPathResource(location.substring("classpath:".length()), this.getClassLoader());
               }

               try {
                   URL url = new URL(location);
                   return (Resource)(ResourceUtils.isFileURL(url) ? new FileUrlResource(url) : new UrlResource(url));
               } catch (MalformedURLException var5) {
                   return this.getResourceByPath(location);
               }
           }

           ProtocolResolver protocolResolver = (ProtocolResolver)var2.next();
           resource = protocolResolver.resolve(location, this);
       } while(resource == null);

       return resource;
   }

   protected Resource getResourceByPath(String path) {
       return new DefaultResourceLoader.ClassPathContextResource(path, this.getClassLoader());
   }

   protected static class ClassPathContextResource extends ClassPathResource implements ContextResource {
       public ClassPathContextResource(String path, @Nullable ClassLoader classLoader) {
           super(path, classLoader);
       }

       public String getPathWithinContext() {
           return this.getPath();
       }

       public Resource createRelative(String relativePath) {
           String pathToUse = StringUtils.applyRelativePath(this.getPath(), relativePath);
           return new DefaultResourceLoader.ClassPathContextResource(pathToUse, this.getClassLoader());
       }
   }
}

ApplicationEventPublisher:

事件发布,通知事件监听者此Application的事件。

MessageSource:

处理Spring 中的消息,支持i18n和参数化消息。另外其子类ReloadableResourceBundleMessageSource支持不重启JVM刷新消息。

EnvironmentCapable:

实现此接口的容器将支持上下文环境。在Spring Ioc容器中,都是支持上下文环境的。

Lifecycle:

对BeanFactory提供生命周期支持。另外其他任何对象都可以实现Lifecycle接口来支持开始/结束控制。 注意Lifecycle接口只支持顶层对象,其他的Lifecycle将被忽略。

DisposableBean:

DisposableBean提供了在销毁Ioc容器的时候释放资源。 在关闭 bean 工厂时,以下生命周期方法适用:

  • DisposableBean 的 {@code destroy}
  • 自定义销毁方法定义

Lifecycle 代码

  • 必须被组件(通常是Spring Context中定义的bean)和容器(也就是ApplicationContext自身)实现。
  • 将会传播启动/停止信号给每个容器中应用的所有组件 例如运行时停止/重启动场景。

注意当前的生命周期接口仅支持顶层的单例bean 对于其他的组件来说,生命周期接口不会检测并且默认忽略 另外,请注意,扩展的SmartLifecycle接口提供了与应用程序上下文的启动和关闭阶段的复杂集成

public interface Lifecycle {
    /*
    开启一个组件
    如果组件已经在运行也不应该抛出异常
    对于容器来说,这会将启动信号传递给应用的所有组件
    */
    void start();
    /*
    通常以同步方式停止此组件,以便在返回此方法时完全停止该组件
    请注意,此停止通知不能保证在销毁之前发出:在定期关闭时,Lifecycle Bean将首先在传播常规销毁回调之前收到停止通知;但是,在上下文生存期内的热刷新或中止刷新尝试时,将调用给定bean的destroy方法,而不预先考虑停止信号。
    */
    void stop();
    /*
    检查组件是否正在运行
    对于容器来说,只有容器应用的全部组件都在运行时才会返回true
    */
    boolean isRunning();
}

Closeable

Closeable是可以关闭的数据的源或者目标,这是java的io接口 调用close方法是为了释放对象持有的资源(例如打开的文件)

public interface Closeable extends AutoCloseable {
    /*
    关闭流并且释放与它关联的系统资源
    如果流已经被关闭,那么调用该方法没有任何影响
    */
    public void close() throws IOException;
}

ApplicationContext(Spring的核心接口和容器)

  • ApplicationContext是Spring中的核心接口和容器,允许容器通过应用程序上下文环境创建bean、获取bean、管理bean。 在构建容器的时候,创建对象采用的策略是立即加载的方式,即只要一读取完配置文件就立即创建配置文件中配置的对象。

  • BeanFactory采用的是延迟加载的方式,什么时候根据id获取对象了,什么时候才真正地创建对象。

  • ApplicationContext继承了上面描述的所有接口,因此ApplicationContext是一个接口集合,提供所继承接口的功能

  • ApplicationContext在启动后是只读的,但是如果ApplicationContext实现类支持reload,也可以刷新这个ApplicationContext。

  • ApplicationContext接口具有三个常用的实现类: 1、ClassPathXmlApplicationContext:可以加载类路径下的配置文件,要求配置文件必须在类路径之下。 2、FileSystemXmlApplicationContext:可以加载磁盘中任意路径下的配置文件,要求具有访问权限。 3、AnnotationConfigApplicationContext:用于读取注解创建容器。

ApplicationContext源码

//接口继承接口,扩展了 EnvironmentCapable、ApplicationEventPublisher 接口的方法
public interface ApplicationContext extends EnvironmentCapable, ListableBeanFactory, HierarchicalBeanFactory, MessageSource, ApplicationEventPublisher, ResourcePatternResolver {
    String getId();

    String getDisplayName();

    long getStartupDate();

    ApplicationContext getParent();

    AutowireCapableBeanFactory getAutowireCapableBeanFactory() throws IllegalStateException;
}

ApplicationContext 结构图

image.png

ConfigurableApplicationContext:

提供对Ioc容器的配置的支持,并帮助spring用来配置和管理应用程序上下文,包括设置父级容器,设置上下文环境,刷新容器,注册关闭容器钩子等。 ConfigurableApplicationContext是用来对ApplicationContext进行一系列配置的:

  • context的唯一id(用于表示每个context),

  • 设置environment

  • 设置BeanFactoryPostProcessor (BeanFactoryPostProcessor和BeanPostProcessor类似,可以对beanDefinition进行处理,也就是说SpringIOC容器允许BeanFactoryPostProcessor在容器实际实例化任何bean之前读取beanDefinition,并有可能修改他.并且我们还可以配置自定义的BeanFactoryPostProcessor.如果想改变bean,那么使用beanPostProcessor.

  • 注册应用程序监听器和关闭时的钩子函数

  • 刷新和关闭context,判断context是否处于活跃状态

  • 设置协议解析器

  • 获得应用程序上下文的内部bean工厂

ConfigurableApplicationContext 源码

public interface ConfigurableApplicationContext extends ApplicationContext, Lifecycle, Closeable {
    /*
    这个字符串中的任意字符都可以作为单个字符串值中多个上下文配置路径之间的分隔符
    */
    String CONFIG_LOCATION_DELIMITERS = ",; \t\n";
    /*
    factory中ConversionService bean的名称,如果没有提供将才有默认的转换规则
    */
    String CONVERSION_SERVICE_BEAN_NAME = "conversionService";
    /*
    factory中LoadTimeWeaver bean的名称,如果提供了这样的bean,
    context将使用一个临时类加载器进行类型匹配,以允许LoadTimeWeaver处理所有实际的bean类
    */
    String LOAD_TIME_WEAVER_BEAN_NAME = "loadTimeWeaver";
    /*
    factory中Environment bean的名称
    */
    String ENVIRONMENT_BEAN_NAME = "environment";
    /*
    系统属性bean的名称
    */
    String SYSTEM_PROPERTIES_BEAN_NAME = "systemProperties";
    /*
    系统环境bean的名称
    */
    String SYSTEM_ENVIRONMENT_BEAN_NAME = "systemEnvironment";
    /*
    关闭钩子线程的名称
    */
    String SHUTDOWN_HOOK_THREAD_NAME = "SpringContextShutdownHook";
    /*
    设置应用程序上下文的唯一ID
    */
    void setId(String id);
    /*
    设置应用程序上下文的父Context
    请注意,父类不应该被修改,只有在创建此类的对象时父级不可用时,才应在构造函数外部设置父级
    */
    void setParent(@Nullable ApplicationContext parent);
    /*
    设置应用程序上下文的环境
    */
    void setEnvironment(ConfigurableEnvironment environment);
    /*
    获得应用程序上下文的环境
    */
    @Override
    ConfigurableEnvironment getEnvironment();
    /*
    增加一个新的BeanFactoryPostProcessor,在任何bean definition被检查之前,
    它将会在当前应用程序上下文刷新的时候将会应用于内部的bean工厂
    
    在进行context配置期间调用
    */
    void addBeanFactoryPostProcessor(BeanFactoryPostProcessor postProcessor);
    /*
    添加一个ApplicationListener,它将会被通知上下文事件
    例如context刷新和关闭事件
    注意,即使上下文没有启动,注册在这里的ApplicationListener也会被应用与刷新事件
    或者在上下文已经激活的情况下,使用当前事件多播进行实时处理
    */
    void addApplicationListener(ApplicationListener<?> listener);
    /*
    指定加载类路径下的资源和bean classs的类加载器
    context类加载器将会被传递给内部的bean工厂
    */
    void setClassLoader(ClassLoader classLoader);
    /*
    注册应用程序上下文中给定的协议解析器
    允许额外的资源协议被处理
    任何这样的解析器都将在这个上下文的标准解析规则之前被调用。
    因此,它也可以覆盖任何默认规则
    */
    void addProtocolResolver(ProtocolResolver resolver);
    /*
    加载或者刷新配置,这些配置可能来自基于Java注解的配置,或者xml文件,或者属性文件,或者关联的数据库等等
    
    这是一个启动方法,如果它失败它应该销毁已经建立的单例,避免浪费资源
    换句话说,调用这个方法之后,应用程序的全部单例或者没有任何单例别初始化
    */
    void refresh() throws BeansException, IllegalStateException;
    /*
    注册JVM运行时的关闭钩子,在JVM关闭时关闭应用程序上下文,除非它已经关闭
    这个方法可以多次调用,每个context实例仅注册一个关闭钩子
    */
    void registerShutdownHook();
    /*
    关闭应用程序上下文,释放所有的资源,同时会销毁单例池中的所有bean
    */
    @Override
    void close();
    /*
    判断当前应用程序上下文是否在使用
    判断它是否至少被刷新一次并且没有被关闭
    */
    boolean isActive();
    /*
    返回当前应用程序上下文的内部bean工厂,可以用于访问指定的功能
    不要用它来对bean工厂进行后期处理;单例之前已经实例化过了。
    使用BeanFactoryPostProcessor在接触Bean之前拦截BeanFactory启动过程
    */
    ConfigurableListableBeanFactory getBeanFactory() throws IllegalStateException;
}

ConfigurableApplicationContext 结构图

ConfigurableApplicationContext接口实现了Lifecycle接口和Closeable接口,接下来首先看看这两个接口。

image.png image.png

AbstractApplicationContext:

AbstractApplicationContext是Ioc容器的抽象实现,这里实现了大部分的功能:消息,事件,刷新容器,生命周期等。AbstractApplicationContext采用模板方法模式,把一部分实现推迟到子类。 AbstractApplicationContext主要有如下几点作用:

对属性的getter和setter方法 进行事件的发布,通过applicationEventMulticaster进行事件的发布。 对应用程序上下文进行刷新,在刷新的过程中:改变了context的状态,初始化了messageSource和applicationEventMulticaster,注册了一系列的监听者,完成了spring中bean的创建等,refresh方法是重点。 可以通过context获得对应beanFactory,然后通过这个bean工厂来查询bean工厂中缓存的各种bean,还可以判断bean的生命周期,通过类型获取对应的bean,获取其中的BeanDefinition 注册了一系列的BeanFactoryPostProcessor,并在refresh()方法执行过程中通过调用PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors执行了我们注册的BeanFactoryPostProcessor 通过LifecycleProcessor对beans的生命周期进行管理

image.png

DefaultLifecycleProcessor

image.png

public class DefaultLifecycleProcessor implements LifecycleProcessor, BeanFactoryAware {}
public interface LifecycleProcessor extends Lifecycle {}
public interface BeanFactoryAware extends Aware {}
 

AbctractApplicationContext 结构图

image.png

从上图来看,AbstractApplicationContext实现了ConfigurationApplicationContext接口,而ConfigurationApplicationContext接口继承自ApplicationContext、Lifecycle和Closeable,ApplicationContext又扩展了BeanFactory的功能,归根到底这些都是在帮助我们管理Bean

public abstract class AbstractApplicationContext extends DefaultResourceLoader
      implements ConfigurableApplicationContext {...}
      ```
public interface ConfigurableApplicationContext extends ApplicationContext, Lifecycle, Closeable {...}
 
public interface ApplicationContext extends EnvironmentCapable, ListableBeanFactory, HierarchicalBeanFactory,
      MessageSource, ApplicationEventPublisher, ResourcePatternResolver {
 
 public interface EnvironmentCapable {
    Environment getEnvironment();
}

AbstractRefreshableApplicationContext:

提供多线程同时刷新容器支持,每次刷新都会产生一个内部BeanFactory(DefaultListableBeanFactory)。另外,子类要实现loadBeanDefinitions方法来正确加载Bean定义。

AbstractRefreshableApplicationContext的基类:{@link org.springframework.context.ApplicationContext}

实现应该支持对{@link #refresh()}的多次调用,每次都创建一个新的内部bean工厂实例。 通常(但不一定),这样的上下文将由一组用于加载bean定义的配置位置驱动

AbstractRefreshableApplicationContext 代码


public abstract class AbstractRefreshableApplicationContext extends AbstractApplicationContext {
    private Boolean allowBeanDefinitionOverriding;
    private Boolean allowCircularReferences;
    private DefaultListableBeanFactory beanFactory;
    private final Object beanFactoryMonitor = new Object();

    public AbstractRefreshableApplicationContext() {
    }

    public AbstractRefreshableApplicationContext(ApplicationContext parent) {
        super(parent);
    }

    public void setAllowBeanDefinitionOverriding(boolean allowBeanDefinitionOverriding) {
        this.allowBeanDefinitionOverriding = allowBeanDefinitionOverriding;
    }

    public void setAllowCircularReferences(boolean allowCircularReferences) {
        this.allowCircularReferences = allowCircularReferences;
    }

    protected final void refreshBeanFactory() throws BeansException {
        if (this.hasBeanFactory()) {
            this.destroyBeans();
            this.closeBeanFactory();
        }

        try {
            DefaultListableBeanFactory beanFactory = this.createBeanFactory();
            beanFactory.setSerializationId(this.getId());
            this.customizeBeanFactory(beanFactory);
            this.loadBeanDefinitions(beanFactory);
            Object var2 = this.beanFactoryMonitor;
            synchronized(this.beanFactoryMonitor) {
                this.beanFactory = beanFactory;
            }
        } catch (IOException var4) {
            throw new ApplicationContextException("I/O error parsing bean definition source for " + this.getDisplayName(), var4);
        }
    }

    protected void cancelRefresh(BeansException ex) {
        Object var2 = this.beanFactoryMonitor;
        synchronized(this.beanFactoryMonitor) {
            if (this.beanFactory != null) {
                this.beanFactory.setSerializationId((String)null);
            }
        }

        super.cancelRefresh(ex);
    }

    protected final void closeBeanFactory() {
        Object var1 = this.beanFactoryMonitor;
        synchronized(this.beanFactoryMonitor) {
            this.beanFactory.setSerializationId((String)null);
            this.beanFactory = null;
        }
    }

    protected final boolean hasBeanFactory() {
        Object var1 = this.beanFactoryMonitor;
        synchronized(this.beanFactoryMonitor) {
            return this.beanFactory != null;
        }
    }

    public final ConfigurableListableBeanFactory getBeanFactory() {
        Object var1 = this.beanFactoryMonitor;
        synchronized(this.beanFactoryMonitor) {
            if (this.beanFactory == null) {
                throw new IllegalStateException("BeanFactory not initialized or already closed - call 'refresh' before accessing beans via the ApplicationContext");
            } else {
                return this.beanFactory;
            }
        }
    }

    protected DefaultListableBeanFactory createBeanFactory() {
        return new DefaultListableBeanFactory(this.getInternalParentBeanFactory());
    }

    protected void customizeBeanFactory(DefaultListableBeanFactory beanFactory) {
        if (this.allowBeanDefinitionOverriding != null) {
            beanFactory.setAllowBeanDefinitionOverriding(this.allowBeanDefinitionOverriding.booleanValue());
        }

        if (this.allowCircularReferences != null) {
            beanFactory.setAllowCircularReferences(this.allowCircularReferences.booleanValue());
        }

        beanFactory.setAutowireCandidateResolver(new QualifierAnnotationAutowireCandidateResolver());
    }

    protected abstract void loadBeanDefinitions(DefaultListableBeanFactory var1) throws BeansException, IOException;
}



Aware:

Aware是个标记接口,实现这个接口的对象提供通知Spring容器功能。具体通知动作在子类定义。 标记超接口,指示bean有资格通过回调方法由特定框架对象的Spring容器通知。实际的方法签名由单独的子接口决定,但通常应该只包含单个参数的返回void的方法。

aware,翻译过来是知道的,已感知的,意识到的,所以这些接口从字面意思应该是能感知到所有Aware前面的含义。

BeanNameAware:

Aware的子接口,当设置BeanName的时候,创建通知。

实现BeanNameAware接口,可以让该Bean感知到自身的BeanName(对应Spring容器的BeanId属性)属性

注意,通常不建议对象依赖于它的bean名称,因为这代表了对外部配置潜在的脆弱依赖,以及对Spring API可能的不必要依赖。

BeanNameAware 源码

public interface Aware {
}

 
public interface BeanNameAware extends Aware {

   /**
    * Set the name of the bean in the bean factory that created this bean.
    * <p>Invoked after population of normal bean properties but before an
    * init callback such as {@link InitializingBean#afterPropertiesSet()}
    * or a custom init-method.
    * @param name the name of the bean in the factory.
    * Note that this name is the actual bean name used in the factory, which may
    * differ from the originally specified name: in particular for inner bean
    * names, the actual bean name might have been made unique through appending
    * "#..." suffixes. Use the {@link BeanFactoryUtils#originalBeanName(String)}
    * method to extract the original bean name (without suffix), if desired.
    */
   void setBeanName(String name);

}

ApplicationContextAware

当一个类实现了这个接口之后,这个类就可以方便的获得ApplicationContext对象(spring上下文),Spring发现某个Bean实现了ApplicationContextAware接口,Spring容器会在创建该Bean之后,自动调用该Bean的setApplicationContext(参数)方法,调用该方法时,会将容器本身ApplicationContext对象作为参数传递给该方法

案例

@Component
public class ApplicationContextUtil implements ApplicationContextAware {

    private static ApplicationContext context;
    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        context = applicationContext;
    }
    public static ApplicationContext getApplicationContext(){
        return context;
    }
    /**
     * 通过name获取 Bean
     * @param name beanName
     * @return Object
     */
    public static Object getBean(String name){
        return getApplicationContext().getBean(name);
    }

    public static <T> T getBean(Class<T> requiredType) throws BeansException{
        return getApplicationContext().getBean(requiredType);
    }
}

 
public interface ApplicationContext extends EnvironmentCapable, ListableBeanFactory, HierarchicalBeanFactory, MessageSource, ApplicationEventPublisher, ResourcePatternResolver {
    String getId();

    String getDisplayName();

    long getStartupDate();

    ApplicationContext getParent();

    AutowireCapableBeanFactory getAutowireCapableBeanFactory() throws IllegalStateException;
}
 
 

InitializingBean:

这个接口作用是当Bean对象的属性都被设置完成或,可以立即做一些自定义的动作。另一个替代方案是设置init-method。 检查所有强制属性是否已经设置

public interface InitializingBean {

   /**
    * Invoked by the containing {@code BeanFactory} after it has set all bean properties
    * and satisfied {@link BeanFactoryAware}, {@code ApplicationContextAware} etc.
    * <p>This method allows the bean instance to perform validation of its overall
    * configuration and final initialization when all bean properties have been set.
    * @throws Exception in the event of misconfiguration (such as failure to set an
    * essential property) or if initialization fails for any other reason
    */
   void afterPropertiesSet() throws Exception;

}

Spring是通过反射来调用init-method指定方法,而实现InitializingBean接口是直接调用afterPropertiesSet方法,所以后者效率高,但使用init-method方式减少了对Spring的依赖 如果调用afterPropertiesSet方法时报错,则不会再调用init-method指定的方法

AbstractRefreshableConfigApplicationContext:

提供对容器的一些特殊设置:setConfigLocation,setBeanName,setId等。 添加指定配置位置的公共处理的子类。 AbstractRefreshableConfigApplicationContext用作基于xml的应用程序的基类


/**
 * {@link AbstractRefreshableApplicationContext} subclass that adds common handling
 * of specified config locations. Serves as base class for XML-based application
 * context implementations such as {@link ClassPathXmlApplicationContext} and
 * {@link FileSystemXmlApplicationContext}, as well as
 * {@link org.springframework.web.context.support.XmlWebApplicationContext}.
 *
 * @author Juergen Hoeller
 * @since 2.5.2
 * @see #setConfigLocation
 * @see #setConfigLocations
 * @see #getDefaultConfigLocations
 */
public abstract class AbstractRefreshableConfigApplicationContext extends AbstractRefreshableApplicationContext
      implements BeanNameAware, InitializingBean {

   @Nullable
   private String[] configLocations;

   private boolean setIdCalled = false;


   /**
    * Create a new AbstractRefreshableConfigApplicationContext with no parent.
    */
   public AbstractRefreshableConfigApplicationContext() {
   }

   /**
    * Create a new AbstractRefreshableConfigApplicationContext with the given parent context.
    * @param parent the parent context
    */
   public AbstractRefreshableConfigApplicationContext(@Nullable ApplicationContext parent) {
      super(parent);
   }


   /**
    * Set the config locations for this application context in init-param style,
    * i.e. with distinct locations separated by commas, semicolons or whitespace.
    * <p>If not set, the implementation may use a default as appropriate.
    */
   public void setConfigLocation(String location) {
      setConfigLocations(StringUtils.tokenizeToStringArray(location, CONFIG_LOCATION_DELIMITERS));
   }

   /**
    * Set the config locations for this application context.
    * <p>If not set, the implementation may use a default as appropriate.
    */
   public void setConfigLocations(@Nullable String... locations) {
      if (locations != null) {
         Assert.noNullElements(locations, "Config locations must not be null");
         this.configLocations = new String[locations.length];
         for (int i = 0; i < locations.length; i++) {
            this.configLocations[i] = resolvePath(locations[i]).trim();
         }
      }
      else {
         this.configLocations = null;
      }
   }

   /**
    * Return an array of resource locations, referring to the XML bean definition
    * files that this context should be built with. Can also include location
    * patterns, which will get resolved via a ResourcePatternResolver.
    * <p>The default implementation returns {@code null}. Subclasses can override
    * this to provide a set of resource locations to load bean definitions from.
    * @return an array of resource locations, or {@code null} if none
    * @see #getResources
    * @see #getResourcePatternResolver
    */
   @Nullable
   protected String[] getConfigLocations() {
      return (this.configLocations != null ? this.configLocations : getDefaultConfigLocations());
   }

   /**
    * Return the default config locations to use, for the case where no
    * explicit config locations have been specified.
    * <p>The default implementation returns {@code null},
    * requiring explicit config locations.
    * @return an array of default config locations, if any
    * @see #setConfigLocations
    */
   @Nullable
   protected String[] getDefaultConfigLocations() {
      return null;
   }

   /**
    * Resolve the given path, replacing placeholders with corresponding
    * environment property values if necessary. Applied to config locations.
    * @param path the original file path
    * @return the resolved file path
    * @see org.springframework.core.env.Environment#resolveRequiredPlaceholders(String)
    */
   protected String resolvePath(String path) {
      return getEnvironment().resolveRequiredPlaceholders(path);
   }


   @Override
   public void setId(String id) {
      super.setId(id);
      this.setIdCalled = true;
   }

   /**
    * Sets the id of this context to the bean name by default,
    * for cases where the context instance is itself defined as a bean.
    */
   @Override
   public void setBeanName(String name) {
      if (!this.setIdCalled) {
         super.setId(name);
         setDisplayName("ApplicationContext '" + name + "'");
      }
   }

   /**
    * Triggers {@link #refresh()} if not refreshed in the concrete context's
    * constructor already.
    */
   @Override
   public void afterPropertiesSet() {
      if (!isActive()) {
         refresh();
      }
   }

}

AbstractFreshableConfigApplicationContext 结构图

image.png

AbstractXmlApplicationContext:

从XML读取Bean定义的容器,这个容器实现了loadBeanDefinitions方法,从XML资源中获得Bean定义。

AbstractXmlApplicationContext 代码

 

/**
 * Convenient base class for {@link org.springframework.context.ApplicationContext}
 * implementations, drawing configuration from XML documents containing bean definitions
 * understood by an {@link org.springframework.beans.factory.xml.XmlBeanDefinitionReader}.
 *
 * <p>Subclasses just have to implement the {@link #getConfigResources} and/or
 * the {@link #getConfigLocations} method. Furthermore, they might override
 * the {@link #getResourceByPath} hook to interpret relative paths in an
 * environment-specific fashion, and/or {@link #getResourcePatternResolver}
 * for extended pattern resolution.
 *
 * @author Rod Johnson
 * @author Juergen Hoeller
 * @see #getConfigResources
 * @see #getConfigLocations
 * @see org.springframework.beans.factory.xml.XmlBeanDefinitionReader
 */
public abstract class AbstractXmlApplicationContext extends AbstractRefreshableConfigApplicationContext {

   private boolean validating = true;


   /**
    * Create a new AbstractXmlApplicationContext with no parent.
    */
   public AbstractXmlApplicationContext() {
   }

   /**
    * Create a new AbstractXmlApplicationContext with the given parent context.
    * @param parent the parent context
    */
   public AbstractXmlApplicationContext(@Nullable ApplicationContext parent) {
      super(parent);
   }


   /**
    * Set whether to use XML validation. Default is {@code true}.
    */
   public void setValidating(boolean validating) {
      this.validating = validating;
   }


   /**
    * Loads the bean definitions via an XmlBeanDefinitionReader.
    */
   @Override
   protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) throws BeansException, IOException {
      // Create a new XmlBeanDefinitionReader for the given BeanFactory.
      XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory);

      // Configure the bean definition reader with this context's
      // resource loading environment.
      beanDefinitionReader.setEnvironment(this.getEnvironment());
      beanDefinitionReader.setResourceLoader(this);
      beanDefinitionReader.setEntityResolver(new ResourceEntityResolver(this));

      // Allow a subclass to provide custom initialization of the reader,
      // then proceed with actually loading the bean definitions.
      initBeanDefinitionReader(beanDefinitionReader);
      loadBeanDefinitions(beanDefinitionReader);
   }

   /**
    * Initialize the bean definition reader used for loading the bean
    * definitions of this context. Default implementation is empty
    */
   protected void initBeanDefinitionReader(XmlBeanDefinitionReader reader) {
      reader.setValidating(this.validating);
   }

   /**
    * Load the bean definitions with the given XmlBeanDefinitionReader.
 
    */
   protected void loadBeanDefinitions(XmlBeanDefinitionReader reader) throws BeansException, IOException {
      Resource[] configResources = getConfigResources();
      if (configResources != null) {
         reader.loadBeanDefinitions(configResources);
      }
      String[] configLocations = getConfigLocations();
      if (configLocations != null) {
         reader.loadBeanDefinitions(configLocations);
      }
   }

   /**
    * Return an array of Resource objects, referring to the XML bean definition 
    */
   @Nullable
   protected Resource[] getConfigResources() {
      return null;
   }

}
 

FileSystemXmlApplicationContext:

标准的从文件系统读XML的Bean定义容器。getResourceByPath方法返回文件系统资源。 独立的XML应用程序上下文,从文件系统或url获取上下文定义文件,将普通路径解释为相对的文件系统位置(例如。“mydir / myfile.txt”)。对于测试工具和独立环境都很有用。


public class FileSystemXmlApplicationContext extends AbstractXmlApplicationContext {
   public FileSystemXmlApplicationContext() {
   }

   public FileSystemXmlApplicationContext(ApplicationContext parent) {
       super(parent);
   }

   public FileSystemXmlApplicationContext(String configLocation) throws BeansException {
       this(new String[]{configLocation}, true, (ApplicationContext)null);
   }

   public FileSystemXmlApplicationContext(String... configLocations) throws BeansException {
       this(configLocations, true, (ApplicationContext)null);
   }

   public FileSystemXmlApplicationContext(String[] configLocations, ApplicationContext parent) throws BeansException {
       this(configLocations, true, parent);
   }

   public FileSystemXmlApplicationContext(String[] configLocations, boolean refresh) throws BeansException {
       this(configLocations, refresh, (ApplicationContext)null);
   }

   public FileSystemXmlApplicationContext(String[] configLocations, boolean refresh, ApplicationContext parent) throws BeansException {
       super(parent);
       this.setConfigLocations(configLocations);
       if (refresh) {
           this.refresh();
       }

   }

   protected Resource getResourceByPath(String path) {
       if (path != null && path.startsWith("/")) {
           path = path.substring(1);
       }

       return new FileSystemResource(path);
   }
}

ClassPathXmlApplicationContext:

独立的XML应用程序上下文,从类路径获取上下文定义文件,将普通路径解释为类路径资源,其中包含包路径(例如。“mypackage / myresource.txt”)。对于测试工具以及嵌入在jar中的应用程序上下文非常有用

public class ClassPathXmlApplicationContext extends AbstractXmlApplicationContext {
    private Resource[] configResources;

    public ClassPathXmlApplicationContext() {
    }

    public ClassPathXmlApplicationContext(ApplicationContext parent) {
        super(parent);
    }

    public ClassPathXmlApplicationContext(String configLocation) throws BeansException {
        this(new String[]{configLocation}, true, (ApplicationContext)null);
    }

    public ClassPathXmlApplicationContext(String... configLocations) throws BeansException {
        this(configLocations, true, (ApplicationContext)null);
    }

    public ClassPathXmlApplicationContext(String[] configLocations, ApplicationContext parent) throws BeansException {
        this(configLocations, true, parent);
    }

    public ClassPathXmlApplicationContext(String[] configLocations, boolean refresh) throws BeansException {
        this(configLocations, refresh, (ApplicationContext)null);
    }

    public ClassPathXmlApplicationContext(String[] configLocations, boolean refresh, ApplicationContext parent) throws BeansException {
        super(parent);
        this.setConfigLocations(configLocations);
        if (refresh) {
            this.refresh();
        }

    }

    public ClassPathXmlApplicationContext(String path, Class clazz) throws BeansException {
        this(new String[]{path}, clazz);
    }

    public ClassPathXmlApplicationContext(String[] paths, Class clazz) throws BeansException {
        this(paths, clazz, (ApplicationContext)null);
    }

    public ClassPathXmlApplicationContext(String[] paths, Class clazz, ApplicationContext parent) throws BeansException {
        super(parent);
        Assert.notNull(paths, "Path array must not be null");
        Assert.notNull(clazz, "Class argument must not be null");
        this.configResources = new Resource[paths.length];

        for(int i = 0; i < paths.length; ++i) {
            this.configResources[i] = new ClassPathResource(paths[i], clazz);
        }

        this.refresh();
    }

    protected Resource[] getConfigResources() {
        return this.configResources;
    }
}

DefaultListableBeanFactory

  • Spring中的单例Bean设计的。提供了统一访问单例Bean的功能,BeanFactory可实现此接口以提供访问内部单例Bean的能力。

  • BeanFactory是个Factory,也就是IOC容器或对象工厂,而

  • DefaultListableBeanFactory是Bean工厂的一个默认实现,

  • DefaultListableBeanFactory提供了原始的BeanFactory的功能,如:对外提供getbean()方法,维护一张beanDefinitionMap表

  • DefaultListableBeanFactory继承关系如下,可以看出

  • DefaultListableBeanFactory还有子类XmlBeanFactory

DefaultListableBeanFactory包含了Ioc容器的重要内容,很多容器都会用的它。如AbstractApplicationContext.refersh()方法就会销毁内部的容器并重新创建一个DefaultListableBeanFactory作为起内部使用。DefaultListableBeanFactory则直接继承它成为从XML读取资源的Ioc容器。

在DefaultListableBeanFactory有一个ConcurrentHashMap保存了Bean的定义。

image.png

getbean DefaultListableBeanFactory是Bean工厂的一个默认实现。截取DefaultListableBeanFactory中与getBean方法。

可以发现getBean有两种方式获取bean: 根据名称获取Bean,这个方法继承于AbstractBeanFactory 根据类型获取Bean,这个方法实现于DefaultListableBeanFactory,属于扩展了getBean方式

可以通过该方法添加格外的自动装配解析器,如:QualifierAnnotationAutowireCandidateResolver提供@Qualifier注解解析的功能和@Autowire

DefaultListableBeanFactory 源码

beanDefinitionMap

DefaultListableBeanFactory作为BeanFactory默认是维护这一张beanDefinition的表。

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

public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFactory implements ConfigurableListableBeanFactory, BeanDefinitionRegistry, Serializable {
    private static Class javaxInjectProviderClass = null;
    private static final Map<String, Reference<DefaultListableBeanFactory>> serializableFactories;
    private String serializationId;
    private boolean allowBeanDefinitionOverriding = true;
    private boolean allowEagerClassLoading = true;
    private AutowireCandidateResolver autowireCandidateResolver = new SimpleAutowireCandidateResolver();
    private final Map<Class, Object> resolvableDependencies = new HashMap();
    private final Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap();
    private final List<String> beanDefinitionNames = new ArrayList();
    private boolean configurationFrozen = false;
    private String[] frozenBeanDefinitionNames;

    static {
        ClassLoader cl = DefaultListableBeanFactory.class.getClassLoader();

        try {
            javaxInjectProviderClass = cl.loadClass("javax.inject.Provider");
        } catch (ClassNotFoundException var1) {
            ;
        }

        serializableFactories = new ConcurrentHashMap();
    }

    public DefaultListableBeanFactory() {
    }

    public DefaultListableBeanFactory(BeanFactory parentBeanFactory) {
        super(parentBeanFactory);
    }

    public void setSerializationId(String serializationId) {
        if (serializationId != null) {
            serializableFactories.put(serializationId, new WeakReference(this));
        } else if (this.serializationId != null) {
            serializableFactories.remove(this.serializationId);
        }

        this.serializationId = serializationId;
    }

    public void setAllowBeanDefinitionOverriding(boolean allowBeanDefinitionOverriding) {
        this.allowBeanDefinitionOverriding = allowBeanDefinitionOverriding;
    }

    public void setAllowEagerClassLoading(boolean allowEagerClassLoading) {
        this.allowEagerClassLoading = allowEagerClassLoading;
    }
/////这个set方法能启动扩展DefaultListableBeanFactory的功能。通过该方法给DefaultListableBeanFactory扩展自动装配的解析器。
    public void setAutowireCandidateResolver(final AutowireCandidateResolver autowireCandidateResolver) {
        Assert.notNull(autowireCandidateResolver, "AutowireCandidateResolver must not be null");
        if (autowireCandidateResolver instanceof BeanFactoryAware) {
            if (System.getSecurityManager() != null) {
                AccessController.doPrivileged(new PrivilegedAction<Object>() {
                    public Object run() {
                        ((BeanFactoryAware)autowireCandidateResolver).setBeanFactory(DefaultListableBeanFactory.this);
                        return null;
                    }
                }, this.getAccessControlContext());
            } else {
                ((BeanFactoryAware)autowireCandidateResolver).setBeanFactory(this);
            }
        }

        this.autowireCandidateResolver = autowireCandidateResolver;
    }

    public AutowireCandidateResolver getAutowireCandidateResolver() {
        return this.autowireCandidateResolver;
    }

    public void copyConfigurationFrom(ConfigurableBeanFactory otherFactory) {
        super.copyConfigurationFrom(otherFactory);
        if (otherFactory instanceof DefaultListableBeanFactory) {
            DefaultListableBeanFactory otherListableFactory = (DefaultListableBeanFactory)otherFactory;
            this.allowBeanDefinitionOverriding = otherListableFactory.allowBeanDefinitionOverriding;
            this.allowEagerClassLoading = otherListableFactory.allowEagerClassLoading;
            this.autowireCandidateResolver = otherListableFactory.autowireCandidateResolver;
            this.resolvableDependencies.putAll(otherListableFactory.resolvableDependencies);
        }

    }

    public <T> T getBean(Class<T> requiredType) throws BeansException {
        Assert.notNull(requiredType, "Required type must not be null");
        String[] beanNames = this.getBeanNamesForType(requiredType);
        if (beanNames.length > 1) {
            ArrayList<String> autowireCandidates = new ArrayList();
            String[] var7 = beanNames;
            int var6 = beanNames.length;

            for(int var5 = 0; var5 < var6; ++var5) {
                String beanName = var7[var5];
                if (this.getBeanDefinition(beanName).isAutowireCandidate()) {
                    autowireCandidates.add(beanName);
                }
            }

            if (autowireCandidates.size() > 0) {
                beanNames = (String[])autowireCandidates.toArray(new String[autowireCandidates.size()]);
            }
        }

        if (beanNames.length == 1) {
            return this.getBean(beanNames[0], requiredType);
        } else if (beanNames.length == 0 && this.getParentBeanFactory() != null) {
            return this.getParentBeanFactory().getBean(requiredType);
        } else {
            throw new NoSuchBeanDefinitionException(requiredType, "expected single bean but found " + beanNames.length + ": " + StringUtils.arrayToCommaDelimitedString(beanNames));
        }
    }

}

DefaultListableBeanFactory的层级结构图:

image.png

AbstractAutowireCapableBeanFactory:

AbstractBeanFactory:

除了BeanFactory这一支的接口,AbstractBeanFactory主要实现了AliasRegistry和SingletonBeanRegistry接口,这边主要提供了这样的三个功能: 别名管理,单例创建与注册,工厂方法FactoryBean支持.

FactoryBeanRegistrySupport:

DefaultSingletonBeanRegistry:

此接口是针对Spring中的单例Bean设计的。提供了统一访问单例Bean的功能,BeanFactory可实现此接口以提供访问内部单例Bean的能力。

共享bean实例的通用注册表,实现了SingletonBeanRegistry. 允许注册表中注册的单例应该被所有调用者共享,通过bean名称获得。

还支持登记的DisposableBean实例,(这可能会或不能正确的注册单例),关闭注册表时destroyed. 可以注册bean之间的依赖关系,执行适当的关闭顺序。

这个类主要用作基类的BeanFactory实现, 提供基本的管理 singleton bean 实例功能。

注意:与AbstractBeanFactory跟DefaultListableBeanFactory不同,这个类既不是一个bean definition概念的标识,也不标识特定的创建过程。也可以作为嵌套的助手来委托。

  • 负责管理singlenton对象,

  • 负责管理ObjectFactory对象

  • 负责管理singleanton对象与ObjectFactory对象的 beanName

  • 负责管理signleton状态中需要执行销毁流程的对象

  • 负责需要管理@Dependent注解以及spring boot里面的功能相同的注解产生的依赖关系与被依赖关系

  • 负责控制并发情况下销毁beanfactory

  • 负责控制并发情况下只有一个线程注册同一个bean。

DefaultSingletonBeanRegistry 源码

public class DefaultSingletonBeanRegistry extends SimpleAliasRegistry implements SingletonBeanRegistry {

  /** Maximum number of suppressed exceptions to preserve. */
  private static final int SUPPRESSED_EXCEPTIONS_LIMIT = 100;


  /** Cache of singleton objects: bean name to bean instance. */
  private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256);

  /** Cache of singleton factories: bean name to ObjectFactory. */
  private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap<>(16);

  /** Cache of early singleton objects: bean name to bean instance. */
  private final Map<String, Object> earlySingletonObjects = new HashMap<>(16);

  /** Set of registered singletons, containing the bean names in registration order. */
  private final Set<String> registeredSingletons = new LinkedHashSet<>(256);

  /** Names of beans that are currently in creation. */
  private final Set<String> singletonsCurrentlyInCreation =
        Collections.newSetFromMap(new ConcurrentHashMap<>(16));

  /** Names of beans currently excluded from in creation checks. */
  private final Set<String> inCreationCheckExclusions =
        Collections.newSetFromMap(new ConcurrentHashMap<>(16));

  /** Collection of suppressed Exceptions, available for associating related causes. */
  @Nullable
  private Set<Exception> suppressedExceptions;

DefaultSingletonBeanRegistry 结构图

image.png

SingletonBeanRegistry:

image.png

//将对象(singletonObject)注册为单例,名称为beanName
void registerSingleton(String beanName, Object singletonObject);
//获取名称为beanName的对象
Object getSingleton(String beanName);
//注册表中是否存在一个名称是beanName的单例
boolean containsSingleton(String beanName);
//获取注册表中所有的单例名称
String[] getSingletonNames();
//获取单例数量
int getSingletonCount();

BeanDefinitionRegistry

image.png

AliasRegistry

Spring Bean的别名管理

/**
 * Common interface for managing aliases. Serves as a super-interface (作为一个父接口)for
 * {@link org.springframework.beans.factory.support.BeanDefinitionRegistry}.
 */
public interface AliasRegistry {

   void registerAlias(String name, String alias);

   void removeAlias(String alias);

   boolean isAlias(String name);

   String[] getAliases(String name);

}

SimpleAliasRegistry:

BeanDefnition:

BeanDefinition描述一个bean实例,这个bean实例包含了属性值,构造函数的参数值,以及由具体实现提供额进一步信息。

image.png

image.png

FactoryBeanRegistrySupport

持单例注册表的基类,需要处理 {@link org.springframework.beans.factoryFactoryBean}实例, 集成了{@link DefaultSingletonBeanRegistry}的单例管理。

image.png

 
public abstract class FactoryBeanRegistrySupport extends DefaultSingletonBeanRegistry {

   /** Cache of singleton objects created by FactoryBeans: FactoryBean name to object. */
   private final Map<String, Object> factoryBeanObjectCache = new ConcurrentHashMap<>(16);


   /**
    * Determine the type for the given FactoryBean.
    * @param factoryBean the FactoryBean instance to check
    * @return the FactoryBean's object type,
    * or {@code null} if the type cannot be determined yet
    */
   @Nullable
   protected Class<?> getTypeForFactoryBean(final FactoryBean<?> factoryBean) {
      try {
         if (System.getSecurityManager() != null) {
            return AccessController.doPrivileged((PrivilegedAction<Class<?>>)
                  factoryBean::getObjectType, getAccessControlContext());
         }
         else {
            return factoryBean.getObjectType();
         }
      }
      catch (Throwable ex) {
         // Thrown from the FactoryBean's getObjectType implementation.
         logger.info("FactoryBean threw exception from getObjectType, despite the contract saying " +
               "that it should return null if the type of its object cannot be determined yet", ex);
         return null;
      }
   }