前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Spring5.0源码深度解析之Spring基于注解启动流程分析

Spring5.0源码深度解析之Spring基于注解启动流程分析

作者头像
须臾之余
发布2019-07-30 15:24:36
1.2K0
发布2019-07-30 15:24:36
举报
文章被收录于专栏:须臾之余

一:BeanFactory与ApplicationContext区别

ApplicationContext和BeanFactory两者都是用来加载bean的,但相比之下ApplicationContext提供了更多的扩展功能,简单一点说:ApplicationContext包含BeanFactory的所有功能。 通常建议比BeanFactory优先,除非在一些限制的场合。比如字节长度对内存有很大影响时。绝大多数“典型的”企业应用和系统,ApplicationContext就是你需要使用的。 BeanFactory负责读取Bean配置文档,管理bean的加载,实例化,维护Bean之间的依赖关系,负责Bean的生命周期。 ApplicationContext除了提供上述BeanFactory所能提供的功能外,还提供了更完整的框架功能: 国际化支持、资源访问、事件传递等...

下面来分析下,通过AnnotationConfigurationContext类图可知:

由类图可知AnnotationConfigApplicationContext的祖宗是ApplicationContext,所有可以这样写:

代码语言:javascript
复制
ApplicationContext applicationContext = new AnnotationConfigApplicationContext(MyConfig.class);

ApplicationContext 的子类

》》》》AnnotationConfigApplicationContext

》》》》ClassPathXmlApplicationContext

由上图可知:ApplicationContext继承BeanFactory实现扩展功能

ApplicationContext类图

ApplicationContext的祖宗是BeanFactory,实现增强

BeanFactory接口

二:AnnotationConfig启动流程源码分析

代码语言:javascript
复制
@Configuration
public class MyConfig {
    
}
代码语言:javascript
复制
ApplicationContext applicationContext = new AnnotationConfigApplicationContext(MyConfig.class);
String[] beanDefinitionNames = applicationContext.getBeanDefinitionNames();
for (int i=0;i<beanDefinitionNames.length;i++){
    System.out.println(beanDefinitionNames[i]);
}

输出结果

代码语言:javascript
复制
org.springframework.context.annotation.internalConfigurationAnnotationProcessor
org.springframework.context.annotation.internalAutowiredAnnotationProcessor
org.springframework.context.annotation.internalRequiredAnnotationProcessor
org.springframework.context.annotation.internalCommonAnnotationProcessor
org.springframework.context.event.internalEventListenerProcessor
org.springframework.context.event.internalEventListenerFactory
myConfig

说明,能注入到spring容器中

下面源码分析:

代码语言:javascript
复制
ApplicationContext applicationContext = new AnnotationConfigApplicationContext(MyConfig.class);
代码语言:javascript
复制
public AnnotationConfigApplicationContext(Class<?>... annotatedClasses) {
   this();
   register(annotatedClasses);
   refresh();
}
代码语言:javascript
复制
public GenericApplicationContext() {
   this.beanFactory = new DefaultListableBeanFactory();
}
代码语言:javascript
复制
public AnnotationConfigApplicationContext() {
   this.reader = new AnnotatedBeanDefinitionReader(this);
   this.scanner = new ClassPathBeanDefinitionScanner(this);
}
代码语言:javascript
复制
public void register(Class<?>... annotatedClasses) {
   Assert.notEmpty(annotatedClasses, "At least one annotated class must be specified");
   this.reader.register(annotatedClasses); //基于注解方式启动
}
代码语言:javascript
复制
public void register(Class<?>... annotatedClasses) {
   for (Class<?> annotatedClass : annotatedClasses) {
      registerBean(annotatedClass);
   }
}
代码语言:javascript
复制
public void registerBean(Class<?> annotatedClass) {
   doRegisterBean(annotatedClass, null, null, null);
}
代码语言:javascript
复制
<T> void doRegisterBean(Class<T> annotatedClass, @Nullable Supplier<T> instanceSupplier, @Nullable String name,
      @Nullable Class<? extends Annotation>[] qualifiers, BeanDefinitionCustomizer... definitionCustomizers) {

   AnnotatedGenericBeanDefinition abd = new AnnotatedGenericBeanDefinition(annotatedClass);    //BeanDefinition的作用:定义Bean的信息,AnnotatedGenericBeanDefinition 表示注解注入的配置bean
   if (this.conditionEvaluator.shouldSkip(abd.getMetadata())) {    //根据条件注入,判断是否需要注册
      return;
   }

   abd.setInstanceSupplier(instanceSupplier);    //设置回调的方式
   ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(abd);    //判断启动类上是否加上@Scope作用域。没有加默认
   abd.setScope(scopeMetadata.getScopeName());
   String beanName = (name != null ? name : this.beanNameGenerator.generateBeanName(abd, this.registry));//判断是否传递了BeanName,没有则默认类名首字母小写作为BeanName

   AnnotationConfigUtils.processCommonDefinitionAnnotations(abd);
   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));
         }
      }
   }
   for (BeanDefinitionCustomizer customizer : definitionCustomizers) {
      customizer.customize(abd);
   }

   BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(abd, beanName);
   definitionHolder = AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);
   BeanDefinitionReaderUtils.registerBeanDefinition(definitionHolder, this.registry);
}

