天天看点

Spring源码系列(一)——容器的创建

一、容器的创建

下面从Spring容器的创建开始分析,逐步深入来探究Spring的源码。

入口函数:

public static void main(String[] args) {
    // 创建容器
    AnnotationConfigApplicationContext annotationConfigApplicationContext = new AnnotationConfigApplicationContext(AppConfig.class);

    // 从容器中获取Bean
    IndexDao dao = annotationConfigApplicationContext.getBean(IndexDao.class);

    // 调用Bean的方法
    dao.query();
}
           

这里要看一下

AnnotationConfigApplicationContext

这个类的构造方法:

public AnnotationConfigApplicationContext(Class<?>... annotatedClasses) {
    // 这里由于它有父类构造方法,故而先调用父类的构造方法,然后才会调用自己的构造方法
    this();
    register(annotatedClasses);
    refresh();
}
           

因为需要调用父类的构造方法,所以看下

AnnotationConfigApplicationContext

继承结构:

Spring源码系列(一)——容器的创建

查看

GenericApplicationContext

类,并查看其构造方法:

public GenericApplicationContext() {
    // 创建一个DefaultListableBeanFactory工厂
    this.beanFactory = new DefaultListableBeanFactory();
}
           
注:对于这个

DefaultListableBeanFactory

,我们就可以把它当成一个Spring容器

下面要看一下

AnnotationConfigApplicationContext

无参构造方法了,因为上面的构造方法中调用了

this()

方法。

public AnnotationConfigApplicationContext() {
    // 创建一个 AnnotatedBeanDefinitionReader读取器,
    // 同时向容器中填加了6个Spring的后置处理器:BeanFactoryPostProcessor、BeanPostProcessor
    this.reader = new AnnotatedBeanDefinitionReader(this);

    // 可以用来扫描包或者类,继而转换成BeanDefinition,但实际上我们扫描包工作不是这个scanner对象来完成的
    // 是spring自己new的一个ClassPathBeanDefinitionScanner
    // 这里的scanner仅仅是为了能够让程序员在外部调用AnnotationConfigApplicationContext对象的scan方法
    this.scanner = new ClassPathBeanDefinitionScanner(this);
}
           

这个无参的构造方法,初始化一个bean的读取器和扫描器。

从这地方可以看出,我们的入口程序可以换一种写法,代码如下:

public static void main(String[] args) {
    
    AnnotationConfigApplicationContext annotationConfigApplicationContext = new AnnotationConfigApplicationContext();
    
    annotationConfigApplicationContext.register(AppConfig.class);
    annotationConfigApplicationContext.refresh();
    
    IndexDao dao = annotationConfigApplicationContext.getBean(IndexDao.class);
    dao.query();
}
           

以上代码能看懂么?其实就是把带参数的构造函数中的两行代码提取出来了,直接调用了

AnnotationConfigApplicationContext

无参构造函数。

二、读取器创建

读取器和扫描器创建的入口在

AnnotationConfigApplicationContext

无参构造方法中,来看下面的代码:

注:此处的this为

AnnotationConfigApplicationContext

,表示一个Registry

进入到

AnnotatedBeanDefinitionReader

的构造函数中:

public AnnotatedBeanDefinitionReader(BeanDefinitionRegistry registry) {
    // 调用两个参数的构造器,如下
    this(registry, getOrCreateEnvironment(registry));
}

// 两个参数的构造器
public AnnotatedBeanDefinitionReader(BeanDefinitionRegistry registry, 
                                     Environment environment) {
    this.registry = registry;
    this.conditionEvaluator = new ConditionEvaluator(registry, environment, null);
    // 这地方很重要(☆☆☆☆☆)
    AnnotationConfigUtils.registerAnnotationConfigProcessors(this.registry);
}
           

下面来看下

AnnotationConfigUtils

这个类的

registerAnnotationConfigProcessors()

方法:

public static void registerAnnotationConfigProcessors(BeanDefinitionRegistry registry) {
   // 下面
   registerAnnotationConfigProcessors(registry, null);
}

