sping ioc 源码分析(一)-- register(componentClasses) 方法
一.测试环境的搭建:
public class Apple {
}
@Component
public class MyComponet {
}
public class MyCondition implements Condition {
@Override
public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
return metadata.isAnnotated("org.springframework.context.annotation.Configuration");
}
}
@Configuration
@Import(Apple.class)
public class MyConfig {
@Bean
public Student student(){
return new Student();
}
}
public class Student {
}
@Configuration
@ComponentScan("com.yang.xiao.hui.ioc")
@Conditional(MyCondition.class)
public class App
{
public static void main( String[] args )
{
ApplicationContext ctx = new AnnotationConfigApplicationContext(App.class);
}
}
//主要分析的是@import,@Componet@Bean @componentScan的方式向spring容器中注入bean的方式:
一个类变成bean的简单过程:

debug调试:

在创建一个类时,会先初始化其父类:GenericApplicationContext 断点在该类的构造器中:

父类创建的过程中,new 了一个beanFactory,而这个就是我们侠义上的ioc容器了,我们的bean定义信息和单例bean都是存在这里的:我们看看该类:
public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFactory
implements ConfigurableListableBeanFactory, BeanDefinitionRegistry, Serializable { @Nullable
private static Class<?> javaxInjectProviderClass; static {
try {
javaxInjectProviderClass =
ClassUtils.forName("javax.inject.Provider", DefaultListableBeanFactory.class.getClassLoader());
}
catch (ClassNotFoundException ex) {
// JSR-330 API not available - Provider interface simply not supported then.
javaxInjectProviderClass = null;
}
} /** Map from serialized id to factory instance. */
private static final Map<String, Reference<DefaultListableBeanFactory>> serializableFactories =
new ConcurrentHashMap<>(8); /** Optional id for this factory, for serialization purposes. */
@Nullable
private String serializationId; /** Whether to allow re-registration of a different definition with the same name. */
private boolean allowBeanDefinitionOverriding = true; /** Whether to allow eager class loading even for lazy-init beans. */
private boolean allowEagerClassLoading = true; /** Optional OrderComparator for dependency Lists and arrays. */
@Nullable
private Comparator<Object> dependencyComparator; /** Resolver to use for checking if a bean definition is an autowire candidate. */
private AutowireCandidateResolver autowireCandidateResolver = new SimpleAutowireCandidateResolver(); /** Map from dependency type to corresponding autowired value. */
private final Map<Class<?>, Object> resolvableDependencies = new ConcurrentHashMap<>(16); /** Map of bean definition objects, keyed by bean name. */
private final Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<>(256); //这里存储了bean的名称和其定义信息 /** Map of singleton and non-singleton bean names, keyed by dependency type. */
private final Map<Class<?>, String[]> allBeanNamesByType = new ConcurrentHashMap<>(64); //bean的类型和对应的beanName,一个bean是可以有别名的 /** Map of singleton-only bean names, keyed by dependency type. */
private final Map<Class<?>, String[]> singletonBeanNamesByType = new ConcurrentHashMap<>(64); /** List of bean definition names, in registration order. */
private volatile List<String> beanDefinitionNames = new ArrayList<>(256);//以list集合的方式,存储了所有的beanName /** List of names of manually registered singletons, in registration order. */
private volatile Set<String> manualSingletonNames = new LinkedHashSet<>(16); //手动注册的单列的bean /** Cached array of bean definition names in case of frozen configuration. */
@Nullable
private volatile String[] frozenBeanDefinitionNames; /** Whether bean definition metadata may be cached for all beans. */
private volatile boolean configurationFrozen = false;
//。。。。。。。。。。。。。。。。。。。。省略部分代码。。。。。。。。。。。。。。。。。。
}

由继承体系可知:DefaultListableBeanFactory 继承了DefaultSingletonBeanRegistry,因此我们看看这个类

小结:我们的bean定义信息和bean对象最终都会存到DefaultListableBeanFactory类对应的属性中:Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<>(256) 和private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256);
我们继续debug调试:

//主要看看this.reader = new AnnotatedBeanDefinitionReader(this);
//该对象底层给beanFactory添加了几个核心的后置处理器

