Skip to content

AnnotationConfigApplicationContext源码解析

一、AnnotationConfigApplicationContext的定位与核心功能

AnnotationConfigApplicationContext是Spring框架中基于注解的应用上下文实现,属于ApplicationContext体系的子类,主要用于替代传统XML配置,通过注解(如@Configuration@Component@Bean)管理Bean的定义与生命周期。

核心功能

  1. 注册配置类:通过register(Class<?>... componentClasses)方法注册标注了@Configuration的类(或直接标注@Component的类)。
  2. 扫描组件:通过scan(String... basePackages)方法扫描指定包下的@Component及其派生注解(@Service@Repository@Controller)标注的类。
  3. 刷新上下文:通过refresh()方法触发Spring容器的初始化流程(BeanDefinition解析、实例化、依赖注入等)。
  4. 管理Bean:提供getBean()getBeanDefinition()等方法获取Bean或其定义。

二、AnnotationConfigApplicationContext的继承体系

AnnotationConfigApplicationContext的继承关系如下:

ApplicationContext (接口)
└── ConfigurableApplicationContext (接口)
    └── AbstractApplicationContext (抽象类)
        └── GenericApplicationContext (抽象类)
            └── AnnotationConfigApplicationContext (实现类)

同时,它还实现了AnnotationConfigRegistry接口(定义了registerscan方法)。

关键父类/接口的作用

  • GenericApplicationContext:持有一个DefaultListableBeanFactory(Spring核心Bean工厂),负责存储BeanDefinition和实例化Bean。
  • AnnotationConfigRegistry:定义了register(注册配置类)和scan(扫描组件)方法,由AnnotationConfigApplicationContext实现。

三、AnnotationConfigApplicationContext的核心组件

AnnotationConfigApplicationContext的核心功能依赖于以下组件:

组件作用
DefaultListableBeanFactory核心Bean工厂,存储BeanDefinition,负责Bean的实例化、依赖注入等。
AnnotatedBeanDefinitionReader读取直接注册的注解类(如@Configuration@Bean),生成AnnotatedBeanDefinition
ClassPathBeanDefinitionScanner扫描类路径下的组件(如@Component@Service),生成BeanDefinition
ConfigurationClassPostProcessor解析@Configuration类中的注解(@Bean@ComponentScan@Import),生成对应的BeanDefinition(关键处理器)。
AutowiredAnnotationBeanPostProcessor处理@Autowired注解,完成依赖注入。

四、AnnotationConfigApplicationContext源码深度剖析

我们从构造方法注册流程扫描流程刷新流程四个核心环节展开源码分析。

1. 构造方法:初始化核心组件

AnnotationConfigApplicationContext的构造方法主要初始化AnnotatedBeanDefinitionReaderClassPathBeanDefinitionScanner,并关联当前上下文(作为BeanDefinitionRegistry)。

java
public class AnnotationConfigApplicationContext extends GenericApplicationContext implements AnnotationConfigRegistry {
    // 用于读取直接注册的注解类(如@Configuration)
    private final AnnotatedBeanDefinitionReader reader;
    // 用于扫描类路径下的组件(如@Component)
    private final ClassPathBeanDefinitionScanner scanner;

    // 无参构造:需后续调用register/scan方法
    public AnnotationConfigApplicationContext() {
        // 初始化AnnotatedBeanDefinitionReader,关联当前上下文(BeanDefinitionRegistry)
        this.reader = new AnnotatedBeanDefinitionReader(this);
        // 初始化ClassPathBeanDefinitionScanner,关联当前上下文(BeanDefinitionRegistry)
        this.scanner = new ClassPathBeanDefinitionScanner(this);
    }

    // 有参构造:直接传入配置类,自动注册并刷新
    public AnnotationConfigApplicationContext(Class<?>... componentClasses) {
        this(); // 调用无参构造初始化reader和scanner
        register(componentClasses); // 注册配置类
        refresh(); // 刷新上下文(核心流程)
    }
}

2. 注册流程:register方法

register方法用于注册具体的类(如@Configuration类、@Bean标注的类),由AnnotatedBeanDefinitionReader完成BeanDefinition的生成与注册。