// registerAnnotationConfigProcessors方法
public static Set<BeanDefinitionHolder> registerAnnotationConfigProcessors(
    BeanDefinitionRegistry registry, @Nullable Object source) {

    // 这行就是验证传进来的registry是不是DefaultListableBeanFactory类型,第一部分已说明,是!!
    DefaultListableBeanFactory beanFactory = unwrapDefaultListableBeanFactory(registry);

    if (beanFactory != null) {
        if (!(beanFactory.getDependencyComparator() instanceof AnnotationAwareOrderComparator)) {
            // AnnotationAwareOrderComparator主要能解析@Order注解和@Priority
            beanFactory.setDependencyComparator(AnnotationAwareOrderComparator.INSTANCE);
        }
        if (!(beanFactory.getAutowireCandidateResolver() instanceof ContextAnnotationAutowireCandidateResolver)) {
            // ContextAnnotationAutowireCandidateResolver提供处理延迟加载的功能
            beanFactory.setAutowireCandidateResolver(new ContextAnnotationAutowireCandidateResolver());
        }
    }

    Set<BeanDefinitionHolder> beanDefs = new LinkedHashSet<>(8);
    
    //BeanDefinitio的注册,这里很重要,需要理解注册每个bean的类型
    // 1、org.springframework.context.annotation.internalConfigurationAnnotationProcessor
    if (!registry.containsBeanDefinition(CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME)) {
        // 向registry中放入ConfigurationClassPostProcessor
        RootBeanDefinition def = new RootBeanDefinition(ConfigurationClassPostProcessor.class);
        def.setSource(source);
        // 往Set集合中加入ConfigurationClassPostProcessor
        beanDefs.add(registerPostProcessor(registry, def, CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME));
    }

    // 2、org.springframework.context.annotation.internalAutowiredAnnotationProcessor
    if (!registry.containsBeanDefinition(AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME)) {
        RootBeanDefinition def = new RootBeanDefinition(AutowiredAnnotationBeanPostProcessor.class);
        def.setSource(source);
        beanDefs.add(registerPostProcessor(registry, def, AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME));
    }

    // 3、org.springframework.context.annotation.internalRequiredAnnotationProcessor
    if (!registry.containsBeanDefinition(REQUIRED_ANNOTATION_PROCESSOR_BEAN_NAME)) {
        RootBeanDefinition def = new RootBeanDefinition(RequiredAnnotationBeanPostProcessor.class);
        def.setSource(source);
        beanDefs.add(registerPostProcessor(registry, def, REQUIRED_ANNOTATION_PROCESSOR_BEAN_NAME));
    }

    // 4、org.springframework.context.annotation.internalCommonAnnotationProcessor
    if (jsr250Present && !registry.containsBeanDefinition(COMMON_ANNOTATION_PROCESSOR_BEAN_NAME)) {
        RootBeanDefinition def = new RootBeanDefinition(CommonAnnotationBeanPostProcessor.class);
        def.setSource(source);
        beanDefs.add(registerPostProcessor(registry, def, COMMON_ANNOTATION_PROCESSOR_BEAN_NAME));
    }

    // 5、org.springframework.context.annotation.internalPersistenceAnnotationProcessor
    if (jpaPresent && !registry.containsBeanDefinition(PERSISTENCE_ANNOTATION_PROCESSOR_BEAN_NAME)) {
        RootBeanDefinition def = new RootBeanDefinition();
            		  def.setBeanClass(ClassUtils.forName(PERSISTENCE_ANNOTATION_PROCESSOR_CLASS_NAME,
                                    AnnotationConfigUtils.class.getClassLoader()));
        def.setSource(source);
        beanDefs.add(registerPostProcessor(registry, def, PERSISTENCE_ANNOTATION_PROCESSOR_BEAN_NAME));
    }

    // 6、org.springframework.context.event.internalEventListenerProcessor
    if (!registry.containsBeanDefinition(EVENT_LISTENER_PROCESSOR_BEAN_NAME)) {
        RootBeanDefinition def = new RootBeanDefinition(EventListenerMethodProcessor.class);
        def.setSource(source);
        beanDefs.add(registerPostProcessor(registry, def, EVENT_LISTENER_PROCESSOR_BEAN_NAME));
    }

    // 7、org.springframework.context.event.internalEventListenerFactory
    if (!registry.containsBeanDefinition(EVENT_LISTENER_FACTORY_BEAN_NAME)) {
        RootBeanDefinition def = new RootBeanDefinition(DefaultEventListenerFactory.class);
        def.setSource(source);
        beanDefs.add(registerPostProcessor(registry, def, EVENT_LISTENER_FACTORY_BEAN_NAME));
    }

    return beanDefs;
}
           
在上面的代码中,创建了一个大小为8的Set集合,集合元素类型为:

BeanDefinitionHolder

并把下面7个类定义成

BeanDefinitionHolder

后添加到Set中,并返回。
  • ConfigurationClassPostProcessor.class

  • AutowiredAnnotationBeanPostProcessor.class

  • RequiredAnnotationBeanPostProcessor.class

  • CommonAnnotationBeanPostProcessor.class

    (Bean生命周期回调方法)
  • PersistenceAnnotationBeanPostProcessor.class

  • EventListenerMethodProcessor.class

  • DefaultEventListenerFactory.class