AnnotatedGenericBeanDefinition :表示注解形式启动的配置类注入spring IOC

代码语言:javascript
复制
String beanName = (name != null ? name : this.beanNameGenerator.generateBeanName(abd, this.registry));
代码语言:javascript
复制
public String generateBeanName(BeanDefinition definition, BeanDefinitionRegistry registry) {
   if (definition instanceof AnnotatedBeanDefinition) {
      String beanName = determineBeanNameFromAnnotation((AnnotatedBeanDefinition) definition);
      if (StringUtils.hasText(beanName)) {
         // Explicit bean name found.
         return beanName;
      }
   }
   // Fallback: generate a unique default bean name.
   return buildDefaultBeanName(definition, registry);
}
代码语言:javascript
复制
protected String buildDefaultBeanName(BeanDefinition definition, BeanDefinitionRegistry registry) {
   return buildDefaultBeanName(definition);
}

下面生成BeanId

代码语言:javascript
复制
AnnotationConfigUtils.processCommonDefinitionAnnotations(abd);
代码语言:javascript
复制
public static void processCommonDefinitionAnnotations(AnnotatedBeanDefinition abd) {
   processCommonDefinitionAnnotations(abd, abd.getMetadata());
}

获取启动类是否添加了如下注解:

代码语言:javascript
复制
static void processCommonDefinitionAnnotations(AnnotatedBeanDefinition abd, AnnotatedTypeMetadata metadata) {
   AnnotationAttributes lazy = attributesFor(metadata, Lazy.class);
   if (lazy != null) {
      abd.setLazyInit(lazy.getBoolean("value"));
   }
   else if (abd.getMetadata() != metadata) {
      lazy = attributesFor(abd.getMetadata(), Lazy.class);
      if (lazy != null) {
         abd.setLazyInit(lazy.getBoolean("value"));
      }
   }

   if (metadata.isAnnotated(Primary.class.getName())) {
      abd.setPrimary(true);
   }
   AnnotationAttributes dependsOn = attributesFor(metadata, DependsOn.class);
   if (dependsOn != null) {
      abd.setDependsOn(dependsOn.getStringArray("value"));
   }

   if (abd instanceof AbstractBeanDefinition) {
      AbstractBeanDefinition absBd = (AbstractBeanDefinition) abd;
      AnnotationAttributes role = attributesFor(metadata, Role.class);
      if (role != null) {
         absBd.setRole(role.getNumber("value").intValue());
      }
      AnnotationAttributes description = attributesFor(metadata, Description.class);
      if (description != null) {
         absBd.setDescription(description.getString("value"));
      }
   }
}

下面看BeanDefinitionHolder包装类:

代码语言:javascript
复制
BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(abd, beanName);//包装一层

BeanDefinition没有BeanName属性,转化为BeanDefinitionHolder添加了BeanName(BeanId),所以需要包装一下。

代码语言:javascript
复制
BeanDefinitionReaderUtils.registerBeanDefinition(definitionHolder, this.registry);
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 一:BeanFactory与ApplicationContext区别
  • 二:AnnotationConfig启动流程源码分析
相关产品与服务
容器服务
腾讯云容器服务(Tencent Kubernetes Engine, TKE)基于原生 kubernetes 提供以容器为核心的、高度可扩展的高性能容器管理服务,覆盖 Serverless、边缘计算、分布式云等多种业务部署场景,业内首创单个集群兼容多种计算节点的容器资源管理模式。同时产品作为云原生 Finops 领先布道者,主导开源项目Crane,全面助力客户实现资源优化、成本控制。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档