2.1 入口方法

java
// AnnotationConfigApplicationContext.java
@Override
public void register(Class<?>... componentClasses) {
    Assert.notEmpty(componentClasses, "At least one component class must be specified");
    this.reader.register(componentClasses); // 委托给AnnotatedBeanDefinitionReader
}

2.2 AnnotatedBeanDefinitionReader的register逻辑

AnnotatedBeanDefinitionReaderregister方法遍历每个类,生成AnnotatedGenericBeanDefinition(标注了注解的BeanDefinition),并处理注解(如@Scope@Lazy@Primary)。

java
// AnnotatedBeanDefinitionReader.java
public void register(Class<?>... componentClasses) {
    for (Class<?> componentClass : componentClasses) {
        registerBean(componentClass);
    }
}

public void registerBean(Class<?> beanClass) {
    doRegisterBean(beanClass, null, null, null, null);
}

// 核心逻辑:生成BeanDefinition并注册
private <T> void doRegisterBean(Class<T> beanClass, @Nullable String name,
                                 @Nullable Class<? extends Annotation>[] qualifiers,
                                 @Nullable Supplier<T> supplier,
                                 @Nullable BeanDefinitionCustomizer[] customizers) {
    // 1. 生成AnnotatedGenericBeanDefinition(包含类的元数据)
    AnnotatedGenericBeanDefinition abd = new AnnotatedGenericBeanDefinition(beanClass);
    
    // 2. 处理@Conditional注解:判断是否跳过注册(如@ConditionalOnProperty未满足)
    if (this.conditionEvaluator.shouldSkip(abd.getMetadata())) {
        return;
    }
    
    // 3. 设置实例供应商(可选,用于自定义实例化逻辑)
    abd.setInstanceSupplier(supplier);
    
    // 4. 处理@Scope注解:解析作用域(如singleton、prototype)
    ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(abd);
    abd.setScope(scopeMetadata.getScopeName());
    
    // 5. 生成Bean名称(默认:类名首字母小写,如UserService→userService)
    String beanName = (name != null ? name : this.beanNameGenerator.generateBeanName(abd, this.registry));
    
    // 6. 处理通用注解:@Lazy(懒加载)、@Primary(优先注入)、@DependsOn(依赖顺序)等
    AnnotationConfigUtils.processCommonDefinitionAnnotations(abd);
    
    // 7. 处理限定符注解:@Qualifier(指定注入名称)、@Primary(优先注入)
    if (qualifiers != null) {
        for (Class<? extends Annotation> qualifier : qualifiers) {
            if (Primary.class == qualifier) {
                abd.setPrimary(true);
            } else if (Lazy.class == qualifier) {
                abd.setLazyInit(true);
            } else {
                abd.addQualifier(new AutowireCandidateQualifier(qualifier));
            }
        }
    }
    
    // 8. 处理自定义器(可选,用于修改BeanDefinition)
    if (customizers != null) {
        for (BeanDefinitionCustomizer customizer : customizers) {
            customizer.customize(abd);
        }
    }
    
    // 9. 封装为BeanDefinitionHolder(包含Bean名称和定义)
    BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(abd, beanName);
    
    // 10. 处理作用域代理(如prototype作用域的Bean被singleton引用时,生成代理)
    definitionHolder = AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);
    
    // 11. 注册到BeanDefinitionRegistry(即当前AnnotationConfigApplicationContext)
    BeanDefinitionReaderUtils.registerBeanDefinition(definitionHolder, this.registry);
}

3. 扫描流程:scan方法

scan方法用于扫描类路径下的组件(如@Component@Service),由ClassPathBeanDefinitionScanner完成BeanDefinition的生成与注册。

3.1 入口方法

java
// AnnotationConfigApplicationContext.java
@Override
public void scan(String... basePackages) {
    Assert.notEmpty(basePackages, "At least one base package must be specified");
    this.scanner.scan(basePackages); // 委托给ClassPathBeanDefinitionScanner
}

3.2 ClassPathBeanDefinitionScanner的scan逻辑