public static Set<BeanDefinitionHolder> registerAnnotationConfigProcessors(
BeanDefinitionRegistry registry, @Nullable Object source) { DefaultListableBeanFactory beanFactory = unwrapDefaultListableBeanFactory(registry); //获取beanFactory
if (beanFactory != null) {
if (!(beanFactory.getDependencyComparator() instanceof AnnotationAwareOrderComparator)) {
beanFactory.setDependencyComparator(AnnotationAwareOrderComparator.INSTANCE); //设置一个用于排序的比较器
}
if (!(beanFactory.getAutowireCandidateResolver() instanceof ContextAnnotationAutowireCandidateResolver)) {
beanFactory.setAutowireCandidateResolver(new ContextAnnotationAutowireCandidateResolver()); //设置一个用于解析@lazy @qualifier注解的解析器
}
} Set<BeanDefinitionHolder> beanDefs = new LinkedHashSet<>(8); if (!registry.containsBeanDefinition(CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME)) {
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)) {
RootBeanDefinition def = new RootBeanDefinition(AutowiredAnnotationBeanPostProcessor.class); //设置一个用于解析@autowired注解的后置处理器
def.setSource(source);
beanDefs.add(registerPostProcessor(registry, def, AUTOWIRED_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); //设置一个用于解析@preDestory 和@postConstruct注解的后置处理器
def.setSource(source);
beanDefs.add(registerPostProcessor(registry, def, COMMON_ANNOTATION_PROCESSOR_BEAN_NAME));
} // Check for JPA support, and if present add the 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));
} return beanDefs;
}
//本次我们主要分析的方法: register(componentClasses);


<T> void doRegisterBean(Class<T> beanClass, @Nullable Supplier<T> instanceSupplier, @Nullable String name,
@Nullable Class<? extends Annotation>[] qualifiers, BeanDefinitionCustomizer... definitionCustomizers) { AnnotatedGenericBeanDefinition abd = new AnnotatedGenericBeanDefinition(beanClass); //创建beanDefinition
if (this.conditionEvaluator.shouldSkip(abd.getMetadata())) { //这里是处理Condition注解,如果条件匹配就跳过,后续会分析
return;
} abd.setInstanceSupplier(instanceSupplier);//设置实例工厂,这里为null
ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(abd); //获取@scope注解的元信息,这个在aop源码博客有分析过
abd.setScope(scopeMetadata.getScopeName());
String beanName = (name != null ? name : this.beanNameGenerator.generateBeanName(abd, this.registry)); AnnotationConfigUtils.processCommonDefinitionAnnotations(abd); //这里是处理bean的一些公共注解:@Lazy,@Primary,@DependsOn,@Role,@Description
if (qualifiers != null) {//这里为null
for (Class<? extends Annotation> qualifier : qualifiers) { //处理@Lazy,@Primary,@qualifier
if (Primary.class == qualifier) {
abd.setPrimary(true);
}
else if (Lazy.class == qualifier) {
abd.setLazyInit(true);
}
else {
abd.addQualifier(new AutowireCandidateQualifier(qualifier));
}
}
}
for (BeanDefinitionCustomizer customizer : definitionCustomizers) { //这里也为null
customizer.customize(abd); //允许我们对bean的定义信息做一些修改
} BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(abd, beanName); //装饰一下beanDefinition
definitionHolder = AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry); //处理bean的@Scope注解
BeanDefinitionReaderUtils.registerBeanDefinition(definitionHolder, this.registry);//向DefaultListableBeanFactory中注册beanDefinition,后面会跟进
}

