1、 AnnotationConfigApplicationContext功能

该类可以实现基于Java的配置类加载自定义在Spring的应用上下文的bean。

1.1 使用方式一:在构造方法中完成注册和刷新

AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(MessageConfiguration.class);
System.out.println(ctx.getBean("beanName"));)//根据bean的名字获得与之对应的实例。 public AnnotationConfigApplicationContext(Class... annotatedClasses) {
this();
this.register(annotatedClasses);
this.refresh();
}

1.2 使用方式二:扫描包路径下所有的配置类,最后刷新

AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();
ctx.scan("org.spring.springboot");
ctx.refresh();
可以直接以包名作为参数传入。
public AnnotationConfigApplicationContext(String... basePackages) {
this();
this.scan(basePackages);
this.refresh();
}

使用方式三:通过使用register方法具体到注册哪个配置类,最后刷新。

AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();
ctx.register(AppConfig.class);
ctx.refresh();

2、 分析AnnotationConfigApplicationContext

AnnotationConfigApplicationContext继承了GenericApplicationContext并实现了接口AnnotationConfigRegistry 

2.1 接口:AnnotationConfigRegistry注册方法和扫描方法。注解配置注册表。用于注解配置应用上下文的通用接口,
拥有一个注册配置类和扫描配置类的方法。

2.2 GenericApplicationContext通用应用上下文。
GenericApplicationContext 继承 AbstractApplicationContext 实现 BeanDefinitionRegistry,内部持有一个
DefaultListableBeanFactory实例,这个类实现了BeanDefinitionRegistry接口,可以在它身上使用任意的bean definition读取器。

2.2.1 AbstractApplicationContext
ApplicationContext接口的抽象实现,没有强制规定配置的存储类型,仅仅实现了通用的上下文功能。
这个实现用到了模板方法设计模式,需要具体的子类来实现其抽象方法。自动通过registerBeanPostProcessors()
方法注册BeanFactoryPostProcessor, BeanPostProcessor和ApplicationListener的实例用来探测bean factory里的特殊bean。

2.2.2 BeanDefinitionRegistry
用于持有像RootBeanDefinition和 ChildBeanDefinition实例的bean definitions的注册表接口。GenericApplicationContext
类中的实例DefaultListableBeanFactory实现了这个接口,它对这个接口的实现实际上是通过调用这个实例的相应方法实现的,
因此可以通过相应的方法向beanFactory里面注册bean。

源码:

public interface BeanDefinitionRegistry extends AliasRegistry {
void registerBeanDefinition(String var1, BeanDefinition var2) throws BeanDefinitionStoreException; void removeBeanDefinition(String var1) throws NoSuchBeanDefinitionException; BeanDefinition getBeanDefinition(String var1) throws NoSuchBeanDefinitionException; boolean containsBeanDefinition(String var1); String[] getBeanDefinitionNames(); int getBeanDefinitionCount(); boolean isBeanNameInUse(String var1);
}

2.3 构造方法
AnnotatedBeanDefinitionReader——BeanDefinition解析器用来解析带注解的bean

2.3.1 AnnotatedBeanDefinitionReader的构造器
注解的条件判断器ConditionEvaluator
该方法在初始化的时调用,当配置的类上有@Conditional注解并且返回false的时候,容器就不处理该类
AnnotationConfigUtils.registerAnnotationConfigProcessors(this.registry)
这个是关键,注册AnnotationConfigProcessor

