Appearance
AnnotationConfigApplicationContext源码解析
一、AnnotationConfigApplicationContext的定位与核心功能
AnnotationConfigApplicationContext
是Spring框架中基于注解的应用上下文实现,属于ApplicationContext
体系的子类,主要用于替代传统XML配置,通过注解(如@Configuration
、@Component
、@Bean
)管理Bean的定义与生命周期。
核心功能
- 注册配置类:通过
register(Class<?>... componentClasses)
方法注册标注了@Configuration
的类(或直接标注@Component
的类)。 - 扫描组件:通过
scan(String... basePackages)
方法扫描指定包下的@Component
及其派生注解(@Service
、@Repository
、@Controller
)标注的类。 - 刷新上下文:通过
refresh()
方法触发Spring容器的初始化流程(BeanDefinition解析、实例化、依赖注入等)。 - 管理Bean:提供
getBean()
、getBeanDefinition()
等方法获取Bean或其定义。
二、AnnotationConfigApplicationContext的继承体系
AnnotationConfigApplicationContext
的继承关系如下:
ApplicationContext (接口)
└── ConfigurableApplicationContext (接口)
└── AbstractApplicationContext (抽象类)
└── GenericApplicationContext (抽象类)
└── AnnotationConfigApplicationContext (实现类)
同时,它还实现了AnnotationConfigRegistry
接口(定义了register
和scan
方法)。
关键父类/接口的作用
- 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
的构造方法主要初始化AnnotatedBeanDefinitionReader
和ClassPathBeanDefinitionScanner
,并关联当前上下文(作为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逻辑
AnnotatedBeanDefinitionReader
的register
方法遍历每个类,生成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逻辑
ClassPathBeanDefinitionScanner
的scan
方法遍历指定包,通过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
实例化所有非懒加载的单例Bean(scope="singleton"
且lazy-init="false"
)。流程如下:- 遍历
BeanDefinition
:筛选出单例且非懒加载的Bean。 - 实例化Bean:调用构造方法(处理
@Autowired
构造注入)。 - 依赖注入:调用
setter
方法(处理@Autowired
属性注入)。 - 初始化:调用
@PostConstruct
方法、InitializingBean
的afterPropertiesSet
方法、自定义init-method
。 - 注册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) |
ClassPathXmlApplicationContext | XML配置 | 传统XML配置的应用 |
FileSystemXmlApplicationContext | XML配置(文件系统路径) | 需指定XML文件绝对路径的应用 |
总结
AnnotationConfigApplicationContext
是Spring基于注解的核心上下文实现,通过AnnotatedBeanDefinitionReader
(注册配置类)、ClassPathBeanDefinitionScanner
(扫描组件)、ConfigurationClassPostProcessor
(解析配置类)等组件,实现了注解驱动的Bean管理。其核心流程是:注册/扫描→解析BeanDefinition→刷新上下文→实例化Bean→依赖注入。
理解AnnotationConfigApplicationContext
的源码与机制,有助于深入掌握Spring的注解配置模型,为使用Spring Boot(默认使用该上下文)打下坚实基础。