使用AnnotationConfigApplicationContext注册配置类
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注册配置类的更多相关文章
- Spring5源码解析2-register方法注册配置类
接上回已经讲完了this()方法,现在来看register(annotatedClasses);方法. // new AnnotationConfigApplicationContext(AppCon ...
- 【Spring】简述@Configuration配置类注册BeanDefinition到Spring容器的过程
概述 本文以SpringBoot应用为基础,尝试分析基于注解@Configuration的配置类是如何向Spring容器注册BeanDefinition的过程 其中主要分析了 Configuratio ...
- 你知道Spring是怎么解析配置类的吗?
彻底读懂Spring(二)你知道Spring是怎么解析配置类的吗? 推荐阅读: Spring官网阅读系列 彻底读懂Spring(一)读源码,我们可以从第一行读起 Spring执行流程图如下: 如果图片 ...
- 使用spring配置类代替xml配置文件注册bean类
spring配置类,即在类上加@Configuration注解,使用这种配置类来注册bean,效果与xml文件是完全一样的,只是创建springIOC容器的方式不同: //通过xml文件创建sprin ...
- spring 配置 Java配置类装配bean
https://www.cnblogs.com/chenbenbuyi/p/8457700.html 自动化装配的确有很大的便利性,但是却并不能适用在所有的应用场景,比如需要装配的组件类不是由自己的应 ...
- Spring源码解析 – @Configuration配置类及注解Bean的解析
在分析Spring 容器创建过程时,我们知道容器默认会加载一些后置处理器PostPRocessor,以AnnotationConfigApplicationContext为例,在构造函数中初始化rea ...
- spring5 源码深度解析----- 被面试官给虐懵了,竟然是因为我不懂@Configuration配置类及@Bean的原理
@Configuration注解提供了全新的bean创建方式.最初spring通过xml配置文件初始化bean并完成依赖注入工作.从spring3.0开始,在spring framework模块中提供 ...
- Spring5源码解析6-ConfigurationClassParser 解析配置类
ConfigurationClassParser 在ConfigurationClassPostProcessor#processConfigBeanDefinitions方法中创建了Configur ...
- SSM框架新特性关于用Java配置类完全代替XML
项目目录结构 从Spring3.0,@Configuration用于定义配置类,可替换xml配置文件,被注解的类内部包含有一个或多个被@Bean注解的方法, 这些方法将会被AnnotationConf ...
随机推荐
- 关于在DBGridEh的一个字段使用checkbox的方法 .
在DBGridEh的columns中新增加一个字段 1.如果你选择的数据库字段,则选择checkbox为true,并在keylist中输入0和1,就可以了 2.如果你选择的是一个临时字段,在数据集中新 ...
- oracle 迁移数据文件
步骤: 1.SQL>SELECT FILE_NAME FROM DBA_DATA_FILES; FILE_NAME --------------------------------------- ...
- 关于OPC连接读写下位机PLC(转)
原文转自:http://blog.csdn.net/u012252959/article/details/49736285?locationNum=11 开发OPC客户端程序时,首先应该生成OPC服务 ...
- sql语句小记录
测试过程中,需要去数据库中查询一些结果,比如验证码 常用的是查询 更新比较少用 删除一般不用 sql查询语句的嵌套用法,比较实用 比如in的用法:第一种:查询多个值时 SELECT "栏位名 ...
- 算是立flag吧~~~看明天结果了~~~
嗯...以前做ssh.应该是stratus spring hibernate. 然后现在来了一个新的需求. 要用 java,bootstrap,oracle,spring boot, jquery,m ...
- 7.安装pycharm----导入Nmap模块----netcat反向shell----metasploitable靶机环境
安装pycharm www.jetbrains.com/pycharm/ tar -zxvf p补全 ls cd p补全 ls cd bin ls ./pycharm.sh 新建项目 pythonRo ...
- python 并发编程 查看进程的id pid与父进程id ppid
查看进程id pid 不需要传参数 from multiprocessing import Process import time import os def task(): print(" ...
- C语言第十二周作业
这个作业属于那个课程 C语言程序设计II 这个作业要求在哪 https://edu.cnblogs.com/campus/zswxy/computer-scienceclass3-2018/h ...
- jmeter应用之批量插入数据
上一篇讲到如何在jmeter中配置并连接使用mysql数据库,这一节主要是讲数据库连接的简单应用——批量插入数据 总体步骤如下: 1)新建线程组和添加JDBC Connection Configura ...
- Linux cat 多行写入文件防止变量替换
Linux cat 多行写入文件防止变量替换 问题描述 对多个变量及多行输出到文件,存在变量自动替换,当使用cat<<EOF不想对内容进行变量替换.命令替换.参数展开等 问题解决 转义特 ...