// 默认使用三个bean处理器
public static void registerAnnotationConfigProcessors(BeanDefinitionRegistry registry) {
registerAnnotationConfigProcessors(registry, (Object)null);
}
Set<BeanDefinitionHolder> beanDefs = new LinkedHashSet(8);
RootBeanDefinition def;
if (!registry.containsBeanDefinition("org.springframework.context.annotation.internalConfigurationAnnotationProcessor")) {
def = new RootBeanDefinition(ConfigurationClassPostProcessor.class);
def.setSource(source);
beanDefs.add(registerPostProcessor(registry, def, "org.springframework.context.annotation.internalConfigurationAnnotationProcessor"));
} if (!registry.containsBeanDefinition("org.springframework.context.annotation.internalAutowiredAnnotationProcessor")) {
def = new RootBeanDefinition(AutowiredAnnotationBeanPostProcessor.class);
def.setSource(source);
beanDefs.add(registerPostProcessor(registry, def, "org.springframework.context.annotation.internalAutowiredAnnotationProcessor"));
} if (jsr250Present && !registry.containsBeanDefinition("org.springframework.context.annotation.internalCommonAnnotationProcessor")) {
def = new RootBeanDefinition(CommonAnnotationBeanPostProcessor.class);
def.setSource(source);
beanDefs.add(registerPostProcessor(registry, def, "org.springframework.context.annotation.internalCommonAnnotationProcessor"));
}

2.3.1.1 @Bean的分析
是在refresh的invokeBeanFactoryPostProcessors(beanFactory)阶段,核心方法是loadBeanDefinitionsForBeanMethod,该方法处理了各种各样的注解。
注解分析的关键方法loadBeanDefinitionsForBeanMethod
该方法具体实现对包括如下注解的处理。
autowire
initMethod
destroyMethod

是在refresh的invokeBeanFactoryPostProcessors(beanFactory)阶段,核心方法是loadBeanDefinitionsForBeanMethod,
该方法处理了各种各样的注解。
2.3.1.2 ConditionEvaluator:配置的类上有@Conditional注解并且返回false的时候,容器就不处理该类

2.3.1.3 @Autowired 重点关注AutowiredAnnotationBeanPostProcessor后置处理器。

2.3.1.4 当AutowiredAnnotationBeanPostProcessor 作为接口MergedBeanDefinitionPostProcessor的实现时
AutowiredAnnotationBeanPostProcessor后置处理器的方法调用栈postProcessMergedBeanDefinition
该方法是在AbstractAutowireCapableBeanFactory.java的doCreateBean中调用的。该方法是创建bean实例的核心方法:

  • 1)创建Bean的实例:createBeanInstance(beanName, mbd, args)
  • 在此后:applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName)
  • 调用AutowiredAnnotationBeanPostProcessor的方法postProcessMergedBeanDefinition
  • 2)populateBean;给bean的各种属性赋值
  • 3)initializeBean:初始化bean;

2.3.2 ClassPathBeanDefinitionScanner——bean的扫描器 用来扫描类

注册解析传入的配置类(使用类配置的方式进行解析)
调用容器的refresh方法初始化容器

使用AnnotationConfigApplicationContext注册配置类的更多相关文章

  1. Spring5源码解析2-register方法注册配置类

    接上回已经讲完了this()方法,现在来看register(annotatedClasses);方法. // new AnnotationConfigApplicationContext(AppCon ...

  2. 【Spring】简述@Configuration配置类注册BeanDefinition到Spring容器的过程

    概述 本文以SpringBoot应用为基础,尝试分析基于注解@Configuration的配置类是如何向Spring容器注册BeanDefinition的过程 其中主要分析了 Configuratio ...

  3. 你知道Spring是怎么解析配置类的吗?

    彻底读懂Spring(二)你知道Spring是怎么解析配置类的吗? 推荐阅读: Spring官网阅读系列 彻底读懂Spring(一)读源码,我们可以从第一行读起 Spring执行流程图如下: 如果图片 ...

  4. 使用spring配置类代替xml配置文件注册bean类

    spring配置类,即在类上加@Configuration注解,使用这种配置类来注册bean,效果与xml文件是完全一样的,只是创建springIOC容器的方式不同: //通过xml文件创建sprin ...

  5. spring 配置 Java配置类装配bean

    https://www.cnblogs.com/chenbenbuyi/p/8457700.html 自动化装配的确有很大的便利性,但是却并不能适用在所有的应用场景,比如需要装配的组件类不是由自己的应 ...

  6. Spring源码解析 – @Configuration配置类及注解Bean的解析

    在分析Spring 容器创建过程时,我们知道容器默认会加载一些后置处理器PostPRocessor,以AnnotationConfigApplicationContext为例,在构造函数中初始化rea ...

  7. spring5 源码深度解析----- 被面试官给虐懵了,竟然是因为我不懂@Configuration配置类及@Bean的原理

    @Configuration注解提供了全新的bean创建方式.最初spring通过xml配置文件初始化bean并完成依赖注入工作.从spring3.0开始,在spring framework模块中提供 ...

  8. Spring5源码解析6-ConfigurationClassParser 解析配置类

    ConfigurationClassParser 在ConfigurationClassPostProcessor#processConfigBeanDefinitions方法中创建了Configur ...

  9. SSM框架新特性关于用Java配置类完全代替XML

    项目目录结构 从Spring3.0,@Configuration用于定义配置类,可替换xml配置文件,被注解的类内部包含有一个或多个被@Bean注解的方法, 这些方法将会被AnnotationConf ...