ClassPathBeanDefinitionScannerscan方法遍历指定包,通过ASM技术(不加载类)读取类元数据,过滤出符合条件的类(如标注了@Component),生成BeanDefinition。

java
// ClassPathBeanDefinitionScanner.java
public int scan(String... basePackages) {
    int beanCountAtScanStart = this.registry.getBeanDefinitionCount();
    doScan(basePackages); // 核心扫描逻辑
    // 注册默认的注解处理器(如ConfigurationClassPostProcessor)
    if (this.includeAnnotationConfig) {
        AnnotationConfigUtils.registerAnnotationConfigProcessors(this.registry);
    }
    return this.registry.getBeanDefinitionCount() - beanCountAtScanStart;
}

// 核心扫描逻辑:找出候选组件并注册
protected Set<BeanDefinitionHolder> doScan(String... basePackages) {
    Assert.notEmpty(basePackages, "At least one base package must be specified");
    Set<BeanDefinitionHolder> beanDefinitions = new LinkedHashSet<>();
    
    for (String basePackage : basePackages) {
        // 1. 找出候选组件(标注了@Component及其派生注解的类)
        Set<BeanDefinition> candidates = findCandidateComponents(basePackage);
        
        for (BeanDefinition candidate : candidates) {
            // 2. 处理@Scope注解:解析作用域
            ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(candidate);
            candidate.setScope(scopeMetadata.getScopeName());
            
            // 3. 生成Bean名称(默认:类名首字母小写)
            String beanName = this.beanNameGenerator.generateBeanName(candidate, this.registry);
            
            // 4. 处理通用注解(如@Lazy、@Primary)
            if (candidate instanceof AnnotatedBeanDefinition) {
                AnnotationConfigUtils.processCommonDefinitionAnnotations((AnnotatedBeanDefinition) candidate);
            }
            
            // 5. 检查候选Bean:是否有重复名称或不符合自动装配条件
            if (checkCandidate(beanName, candidate)) {
                BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(candidate, beanName);
                // 6. 处理作用域代理(如prototype→代理)
                definitionHolder = AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);
                beanDefinitions.add(definitionHolder);
                // 7. 注册到BeanDefinitionRegistry
                registerBeanDefinition(definitionHolder, this.registry);
            }
        }
    }
    
    return beanDefinitions;
}

3.3 候选组件的筛选:findCandidateComponents

findCandidateComponents方法通过ResourcePatternResolver遍历类路径下的.class文件,使用MetadataReader读取类元数据(如注解),过滤出符合条件的类(默认过滤@Component注解)。

java
// ClassPathScanningCandidateComponentProvider.java(父类)
public Set<BeanDefinition> findCandidateComponents(String basePackage) {
    if (this.componentsIndex != null && indexSupportsIncludeFilters()) {
        // 使用索引加速扫描(Spring 5+支持)
        return addCandidateComponentsFromIndex(this.componentsIndex, basePackage);
    } else {
        // 传统扫描方式:遍历类路径
        return scanCandidateComponents(basePackage);
    }
}

private Set<BeanDefinition> scanCandidateComponents(String basePackage) {
    Set<BeanDefinition> candidates = new LinkedHashSet<>();
    try {
        // 将包路径转换为资源路径(如com.example→classpath*:com/example/**/*.class)
        String packageSearchPath = ResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX +
                resolveBasePackage(basePackage) + '/' + this.resourcePattern;
        // 找到所有匹配的资源(.class文件)
        Resource[] resources = getResourcePatternResolver().getResources(packageSearchPath);
        
        for (Resource resource : resources) {
            if (resource.isReadable()) {
                try {
                    // 读取类元数据(不加载类)
                    MetadataReader metadataReader = getMetadataReaderFactory().getMetadataReader(resource);
                    // 过滤:是否符合includeFilters(默认:@Component)且不符合excludeFilters
                    if (isCandidateComponent(metadataReader)) {
                        // 生成ScannedGenericBeanDefinition(包含类元数据)
                        ScannedGenericBeanDefinition sbd = new ScannedGenericBeanDefinition(metadataReader);
                        sbd.setResource(resource);
                        sbd.setSource(resource);
                        // 再次检查:是否是具体类(非接口/抽象类)
                        if (isCandidateComponent(sbd)) {
                            candidates.add(sbd);
                        }
                    }
                } catch (Throwable ex) {
                    throw new BeanDefinitionStoreException(
                            "Failed to read candidate component class: " + resource, ex);
                }
            }
        }
    } catch (IOException ex) {
        throw new BeanDefinitionStoreException("I/O failure during classpath scanning", ex);
    }
    return candidates;
}

