概述
目录
1. 注册内部处理器类
2. 注册普通BeanDefinition
3. 应用环境刷新
使用示例:
AnnotationConfigApplicationContext annotationConfigApplicationContext11 = new AnnotationConfigApplicationContext("com.ioc.lic");
UserService userService = (UserService) annotationConfigApplicationContext11.getBean("userService");
userService.query();
分析:
- 构建AnnotationConfigApplicationContext实例
- 调用getBean方法获取Bean
- 执行目标bean的方法
AnnotationConfigApplicationContext#AnnotationConfigApplicationContext实现:
/**
* 创建一个AnnotationConfigApplicationContext对象, 根据提供的包信息刷新上下文
*/
public AnnotationConfigApplicationContext(String... basePackages) {
/**
* 1. 初始化上下文环境
* 2. 初始化注解bean定义解析器和类路径bean定义扫描器
*/
this();
//根据提供的包路径信息去扫描注册bean信息
scan(basePackages);
//
refresh();
}
分析:
- 初始化上下文环境, 初始化注解bean定义解析器和类路径bean定义扫描器
- 根据提供的包路径信息去扫描注册bean信息
- 刷新应用上下文信息
由Spring源码解析一 (IOC容器初始化深度解析)中的流程图可以看到该方式初始化IOC容器是分为两个流程执行的, 先注册了相关处理器类, 然后再通过配置的包路径信息注册BeanDefinition信息, 所以我们分为两大步骤解析:
1. 注册内部处理器类
_1. AnnotationConfigApplicationContext#AnnotationConfigApplicationContext实现:
/**
* 初始化一个bean的读取和扫描器
* 何谓读取器和扫描器参考上面的属性注释
* 默认构造函数,如果直接调用这个默认构造方法,需要在稍后通过调用其register()
* 去注册配置类(javaconfig),并调用refresh()方法刷新容器,
* 触发容器对注解Bean的载入、解析和注册过程
* 这种使用过程我在ioc应用的第二节课讲@profile的时候讲过
*
* 注意在初始化AnnotatedBeanDefinitionReader和ClassPathBeanDefinitionScanner时需要传递的是bean定义注册器用来存储解析好的bean定义信息
* AnnotationConfigApplicationContext实现了GenericApplicationContext,而GenericApplicationContext实现了BeanDefinitionRegistry接口
*/
public AnnotationConfigApplicationContext() {
/**
* 实例化注解bean的解析器, 并会对beanFactory进行一些初始化配置
*/
this.reader = new AnnotatedBeanDefinitionReader(this);
/**
* ClassPathBeanDefinitionScanner: 可以用来扫描包或者类,继而转换成bd
* 1.当初始化AnnotationConfigApplicationContext时传入的是配置类的Class信息时
* 在后面根据注解信息获取到包信息并扫描时使用的并不是这个scanner对象, 而是spring内部实例化的一个ClassPathBeanDefinitionScanner
* {@link ComponentScanAnnotationParser#parse(org.springframework.core.annotation.AnnotationAttributes, java.lang.String)}
* 2.当初始化AnnotationConfigApplicationContext时传入的是配置类的包路径信息时
* 在{@link this#scan(String...)}方法中对包路径进行扫描时使用的是该scanner对象
*
* 总之: 两种方式对包的扫描工作都是在{@link ClassPathBeanDefinitionScanner#doScan(String...)}中进行的
*/
this.scanner = new ClassPathBeanDefinitionScanner(this);
}
分析:
- 实例化注解bean的解析器, 并会对beanFactory进行一些初始化配置, 其中就包括处理器类的注册
- 实例化类路径扫描器,可以用来扫描包信息,对该包路径下的Bean进行解析
注意:
- 当初始化AnnotationConfigApplicationContext时传入的是配置类的Class信息时在后面根据注解信息获取到包信息并扫描时使用的并不是这个scanner对象, 而是spring内部实例化的一个ClassPathBeanDefinitionScanner
- 当初始化AnnotationConfigApplicationContext时传入的包路径信息时, 在{@link this#scan(String...)}方法中对包路径进行扫描时使用的是该scanner对象
_1. AnnotatedBeanDefinitionReader#AnnotatedBeanDefinitionReader实现:
public AnnotatedBeanDefinitionReader(BeanDefinitionRegistry registry, Environment environment) {
. . .
this.registry = registry;
this.conditionEvaluator = new ConditionEvaluator(registry, environment, null);
/**
* 设置beanFactory中的DependencyComparator和AutowireCandidateResolver属性
* 注册一些beanFactory内部的注解配置处理器类
*/
AnnotationConfigUtils.registerAnnotationConfigProcessors(this.registry);
}
分析: 将注册中心维护在AnnotatedBeanDefinitionReader中以及注册一些BeanFactory内部的注解配置处理器类
AnnotationConfigUtils#registerAnnotationConfigProcessors实现:
public static Set<BeanDefinitionHolder> registerAnnotationConfigProcessors(
BeanDefinitionRegistry registry, @Nullable Object source) {
/**
* 1. 对beanFactory的属性进行设置
*/
//获取注册器中维护的DefaultListableBeanFactory工厂
DefaultListableBeanFactory beanFactory = unwrapDefaultListableBeanFactory(registry);
//如果beanFactory不为空, 则设置beanFactory的DependencyComparator和AutowireCandidateResolver属性
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());
}
}
/**
* 2. 注册Spring内部的处理器类(实现BeanDefinitionRegistryPostProcessor接口和BeanFactoryPostProcessor接口)
* Spring在内部类维护这些类, 为BeanFactory提供特定的功能
* 以下7个类是最先注册到beanFactory中的BeanDefinitionMap集合中去
* (1).org.springframework.context.annotation.internalConfigurationAnnotationProcessor -->只有这一个实现了BeanDefinitionRegistryPostProcessor接口
* (2).org.springframework.context.annotation.internalAutowiredAnnotationProcessor
* (3).org.springframework.context.annotation.internalRequiredAnnotationProcessor
* (4).org.springframework.context.annotation.internalCommonAnnotationProcessor
* (5).org.springframework.context.annotation.internalPersistenceAnnotationProcessor -->这个没有被注册
* (6).org.springframework.context.event.internalEventListenerProcessor
* (7).org.springframework.context.event.internalEventListenerFactory
*/
//暂存BeanDefinitionHolder的Set集合
Set<BeanDefinitionHolder> beanDefs = new LinkedHashSet<>(8);
//判断注册器中是否含有指定的BeanDefinition,并注册到到注册器中, 然后将beanName和BeanDefinition封装到BeanDefinitionHolder
if (!registry.containsBeanDefinition(CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME)) {
//需要注意的是ConfigurationClassPostProcessor的类型是BeanDefinitionRegistryPostProcessor
//而 BeanDefinitionRegistryPostProcessor 最终实现BeanFactoryPostProcessor这个接口
//根据spring内部提供的class实例化ConfigurationClassPostProcessor
RootBeanDefinition def = new RootBeanDefinition(ConfigurationClassPostProcessor.class);
def.setSource(source);
beanDefs.add(registerPostProcessor(registry, def, CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME));
}
if (!registry.containsBeanDefinition(AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME)) {
//AutowiredAnnotationBeanPostProcessor 实现了 MergedBeanDefinitionPostProcessor
//MergedBeanDefinitionPostProcessor 最终实现了 BeanPostProcessor
RootBeanDefinition def = new RootBeanDefinition(AutowiredAnnotationBeanPostProcessor.class);
def.setSource(source);
/**
* 注册后处理器类
*/
beanDefs.add(registerPostProcessor(registry, def, AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME));
}
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));
}
// Check for JSR-250 support, and if present add the CommonAnnotationBeanPostProcessor.
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));
}
// 检查JPA支持,如果存在,添加PersistenceAnnotationBeanPostProcessor
if (jpaPresent && !registry.containsBeanDefinition(PERSISTENCE_ANNOTATION_PROCESSOR_BEAN_NAME)) {
RootBeanDefinition def = new RootBeanDefinition();
try {
def.setBeanClass(ClassUtils.forName(PERSISTENCE_ANNOTATION_PROCESSOR_CLASS_NAME,
AnnotationConfigUtils.class.getClassLoader()));
}
catch (ClassNotFoundException ex) {
throw new IllegalStateException(
"Cannot load optional framework class: " + PERSISTENCE_ANNOTATION_PROCESSOR_CLASS_NAME, ex);
}
def.setSource(source);
beanDefs.add(registerPostProcessor(registry, def, PERSISTENCE_ANNOTATION_PROCESSOR_BEAN_NAME));
}
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));
}
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));
}
/**
* 3. 将注册Spring内部的类封装到Set集合中返回
*/
return beanDefs;
}
分析:
1. 对beanFactory的属性进行设置
2. 注册Spring内部的处理器类(实现BeanDefinitionRegistryPostProcessor接口和BeanFactoryPostProcessor接口), Spring在内部类维护这些类, 为BeanFactory提供特定的功能
以下7个类是最先注册到beanFactory中的BeanDefinitionMap集合中去
(1). org.springframework.context.annotation.internalConfigurationAnnotationProcessor (重点)
(2). org.springframework.context.annotation.internalAutowiredAnnotationProcessor
(3). org.springframework.context.annotation.internalRequiredAnnotationProcessor
(4). org.springframework.context.annotation.internalCommonAnnotationProcessor
(5). org.springframework.context.annotation.internalPersistenceAnnotationProcessor
(6). org.springframework.context.event.internalEventListenerProcessor
(7). org.springframework.context.event.internalEventListenerFactory
3. 将注册Spring内部的类封装到Set集合中返回
_2. AnnotationConfigUtils#registerPostProcessor实现:
private static BeanDefinitionHolder registerPostProcessor(BeanDefinitionRegistry registry, RootBeanDefinition definition, String beanName) {
definition.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
registry.registerBeanDefinition(beanName, definition);
return new BeanDefinitionHolder(definition, beanName);
}
GenericApplicationContext#registerBeanDefinition ==> DefaultListableBeanFactory#registerBeanDefinition实现:
@Override
public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition) throws BeanDefinitionStoreException {
. . .
if (beanDefinition instanceof AbstractBeanDefinition) {
try {
/**
* 注册前的最后一次校验,这里的校验不同于之前的XML文件校验
* 主要是对于AbstracBeanDefinition属性中的methodOverrides校验,
* 校验methodOverrides是否与工厂方法并存或者methodOverrides对应的方法不存在
*/
((AbstractBeanDefinition) beanDefinition).validate();
}
. . .
}
//判断该beanName是否已经注册 ,根据不同的设置记性处理; (不愧是Spring, 在我模拟的SpringIOC中我管它那么多, 直接覆盖 ,简单粗暴)
BeanDefinition existingDefinition = this.beanDefinitionMap.get(beanName);
if (existingDefinition != null) {
//如果对应的BeanName已经注册且在配置中配置了bean不允许被覆盖,则抛出异常
. . .
//注册beanDefinition(将beanDefinition放入map缓存中)
this.beanDefinitionMap.put(beanName, beanDefinition);
}
//处理注册未被注册的beanName的情况
else {
/**
* 检查这个工厂的bean创建阶段是否已经开始,即 是否有任何bean被标记为同时创建。
* 如果bean工厂的bean创建已经开始, 那么就不能在beanDefinitionNames集合中添加beanName; 因为创建bean时, 会迭代beanDefinitionNames集合,获取beanName,获取BeanDefinition创建bean实例
* 一旦开始迭代, 则不允许在向该map集合中插入元素
*/
if (hasBeanCreationStarted()) {
//处于bean创建阶段
//因为beanDefinitionMap是全局变量,这里肯定会存在并发访问的情况
synchronized (this.beanDefinitionMap) {
//注册beanDefinitionv
this.beanDefinitionMap.put(beanName, beanDefinition);
//创建新的集合来更新存储已注册beanName的beanDefinitionNames集合
List<String> updatedDefinitions = new ArrayList<>(this.beanDefinitionNames.size() + 1);
updatedDefinitions.addAll(this.beanDefinitionNames);
updatedDefinitions.add(beanName);
this.beanDefinitionNames = updatedDefinitions;
//更新manualSingletonNames(存储单例bean)集合
if (this.manualSingletonNames.contains(beanName)) {
Set<String> updatedSingletons = new LinkedHashSet<>(this.manualSingletonNames);
updatedSingletons.remove(beanName);
this.manualSingletonNames = updatedSingletons;
}
}
}
//仍处于注册阶段
else {
//将beanName和bean的定义信息加入beanDefinitionMap集合
this.beanDefinitionMap.put(beanName, beanDefinition);
//bean定义名称列表,按注册顺序排列
this.beanDefinitionNames.add(beanName);
//手动注册的单例程序的名称列表,按注册顺序排列
this.manualSingletonNames.remove(beanName);
}
this.frozenBeanDefinitionNames = null;
}
//如果该bean定义已经注册,并且为单例,则进行重置
if (existingDefinition != null || containsSingleton(beanName)) {
resetBeanDefinition(beanName);
}
}
分析:
- 注册前的最后一次校验,这里的校验不同于之前的XML文件校验, 主要是对于AbstracBeanDefinition属性中的methodOverrides校验, 校验methodOverrides是否与工厂方法并存或者methodOverrides对应的方法不存在
- 判断该beanName是否已经注册; 如果beanName已经注册过: 根据不同的设置进行处理(是否允许覆盖, 如果不允许,则抛出异常; 允许的话, 则进行注册)
- 如果beanName没有被注册过; 则开始检查这个工厂的bean创建阶段是否已经开始,即是否有任何bean被标记为同时创建。如果bean工厂的bean创建已经开始, 那么就不能在beanDefinitionNames集合中添加beanName; 因为创建bean时, 会迭代beanDefinitionNames集合, 获取beanName, 获取BeanDefinition创建bean实例; 一旦开始迭代, 则不允许在向该list集合中插入元素, 但是beanDefinitionMap集合可以, 因为beanDefinitionMap集合并没有被迭代, 而是通过beanName获取BeanDefinition信息;
- 如果该bean定义已经注册, 并且为单例, 则进行重置
2. 注册普通BeanDefinition
_2. AnnotationConfigApplicationContext#scan实现:
public void scan(String... basePackages) {
...
this.scanner.scan(basePackages);
}
分析: 通过之前实例化的扫描器调用scan()方法扫描包信息
ClassPathBeanDefinitionScanner#scan实现:
public int scan(String... basePackages) {
int beanCountAtScanStart = this.registry.getBeanDefinitionCount();
doScan(basePackages);
// Register annotation config processors, if necessary.
if (this.includeAnnotationConfig) {
AnnotationConfigUtils.registerAnnotationConfigProcessors(this.registry);
}
return (this.registry.getBeanDefinitionCount() - beanCountAtScanStart);
}
ClassPathBeanDefinitionScanner#doScan实现:
protected Set<BeanDefinitionHolder> doScan(String... basePackages) {
Assert.notEmpty(basePackages, "At least one base package must be specified");
//存储扫描到的BeanDefinition信息
Set<BeanDefinitionHolder> beanDefinitions = new LinkedHashSet<>();
//循环遍历包路径信息,进行解析,注册
for (String basePackage : basePackages) {
//扫描出该包路径下左右的候选Bean
Set<BeanDefinition> candidates = findCandidateComponents(basePackage);
//对所有的候选bean进行解析
for (BeanDefinition candidate : candidates) {
//获取Scope属性
ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(candidate);
candidate.setScope(scopeMetadata.getScopeName());
//根据Bean信息生成BeanName
String beanName = this.beanNameGenerator.generateBeanName(candidate, this.registry);
//对于配置类型BeanDefinition类型和注解类型BeanDefinition类型进行区分设置
if (candidate instanceof AbstractBeanDefinition) {
/**
* 如果这个类是AbstractBeanDefinition的子类
* 则为他设置默认值,比如lazy,init destory
*/
postProcessBeanDefinition((AbstractBeanDefinition) candidate, beanName);
}
if (candidate instanceof AnnotatedBeanDefinition) {
/**
* 检查并且处理常用的注解
* 这里的处理主要是指把常用注解的值设置到AnnotatedBeanDefinition当中
* 当前前提是这个类必须是AnnotatedBeanDefinition类型的,说白了就是加了注解的类
*/
AnnotationConfigUtils.processCommonDefinitionAnnotations((AnnotatedBeanDefinition) candidate);
}
//判断注册器中是否已经存在该BeanName
if (checkCandidate(beanName, candidate)) {
BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(candidate, beanName);
definitionHolder = AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);
beanDefinitions.add(definitionHolder);
/**
* 注册BeanDefinition
*/
registerBeanDefinition(definitionHolder, this.registry);
}
}
}
return beanDefinitions;
}
分析: 循环遍历包路径信息,进行解析,注册
ClassPathBeanDefinitionScanner#registerBeanDefinition
==> BeanDefinitionReaderUtils#registerBeanDefinition实现
public static void registerBeanDefinition(BeanDefinitionHolder definitionHolder, BeanDefinitionRegistry registry) throws BeanDefinitionStoreException {
// 根据主名称注册bean定义信息
String beanName = definitionHolder.getBeanName();
/**
* GenericApplicationContext类实现了BeanDefinitionRegistry接口,
* 并且在 GenericApplicationContext类中维护了一个DefaultListableBeanFactory beanFactory (卧槽, 终于见到bean工厂了)
*
* 该步骤实际调用的是GenericApplicationContext类中的registerBeanDefinition()方法
*{@link org.springframework.context.support.GenericApplicationContext#registerBeanDefinition(String,BeanDefinition)}
*/
registry.registerBeanDefinition(beanName, definitionHolder.getBeanDefinition());
// 如果该bean有别名的话, 为bean名称注册别名
String[] aliases = definitionHolder.getAliases();
if (aliases != null) {
for (String alias : aliases) {
registry.registerAlias(beanName, alias);
}
}
}
GenericApplicationContext#registerBeanDefinition ==> DefaultListableBeanFactory#registerBeanDefinition
注: 前面已经解析过DefaultListableBeanFactory#registerBeanDefinition相关逻辑, 这里不再进行解析了
3. 应用环境刷新
AbstractApplicationContext#refresh实现:
@Override
public void refresh() throws BeansException, IllegalStateException {
synchronized (this.startupShutdownMonitor) {
// 准备好刷新上下文(设置一些变量)
prepareRefresh();
/**
* obtainFreshBeanFactory()方法中根据实现类的不同调用不同的refreshBeanFactory()方法
* <----- 注解模式 ----->
* 1. 如果是使用AnnotationConfigApplicationContext来初始化环境
* 调用的是GenericApplicationContext#refreshBeanFactory()方法
* {@link GenericApplicationContext#refreshBeanFactory()}
* 在该方法中只是对beanFactory的一些变量进行设置
* <----- XML配置模式 ----->
* 2. 如果是使用ClassPathXmlApplicationContext来初始化环境
* 调用的是{@link AbstractRefreshableApplicationContext#refreshBeanFactory()}
* 由于还没有对beanFactory进行初始化,所以在该方法中,完成了对beanFactory的初始化操作
* 并对设置的资源位置进行扫描, 解析
* 注意:此方法是使用ClassPathXmlApplicationContext来初始化上下文是解析注册bean的重要入口 <-------------------重要
*/
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
//对beanFactory进行属性设置
prepareBeanFactory(beanFactory);
try {
//允许在子类中对bean工厂进行后处理。
postProcessBeanFactory(beanFactory);
/**
* <----- 注解模式 ----->
* 1. 如果是使用AnnotationConfigApplicationContext来初始化环境(该方法是解析注册bean的重要入口) <--------------------重要
* 在该方法中执行了
* {@link org.springframework.context.annotation.ConfigurationClassPostProcessor#processConfigBeanDefinitions} 方法
* 对配置类进行解析(如果该注解bean是配置类则在这个方法里完成了包扫描操作) <--------------- 重要
* 注意:
* 1. 一般情况下, 此时beanFactory中只注册了这一个BeanFactoryPostProcessor类-->ConfigurationClassPostProcessor
* 在{@link AnnotationConfigUtils#registerAnnotationConfigProcessors(org.springframework.beans.factory.support.BeanDefinitionRegistry)}中注册的
* 2. 注解模式下,此时BeanDefinitionMap中含有6个Spring内部处理器类, 其中通过ConfigurationClassPostProcessor类来解析配置类,完成包扫描,bean注册等操作
* 然而, 在xml配置模式下, 此时BeanDefinitionMap只有自定义配置的BeanDefinition信息
*
* <----- XML配置模式 ----->
* 2. 如果是使用ClassPathXmlApplicationContext来初始化环境
* 默认情况下, 此时BeanDefinitionMap只有自定义配置的BeanDefinition信息, 并没有任何Spring内部所定义的BeanFactory后处理器
* 除非用户自定义了BeanFactory后处理器, 需要对BeanFactory进行修改, 那么才会执行对应后处理器里面的方法;
*
*/
invokeBeanFactoryPostProcessors(beanFactory);
/**
* 注册bean后处理处理器
*/
registerBeanPostProcessors(beanFactory);
//为上下文初始化Message源,即不同的语言体,国际化处理
initMessageSource();
// 初始化应用消息广播,并放入"appliactionEventMulitcaster"bean中
initApplicationEventMulticaster();
// 留给子类来初始化其他的Bean
onRefresh();
//在所有注册的bean中查找listener bean,注册到消息广播器中
registerListeners();
// 初始化剩下的单例(非延迟加载的,延迟加载的单例在第一次调用的时候初始化)
finishBeanFactoryInitialization(beanFactory);
/**
* 最后一步:完成刷新过程,通知生命周期处理器lifecycleProcessor刷新过程,同时发出ContextRefreshEvent通知别人
*/
finishRefresh();
}
catch (BeansException ex) {
if (logger.isWarnEnabled()) {
logger.warn("Exception encountered during context initialization - " +
"cancelling refresh attempt: " + ex);
}
// 销毁已创建的单例以避免资源悬空。
destroyBeans();
// Reset 'active' flag.
cancelRefresh(ex);
// Propagate exception to caller.
throw ex;
}
finally {
resetCommonCaches();
}
}
}
分析: 使用 AnnotationConfigApplicationContext[包路径配置方式]初始化, 到这里只是已经对包路径下的Bean进行注册, 如果已注册的Bean中包括配置类呢? 那么在激活Bean工厂后处理器时会对配置类进行解析, 相关解析内容将在播客: Spring源码解析五 (IOC容器初始化方式三: AnnotationConfigApplicationContext[Java配置方式])中详细讲解, 这里不再进行赘述了
至此, 使用AnnotationConfigApplicationContext初始化IOC容器解析完成;
相关文章:
Spring源码解析一 (IOC容器初始化深度解析)
Spring源码解析二 (IOC容器初始化方式一:XmlBeanFactory)
Spring源码解析三 (IOC容器初始化方式二:ClassPathXmlApplicationContext)
Spring源码解析四 (IOC容器初始化方式三: AnnotationConfigApplicationContext[包路径配置方式])
Spring源码解析五 (IOC容器初始化方式四: AnnotationConfigApplicationContext[Java配置类方式])
Spring源码解析六 (Bean的初始化)
Spring源码解析七 (AOP深度解析)
最后
以上就是苹果哑铃为你收集整理的Spring源码解析四 (IOC容器初始化方式三: AnnotationConfigApplicationContext[包路径配置方式])的全部内容,希望文章能够帮你解决Spring源码解析四 (IOC容器初始化方式三: AnnotationConfigApplicationContext[包路径配置方式])所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复