spring-源码-AnnotationConfigApplicationContext-创建分析-3

前言

该文主要是对其源码分析,以及单独调用记录

ClassPathBeanDefinitionScanner

一个bean定义扫描器,它检测类路径上的所有bean,并用给定的注册表(BeanFactory或ApplicationContext)注册相应的bean定义。
候选类别通过可配置的类型过滤器进行检测。

默认的过滤器包括用Spring的@Component、@Repository、@Service或@Controller构造型注释的类。

如果可用,还支持Java EE 6的@ManagedBean和@Named注解。

继承体系

  1. ClassPathBeanDefinitionScanner
    1. 继承了ClassPathScanningCandidateComponentProvider

开始

创建一个ClassPathBeanDefinitionScanner,将AnnotationConfigApplicationContext向下传递

  1. 创建 BeanDefinition 扫描器,可以用来扫描包或者类,继而转换为 BeanDefinition
  2. spring默认的扫描器其实不是这个scanner对象,而是在后面自己又重新new了一个ClassPathBeanDefinitionScanner
  3. spring在执行工程后置处理器 ConfigurationClassPostProcessor 时,去扫描包时会 new一个ClassPathBeanDefinitionScanner
  4. 这里的 scanne r仅仅是为了程序员可以手动调用 AnnotationConfigApplicationContext 对象的 scan 方法
public AnnotationConfigApplicationContext() {
    //构建一个扫描器,用于扫描 Class 并且定义成 BeanDefinition
    this.scanner = new ClassPathBeanDefinitionScanner(this);
}

ClassPathBeanDefinitionScanner

接收了一个参数:AnnotationConfigApplicationContext (BeanDefinitionRegistry)

public ClassPathBeanDefinitionScanner(BeanDefinitionRegistry registry) {
    //穿
    this(registry, true);
}

ClassPathBeanDefinitionScanner

  1. BeanDefinitionRegistry,这里其实可以理解为获取的是 beanFactory
  2. true 表示默认的过筛选器
public ClassPathBeanDefinitionScanner(BeanDefinitionRegistry registry, boolean useDefaultFilters) {
    //注意这个方法是 获取或者创建,其实这个 StandardEnvironment 是在 AnnotatedBeanDefinitionReader 的时候已经创建了,所以这次是去获取
    this(registry, useDefaultFilters, getOrCreateEnvironment(registry));
}

ClassPathBeanDefinitionScanner

接收了三个参数:

  1. BeanDefinitionRegistry,这里其实可以理解为获取的是 beanFactory

  2. true 表示默认的过筛选器

  3. Environment(StandardEnvironment)

public ClassPathBeanDefinitionScanner(BeanDefinitionRegistry registry, boolean useDefaultFilters,
                                      Environment environment) {
    this(registry, useDefaultFilters, environment,
         (registry instanceof ResourceLoader ? (ResourceLoader) registry : null));
 
}

ClassPathBeanDefinitionScanner

  1. BeanDefinitionRegistry,这里其实可以理解为获取的是 beanFactory
  2. true 表示默认的过筛选器
  3. Environment(StandardEnvironment)
  4. ResourceLoader(AnnotationConfigApplicationContext)
public ClassPathBeanDefinitionScanner(BeanDefinitionRegistry registry, boolean useDefaultFilters,
                                      Environment environment, @Nullable ResourceLoader resourceLoader) {
    // ClassPathBeanDefinitionScanner 继承了 ClassPathScanningCandidateComponentProvider
    super();
    this.registry = registry;
    // 存在默认的筛选器... 这里传递过来的就是ture....
    if (useDefaultFilters) {
        // 主要关注的是整个方法,
        registerDefaultFilters();
    }
    //设置环境
    setEnvironment(environment);
    //设置资源的加载器
    setResourceLoader(resourceLoader);
}
 

调用registerDefaultFilters()

那其实可以理解 includeFilters 和 excludeFilters的参数了

  1. includeFilters 就是我们主要定义这些注解就能被 spring 扫描到
  2. excludeFilters 就是我们如果定义了这些注解就不能被 spring 扫描到
private final List<TypeFilter> includeFilters = new LinkedList<>();
protected void registerDefaultFilters() {
    // 注册 @Component 类型的过滤器,只要带有这个注解的bean定义都会被扫描,也包括包装这个注解的注解
    this.includeFilters.add(new AnnotationTypeFilter(Component.class));
    ClassLoader cl = ClassPathScanningCandidateComponentProvider.class.getClassLoader();
    try {
        //@ManagedBean 如果存在如果存在也会被扫描
        this.includeFilters.add(new AnnotationTypeFilter(
            ((Class<? extends Annotation>) ClassUtils.forName("javax.annotation.ManagedBean", cl)), false));
    } catch (ClassNotFoundException ex) {
    }
    try {
        //@Named 如果存在也会被扫描
        this.includeFilters.add(new AnnotationTypeFilter(
            ((Class<? extends Annotation>) ClassUtils.forName("javax.inject.Named", cl)), false));
    } catch (ClassNotFoundException ex) {
    }
}

后言

通过源码分析我们知道了

  1. 在初始化的时候帮我们创建了: ClassPathBeanDefinitionScanner
  2. 创建了:StandardEnvironment
  3. 将这些@Component@ManagedBean@Named注解添加到集合当中,包括类型是一样的也会添加到容器中,例如:@Service

扩展阅读

简单来说不依托于AnnotationConfigApplicationContext的运行,单独拿这一小块内容出来使用

@Component
public class ClassPathBeanDefinitionScannerContext {

    public static void main(String[] args) {
        // 创建 BeanFactory
        DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
        // 创建扫描器
        ClassPathBeanDefinitionScanner value = new ClassPathBeanDefinitionScanner(beanFactory);
        // 这里需要注意不要使用 toString方法
        value.scan(ClassPathBeanDefinitionScannerContext.class.getPackage().getName());
        // 创建Bean
        User bean = beanFactory.getBean(User.class);
        System.out.println(bean);
    }
}

@Component
class User {
}

流程图

在这里插入图片描述

后续文章

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值