下图是debug断点后,看到的Set集合中的内容为6个,其中,

PersistenceAnnotationBeanPostProcessor.class

这个类不符合要求,没有被添加。

这6个类要么是

BeanFactoryPostProcessor

的实现,要么是

BeanPostProcessor

的实现。

Spring源码系列(一)——容器的创建
Spring源码系列(一)——容器的创建

上面的代码需要注意一下下面这行代码,下面来介绍一下这个

registerPostProcessor()

方法

AnnotationConfigUtils.registerPostProcessor()

方法如下:

private static BeanDefinitionHolder registerPostProcessor(BeanDefinitionRegistry registry, RootBeanDefinition definition, String beanName) {
    definition.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
    // 向registry中注册BeanDefinition
    registry.registerBeanDefinition(beanName, definition);
    return new BeanDefinitionHolder(definition, beanName);
}
           

其实搞清楚这个方法,就是要搞清楚

BeanDefinitionRegistry

BeanDefinitionHolder

是干嘛的。

BeanDefinitionRegistry

是个接口,里面定义了一些操作

BeanDefinition

的方法,如下:

public interface BeanDefinitionRegistry extends AliasRegistry {

	void registerBeanDefinition(String beanName, BeanDefinition beanDefinition);

	void removeBeanDefinition(String beanName);

	BeanDefinition getBeanDefinition(String beanName) ;

	boolean containsBeanDefinition(String beanName);

	String[] getBeanDefinitionNames();

	int getBeanDefinitionCount();

	boolean isBeanNameInUse(String beanName);
}
           

而这些方法的主要实现类如下,是不是有看到了熟悉的

DefaultListableBeanFactory

Spring源码系列(一)——容器的创建

下面要来看下

DefaultListableBeanFactory

中的

registerBeanDefinition()

其实Spring容器,底层就是一个

ConcurrentHashMap

// 存放所有BeanDefinition的Map
private final Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<>(256);

// 存放了所有BeanDefinition的名字,通过扫描进去的
private volatile List<String> beanDefinitionNames = new ArrayList<>(256);

@Override
public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition)
    throws BeanDefinitionStoreException {

    // 先从beanDefinitionMap中,根据beanName去获取BeanDefinition
    BeanDefinition existingDefinition = this.beanDefinitionMap.get(beanName);
    
    if (existingDefinition != null) {
        this.beanDefinitionMap.put(beanName, beanDefinition);
    } else {
        if (hasBeanCreationStarted()) {
            synchronized (this.beanDefinitionMap) {
                this.beanDefinitionMap.put(beanName, beanDefinition);
                List<String> updatedDefinitions = new ArrayList<>(this.beanDefinitionNames.size() + 1);
                updatedDefinitions.addAll(this.beanDefinitionNames);
                updatedDefinitions.add(beanName);
                this.beanDefinitionNames = updatedDefinitions;
                if (this.manualSingletonNames.contains(beanName)) {
                    Set<String> updatedSingletons = new LinkedHashSet<>(this.manualSingletonNames);
                    updatedSingletons.remove(beanName);
                    this.manualSingletonNames = updatedSingletons;
                }
            }
        } else {
            // Still in startup registration phase
            this.beanDefinitionMap.put(beanName, beanDefinition);
            this.beanDefinitionNames.add(beanName);
            this.manualSingletonNames.remove(beanName);
        }
        this.frozenBeanDefinitionNames = null;
    }

    if (existingDefinition != null || containsSingleton(beanName)) {
        resetBeanDefinition(beanName);
    } else if (isConfigurationFrozen()) {
        clearByTypeCache();
    }
}
           

BeanDefinitionHolder

类如下,就是对

BeanDefinition

进行了再次封装。

public class BeanDefinitionHolder implements BeanMetadataElement {

	private final BeanDefinition beanDefinition;

	private final String beanName;
    
    //…… 略
}
           

下面打一个断点在

registerAnnotationConfigProcessors()

方法的

return beanDefs;

语句,看下面两个集合中的内容。

beanDefinitionNames

是个 List。

Spring源码系列(一)——容器的创建

beanDefinitionMap

是个Map。

Spring源码系列(一)——容器的创建

到此处,读取器的创建就结束了。回想一下,到目前为止,做了哪些工作?

只是向Spring容器中添加了6个

BeanDefinition

,需要注意的是:这6个

BeanDefinition

是Spring 自己添加的,这6个

BeanDefinition

的功能是什么呢???Spring不会平白无故的往容器中放多余的东西吧。

这里,只是完成了