4. 刷新流程:refresh方法

refresh方法是ApplicationContext的核心流程,由AbstractApplicationContext定义,AnnotationConfigApplicationContext继承并执行。该流程负责初始化容器(解析BeanDefinition、实例化Bean、依赖注入等)。

4.1 刷新流程的核心步骤

java
// AbstractApplicationContext.java
public void refresh() throws BeansException, IllegalStateException {
    synchronized (this.startupShutdownMonitor) {
        // 1. 准备刷新:设置启动时间、激活标志、初始化属性源(如Environment)
        prepareRefresh();
        
        // 2. 获取新鲜的BeanFactory(GenericApplicationContext返回内部的DefaultListableBeanFactory)
        ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
        
        // 3. 准备BeanFactory:设置类加载器、添加BeanPostProcessor、注册默认Bean(如Environment)
        prepareBeanFactory(beanFactory);
        
        try {
            // 4. 后置处理BeanFactory:子类扩展(如WebApplicationContext添加Servlet相关处理器)
            postProcessBeanFactory(beanFactory);
            
            // 5. 调用BeanFactoryPostProcessor:解析@Configuration类、处理@Bean等(**关键步骤**)
            invokeBeanFactoryPostProcessors(beanFactory);
            
            // 6. 注册BeanPostProcessor:处理Bean的生命周期回调(如@Autowired、@PostConstruct)
            registerBeanPostProcessors(beanFactory);
            
            // 7. 初始化消息源:用于国际化(如ResourceBundleMessageSource)
            initMessageSource();
            
            // 8. 初始化事件多播器:用于发布事件(如SimpleApplicationEventMulticaster)
            initApplicationEventMulticaster();
            
            // 9. 子类扩展:如WebApplicationContext初始化ServletContext
            onRefresh();
            
            // 10. 注册事件监听器:从BeanFactory中获取所有ApplicationListener并注册
            registerListeners();
            
            // 11. 完成BeanFactory初始化:实例化所有非懒加载的单例Bean(**核心步骤**)
            finishBeanFactoryInitialization(beanFactory);
            
            // 12. 完成刷新:发布ContextRefreshedEvent事件、启动定时任务等
            finishRefresh();
        } catch (BeansException ex) {
            // 异常处理:销毁已创建的Bean、关闭容器
            destroyBeans();
            cancelRefresh(ex);
            throw ex;
        } finally {
            // 重置缓存(如BeanDefinition的元数据缓存)
            resetCommonCaches();
        }
    }
}

4.2 关键步骤解析

  • 步骤5:invokeBeanFactoryPostProcessors
    调用BeanFactoryPostProcessor(Bean工厂后置处理器),其中**ConfigurationClassPostProcessor是核心**。它负责解析@Configuration类中的注解(@Bean@ComponentScan@Import@PropertySource),生成对应的BeanDefinition。
    例如,@ComponentScan注解会触发再次扫描(类似scan方法),@Bean方法会生成BeanDefinition(关联到该方法),@Import注解会导入其他配置类或Bean。

  • 步骤6:registerBeanPostProcessors
    注册BeanPostProcessor(Bean后置处理器),其中**AutowiredAnnotationBeanPostProcessor负责处理@Autowired注解(依赖注入),CommonAnnotationBeanPostProcessor**负责处理@Resource@PostConstruct@PreDestroy注解。

  • 步骤11:finishBeanFactoryInitialization
    实例化所有非懒加载的单例Beanscope="singleton"lazy-init="false")。流程如下:

    1. 遍历BeanDefinition:筛选出单例且非懒加载的Bean。
    2. 实例化Bean:调用构造方法(处理@Autowired构造注入)。
    3. 依赖注入:调用setter方法(处理@Autowired属性注入)。
    4. 初始化:调用@PostConstruct方法、InitializingBeanafterPropertiesSet方法、自定义init-method
    5. 注册Bean:将实例存入DefaultListableBeanFactory的单例缓存(singletonObjects)。