随机推荐

  1. Jmeter接口测试系列之测试用例编写和调用

    在使用Jmeter进行接口测试时,首先需要根据接口定义,编写响应的接口测试用例,在编写接口测试用例时,我们根据测试的侧重点不同,使用不同的方式编译测试用例. 一种是:整个请求参数作为一个变量,进行测试 ...

  2. 【Spring】---【AOP】

    转发几篇文章 专治不会看源码的毛病--spring源码解析AOP篇 Spring3:AOP 理解AOP 什么是AOP? 转自: http://www.cnblogs.com/xiexj/p/73668 ...

  3. Linux常用命令梳理——文件管理(一)

    由于本人目前仍是萌新一枚,所以<Linux常用命令梳理>系列仅依照个人目前掌握的知识,对一部分命令进行梳理,目的是为了对之前学到的知识进行巩固.当然了,如果机缘巧合被大家看到了,也欢迎各位 ...

  4. [Usaco2017 Jan]Promotion Counting

    n只奶牛构成了一个树形的公司,每个奶牛有一个能力值pi,1号奶牛为树根.问对于每个奶牛来说,它的子树中有几个能力值比它大的.Inputn,表示有几只奶牛 n<=100000接下来n行为1-n号奶 ...

  5. python面试题--初级(二)

    基础不牢,地动山摇,面试的时候经常会被问到一些平时基础的很容易被忽视的知识点,所以重在积累,多看多背深入理解,才能在某一天工作中豁然开朗恍然大悟. 面试题不仅仅为了应付面试,更是知识点的一个梳理总结归 ...

  6. 【监控笔记】【2.4】SQL Server中的 Ring Buffer 诊断各种系统资源压力情况

    SQL Server 操作系统(SQLOS)负责管理特定于SQL Server的操作系统资源. 其中相关的动态管理试图sys.dm_os_ring_buffers将被标识为仅供参考.不提供支持.不保证 ...

  7. 替换url不刷新页面

    今天碰到一个有趣的问题, 从其他站点登录后,放回了一个token, 但是我切换了路由之后token还在, 路由直接跟在了token参数后面, 后面先利用location.href替换掉原来的连接, 但 ...

  8. HNUSTOJ-1520 压缩编码

    1520: 压缩编码 时间限制: 1 Sec  内存限制: 2 MB提交: 107  解决: 54[提交][状态][讨论版] 题目描述 某工业监控设备不断发回采样数据.每个数据是一个整数(0到1000 ...

  9. A广搜

    <span style="color:#330099;">/* A - 广搜 基础 Time Limit:2000MS Memory Limit:65536KB 64b ...

  10. RabbitMQ交换器Exchange介绍与实践

    RabbitMQ交换器Exchange介绍与实践 RabbitMQ系列文章 RabbitMQ在Ubuntu上的环境搭建 深入了解RabbitMQ工作原理及简单使用 RabbitMQ交换器Exchang ...