@Override
public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition)
throws BeanDefinitionStoreException { BeanDefinition existingDefinition = this.beanDefinitionMap.get(beanName);//判断是否已经存在对应的beanDifinition了
if (existingDefinition != null) {
if (!isAllowBeanDefinitionOverriding()) { //如果已经存在,并且不允许覆盖就抛异常
throw new BeanDefinitionOverrideException(beanName, beanDefinition, existingDefinition);
}
else if (existingDefinition.getRole() < beanDefinition.getRole()) { //角色升级,我们自己定义的bean,role就是application,spring自己的bean,角色就是role_support或者ROLE_INFRASTRUCTURE
// e.g. was ROLE_APPLICATION, now overriding with ROLE_SUPPORT or ROLE_INFRASTRUCTURE
if (logger.isInfoEnabled()) {
logger.info("Overriding user-defined bean definition for bean '" + beanName +
"' with a framework-generated bean definition: replacing [" +
existingDefinition + "] with [" + beanDefinition + "]");
}
}
else if (!beanDefinition.equals(existingDefinition)) {//如果跟之前的不一样,就打印一下日志
if (logger.isDebugEnabled()) {
logger.debug("Overriding bean definition for bean '" + beanName +
"' with a different definition: replacing [" + existingDefinition +
"] with [" + beanDefinition + "]");
}
}
else {
if (logger.isTraceEnabled()) {
logger.trace("Overriding bean definition for bean '" + beanName +
"' with an equivalent definition: replacing [" + existingDefinition +
"] with [" + beanDefinition + "]");
}
}
this.beanDefinitionMap.put(beanName, beanDefinition); //将bean的定义信息存到map集合中
}
else {
if (hasBeanCreationStarted()) { //如果存在bean的创建已经开始
// Cannot modify startup-time collection elements anymore (for stable iteration)
synchronized (this.beanDefinitionMap) {
this.beanDefinitionMap.put(beanName, beanDefinition);//将bean的定义信息存到map集合中
List<String> updatedDefinitions = new ArrayList<>(this.beanDefinitionNames.size() + 1);
updatedDefinitions.addAll(this.beanDefinitionNames);
updatedDefinitions.add(beanName);
this.beanDefinitionNames = updatedDefinitions;
removeManualSingletonName(beanName);
}
}
else {
// Still in startup registration phase 还在注册阶段
this.beanDefinitionMap.put(beanName, beanDefinition);//将bean的定义信息存到map集合中
this.beanDefinitionNames.add(beanName);
removeManualSingletonName(beanName);
}
this.frozenBeanDefinitionNames = null;
} if (existingDefinition != null || containsSingleton(beanName)) { //bean的实例已经创建
resetBeanDefinition(beanName); //重新设置bean的定义信息
}
}


接下来,我们回去看看condition注解的解析逻辑:

public boolean shouldSkip(@Nullable AnnotatedTypeMetadata metadata, @Nullable ConfigurationPhase phase) {
if (metadata == null || !metadata.isAnnotated(Conditional.class.getName())) { //先判断有没conditional注解,我们在本次的测试中,添加了@Conditional(MyCondition.class)
return false;
}
if (phase == null) { //ConfigurationPhase phase 是一个枚举,用于判断condition生效的阶段
if (metadata instanceof AnnotationMetadata &&
ConfigurationClassUtils.isConfigurationCandidate((AnnotationMetadata) metadata)) { //如果被Conditonal标注的类是一个是一个配置类
return shouldSkip(metadata, ConfigurationPhase.PARSE_CONFIGURATION); //再次递归调用本方法,此时枚举就有值了
}
return shouldSkip(metadata, ConfigurationPhase.REGISTER_BEAN);
}
List<Condition> conditions = new ArrayList<>();
for (String[] conditionClasses : getConditionClasses(metadata)) { //获取所有的Conditional注解的属性值,业绩是Condition.class的实现类类名
for (String conditionClass : conditionClasses) {
Condition condition = getCondition(conditionClass, this.context.getClassLoader());//反射创建Conditon.class的实例
conditions.add(condition);
}
}
AnnotationAwareOrderComparator.sort(conditions); //排序
for (Condition condition : conditions) {
ConfigurationPhase requiredPhase = null;
if (condition instanceof ConfigurationCondition) {
requiredPhase = ((ConfigurationCondition) condition).getConfigurationPhase();
}
//如果requiredPhase 为null,或者枚举值一致才会去匹配条件,如果条件匹配不上,就要跳过该bean,这个bean就不会加入到spring容器中
if ((requiredPhase == null || requiredPhase == phase) && !condition.matches(this.context, metadata)) {
return true;
}
}
return false;
}
//小结: register(componentClasses); 方法的作用就是将主启动类的bean的定义信息注册到容器
sping ioc 源码分析(一)-- register(componentClasses) 方法的更多相关文章
- sping ioc 源码分析(二)-- refresh()方法分析
测试环境代码: @Configuration @ComponentScan("com.yang.xiao.hui.ioc") @Conditional(MyCondition.cl ...
- Spring Ioc源码分析系列--Bean实例化过程(二)
Spring Ioc源码分析系列--Bean实例化过程(二) 前言 上篇文章Spring Ioc源码分析系列--Bean实例化过程(一)简单分析了getBean()方法,还记得分析了什么吗?不记得了才 ...
- Spring IOC 源码分析
Spring 最重要的概念是 IOC 和 AOP,本篇文章其实就是要带领大家来分析下 Spring 的 IOC 容器.既然大家平时都要用到 Spring,怎么可以不好好了解 Spring 呢?阅读本文 ...
- spring IoC源码分析 (3)Resource解析
引自 spring IoC源码分析 (3)Resource解析 定义好了Resource之后,看到XmlFactoryBean的构造函数 public XmlBeanFactory(Resource ...
- Spring IoC 源码分析 (基于注解) 之 包扫描
在上篇文章Spring IoC 源码分析 (基于注解) 一我们分析到,我们通过AnnotationConfigApplicationContext类传入一个包路径启动Spring之后,会首先初始化包扫 ...
- Spring Ioc源码分析系列--Ioc的基础知识准备
Spring Ioc源码分析系列--Ioc的基础知识准备 本系列文章代码基于Spring Framework 5.2.x Ioc的概念 在Spring里,Ioc的定义为The IoC Containe ...
- Spring Ioc源码分析系列--Ioc源码入口分析
Spring Ioc源码分析系列--Ioc源码入口分析 本系列文章代码基于Spring Framework 5.2.x 前言 上一篇文章Spring Ioc源码分析系列--Ioc的基础知识准备介绍了I ...
- Spring Ioc源码分析系列--Ioc容器注册BeanPostProcessor后置处理器以及事件消息处理
Spring Ioc源码分析系列--Ioc容器注册BeanPostProcessor后置处理器以及事件消息处理 前言 上一篇分析了BeanFactoryPostProcessor的作用,那么这一篇继续 ...
- Spring Ioc源码分析系列--Bean实例化过程(一)
Spring Ioc源码分析系列--Bean实例化过程(一) 前言 上一篇文章Spring Ioc源码分析系列--Ioc容器注册BeanPostProcessor后置处理器以及事件消息处理已经完成了对 ...
随机推荐
- DevOps系列(1)-总体架构
扯闲淡 在进入正式话题之前,先扯个淡,这算是第一篇我正式在博客上发布的随笔吧,之前也一直有想写点什么,将自己多年的工作经验分享出来,供大家参考点评,但是奈何一直对自己的文字功底不自信(其实也确实比较烂 ...
- C# 根据出生年月 计算天数/计算X岁X月X天字符串
public class TimeTool { //根据出生年月计算 整数天 private static int GetAgeByBirthdate(DateTime birthdate) { Da ...
- wordpress建站如何用SMTP配置邮件通知
前提条件:你已经有了企业邮箱,相关文章请看:如何开通阿里云企业邮箱免费版(点此前往) 不建议使用主机商提供的邮箱,因为换主机商是比较常见的事情,因此导致的邮箱迁移就有些麻烦了,不如一开始就选择独立的第 ...
- JS学习阶段性总结-1
各种函数的声明 /** * 函数的声明 */ // 声明一个方法,任意调用 function aaa(args){...} // 声明一个函数并以变量的形式展示出去,因此无法再声明前调用 var fn ...
- springmvc以及springboot中的拦截器配置
拦截器两种实现 如果不同的controller中都需要拦截器,不能使用相同的拦截器,因为拦截器不能跨controller,这个时候只能为不同的controller配置不同的拦截器,每一个拦截器只能 ...
- Fitness - 06.01
倒计时213天 久违的瑜伽课,却发现生疏了很多,倒地不起TAT 要加强锻炼,不要松懈啊~~~! 期待黄金周的到来!!
- Fitness - 05.08
倒计时237天 运动34分钟,共计8组,3.4公里.拉伸10分钟. 每组跑步2分钟(6.6KM/h),走路2分钟(6KM/h). 最近掉了几斤,所以今天状态感觉特别好. 虽然每天在拼命学习Unity, ...
- GLSL 着色器程序
除了使用Cg/HSL 着色器程序以外, OpenGL 着色器语言(GLSL)着色器可以直接书写shader. 然而,使用原生的GLSL只推荐作为测试使用,或者你清晰的知道你的目标平台是 Mac OS ...
- P1090 合并果子(哈弗曼树)
题目描述 在一个果园里,多多已经将所有的果子打了下来,而且按果子的不同种类分成了不同的堆.多多决定把所有的果子合成一堆. 每一次合并,多多可以把两堆果子合并到一起,消耗的体力等于两堆果子的重量之和.可 ...
- P1164 小A点菜(动态规划背包问题)
题目背景 uim神犇拿到了uoi的ra(镭牌)后,立刻拉着基友小A到了一家--餐馆,很低端的那种. uim指着墙上的价目表(太低级了没有菜单),说:"随便点". 题目描述 不过ui ...