五、关键机制:配置类的增强(CGLIB代理)

@Configuration类会被ConfigurationClassPostProcessor增强(通过CGLIB生成代理类),保证@Bean方法的单例性。例如:

java
@Configuration
public class AppConfig {
    @Bean
    public UserService userService() {
        return new UserService(userRepository()); // 调用userRepository()方法
    }

    @Bean
    public UserRepository userRepository() {
        return new UserRepositoryImpl();
    }
}

增强原理

  • 代理类会重写@Bean方法,当调用userRepository()时,会先检查DefaultListableBeanFactory的单例缓存(singletonObjects):
    • 如果存在userRepository的实例,直接返回;
    • 如果不存在,调用原方法创建实例,并存入缓存。
  • 这样,即使多次调用userRepository(),也只会创建一个实例(单例)。

六、AnnotationConfigApplicationContext的使用示例

java
// 1. 配置类(@Configuration+@ComponentScan+@Bean)
@Configuration
@ComponentScan("com.example") // 扫描com.example包下的组件
public class AppConfig {
    @Bean // 定义Bean(默认单例)
    public UserRepository userRepository() {
        return new UserRepositoryImpl();
    }
}

// 2. 组件类(@Service+@Autowired)
@Service // 标注为服务组件(会被@ComponentScan扫描到)
public class UserService {
    private final UserRepository userRepository;

    @Autowired // 构造注入(由AutowiredAnnotationBeanPostProcessor处理)
    public UserService(UserRepository userRepository) {
        this.userRepository = userRepository;
    }

    public void doSomething() {
        userRepository.save();
    }
}

// 3. 启动类(创建AnnotationConfigApplicationContext)
public class Application {
    public static void main(String[] args) {
        // 创建上下文:传入配置类(自动注册并刷新)
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
        
        // 获取Bean(从单例缓存中获取)
        UserService userService = context.getBean(UserService.class);
        
        // 使用Bean
        userService.doSomething();
        
        // 关闭上下文(销毁Bean)
        context.close();
    }
}

七、优缺点总结

优点

  • 配置简洁:通过注解替代XML,减少冗余配置。
  • 自动扫描@ComponentScan自动发现组件,减少手动注册。
  • 集中管理@Configuration类集中定义Bean,逻辑清晰。
  • 集成性好:支持Spring核心功能(依赖注入、AOP、事件机制等)。

缺点

  • 分散性:注解配置分散在各个类中,不如XML集中管理(取决于场景)。
  • 动态性差:对于需要动态切换的配置(如多环境),需结合@Profile注解,不如XML的<profile>标签直观。
  • 学习成本:需掌握多个注解(@Configuration@Component@Bean@Autowired等)的组合使用。

八、扩展:与其他上下文的区别

上下文类型配置方式适用场景
AnnotationConfigApplicationContext注解(@Configuration、@Component)非Web应用(如桌面应用、单元测试)
AnnotationConfigWebApplicationContext注解+Web配置Web应用(如Spring MVC)
ClassPathXmlApplicationContextXML配置传统XML配置的应用
FileSystemXmlApplicationContextXML配置(文件系统路径)需指定XML文件绝对路径的应用

总结

AnnotationConfigApplicationContext是Spring基于注解的核心上下文实现,通过AnnotatedBeanDefinitionReader(注册配置类)、ClassPathBeanDefinitionScanner(扫描组件)、ConfigurationClassPostProcessor(解析配置类)等组件,实现了注解驱动的Bean管理。其核心流程是:注册/扫描→解析BeanDefinition→刷新上下文→实例化Bean→依赖注入

理解AnnotationConfigApplicationContext的源码与机制,有助于深入掌握Spring的注解配置模型,为使用Spring Boot(默认使用该上下文)打下坚实基础。