Class

类到

BeanDefinition

的转变,但

BeanDefinition

并没有实例化。

所以,这6个

BeanDefinition

很重要,后面会讲解它们的作用。

三、扫描器创建

从上文可以知道,扫描器创建的入口也在

AnnotationConfigApplicationContext

无参构造函数中,来看下面的代码:

这地方创建了一个

ClassPathBeanDefinitionScanner

扫描器对象,通过层层的构造函数封装,调用到了下面的这个构造函数。这地方代码不重要,可以直接忽略。

public ClassPathBeanDefinitionScanner(BeanDefinitionRegistry registry, boolean useDefaultFilters,
							Environment environment, @Nullable ResourceLoader resourceLoader) {

    this.registry = registry;

    if (useDefaultFilters) {
        registerDefaultFilters();
    }
    setEnvironment(environment);
    setResourceLoader(resourceLoader);
}
           
对于这个这个

ClassPathBeanDefinitionScanner

扫描器,只需要知道下面的内容:

这个扫描器可以用来扫描包或者类,继而将扫描到的类转换成

BeanDefinition

,但是实际上我们扫描包工作不是这个

scanner

对象来完成的!!!而是Spring自己new的一个

ClassPathBeanDefinitionScanner

,后面的代码分析会讲到。

这里的

scanner

仅仅是为了程序员能够在外部调用

AnnotationConfigApplicationContext

对象的

scan

方法。

四、小结

到目前为止,Spring做了以下几部分工作:

  • 创建了一个

    DefaultListableBeanFactory

    容器
  • 创建一个

    AnnotatedBeanDefinitionReader

    读取器
    • 在创建读取器的过程中,向Spring容器中添加了6个Spring自己的

      BeanDefinition

  • 创建一个

    ClassPathBeanDefinitionScanner

    扫描器
    • 这个扫描器仅仅是为了让程序员能够在外部调用,Spring真正的扫描工作不是这个扫描器来完成的

五、补充

1.BeanPostProcessor

BeanPostProcessor

是Spring框架提供的一个扩展类点,但Spring的扩展类点不止这一个。

通过实现

BeanPostProcessor

接口,程序员就可插手

Spring Bean

实例化的过程,在

Bean

实例化之后、初始化之前执行,从而减轻了

BeanFactory

的负担,值得说明的是这个接口可以设置多个,会形成一个列表,然后依次执行。

程序员自己定义的

BeanPostProcessor

,只需要实现

BeanPostProcessor

接口,然后加上

@Component

注解,就可以自动被扫描并添加到Spring容器中,但是Spring框架默认的怎么办呢?

本文第二部分,在读取器创建的时候,Spring框架就默认创建了5个

BeanPostProcessor

。这5个

BeanPostProcessor

非常重要。

比如

AOP

就是在Bean实例后期间将切面逻辑织入Bean实例中的,

AOP

也正是通过

BeanPostProcessor

和Spring容器建立起了联系。

下面看看Spring提供哪些默认的

BeanPostProcessor

实现,前方高能!!!

因为高能,故而只是解释几个常用的:

  • ApplicationContextAwareProcessor,简写acap

    作用:当应用程序定义的Bean实现

    ApplicationContextAware

    接口时注入

    ApplicationContext

    对象
  • InitDestroyAnnotationBeanPostProcessor

    作用: 用来处理自定义的初始化方法和销毁方法。

    Spring中提供了3种自定义初始化和销毁方法分别是

    • 通过@Bean指定init-method和destroy-method属性
    • Bean实现InitializingBean接口和实现DisposableBean
    • @PostConstruct、@PreDestroy

    为什么spring通这三种方法都能完成对bean生命周期的回调呢?

    可以通过InitDestroyAnnotationBeanPostProcessor的源码来解释

  • InstantiationAwareBeanPostProcessor
  • CommonAnnotationBeanPostProcessor
  • AutowiredAnnotationBeanPostProcessor
  • RequiredAnnotationBeanPostProcessor
  • BeanValidationPostProcessor
  • AbstractAutoProxyCreator

2.Spring容器中属性说明

BeanDefinition

:简称bd,是对一个

Bean

的描述。类比,在Java中,你要描述一个用户,你得定义一个User类,在Spring中,你要描述一个

Bean

的话,就定义个

BeanDefinition

beanDefinitionNames

:存在

Bean

的名字

beanDefinitionMap

:存放

Bean

的名字与

BeanDefinition

的对应关系

AnnotatedBeanDefinitionReader

BeanDefinitionRegistry

:简称bdr,把一个

BeanDefinition

放入到

beanDefinitionMap

中。

继续阅读