加载AnnotationConfig
mian()入口
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(MyConfig.class);
@Configuration public class MyConfig { @Bean public BeanA beanA() {return new BeanA();} @Bean public BeanB beanB(BeanA beanA) {return new BeanB().set(beanA);} static class BeanA{} static class BeanB{ private BeanA beanA; public BeanB set(BeanA beanA) {this.beanA = beanA;return this;} public BeanA get() {return beanA;} } }
AnnotationConfigApplicationContext
public AnnotationConfigApplicationContext(Class<?>... componentClasses) { //创建AnnotatedBeanDefinitionReader 创建ClassPathBeanDefinitionScanner this(); //注册class register(componentClasses); //大名鼎鼎的refresh refresh(); }
点击diagrams图 留着,初期看源码不开图,懵逼/(ㄒoㄒ)/~~
读取类AnnotatedBeanDefinitionReader
点击 this.reader.register
()方法,registerBean()
方法进到doRegisterBean,
spring中凡是do开头大多都是真正干活的类
/** * 省略了注解,记得看 */ private <T> void doRegisterBean(Class<T> beanClass, @Nullable String name, @Nullable Class<? extends Annotation>[] qualifiers, @Nullable Supplier<T> supplier, @Nullable BeanDefinitionCustomizer[] customizers) { AnnotatedGenericBeanDefinition abd = new AnnotatedGenericBeanDefinition(beanClass); if (this.conditionEvaluator.shouldSkip(abd.getMetadata())) { return; } abd.setInstanceSupplier(supplier); //解析作用域 原始/元数据 默认单例,并设置到bd中 ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(abd); abd.setScope(scopeMetadata.getScopeName()); String beanName = (name != null ? name : this.beanNameGenerator.generateBeanName(abd, this.registry)); /** * processCommonDefinitionAnnotations * 用于解析通用的注解定义,并根据注解的属性值设置对应的Bean定义属性。 * 处理了@Lazy注解的懒加载标志、@Primary注解的主要标志、@DependsOn注解的依赖关系、 * @Role注解的角色以及@Description注解的描述,并将这些属性值设置到Bean定义中。 */ AnnotationConfigUtils.processCommonDefinitionAnnotations(abd); //@Qualifier if (qualifiers != null) { for (Class<? extends Annotation> qualifier : qualifiers) { //@Primary if (Primary.class == qualifier) { abd.setPrimary(true); } //@Lazy else if (Lazy.class == qualifier) { abd.setLazyInit(true); } else { //提示有限定符需要注意 abd.addQualifier(new AutowireCandidateQualifier(qualifier)); } } } //上面代码的目的是根据不同的限定符,对abd进行不同的设置,以确保正确的Bean被注入。 if (customizers != null) { for (BeanDefinitionCustomizer customizer : customizers) { customizer.customize(abd); } } BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(abd, beanName); //根据作用域代理模式,为Bean定义创建适当的代理,并将代理注册到Bean定义注册表中。这样,当获取该作用域的Bean实例时,实际上获取到的是代理对象。默认是 NO definitionHolder = AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry); /** * 判断是否存在 existingDefinition * 判断是否创建中 hasBeanCreationStarted * 注册bean到 beanDefinitionMap * 添加beanName到 beanDefinitionNames * 注册后需要删除手动注册方式注册到spring context上 singleton bean name * 可能是防止冲突或错误 */ BeanDefinitionReaderUtils.registerBeanDefinition(definitionHolder, this.registry); //等待refresh }
之后就是refresh方法
小结
AnnotationConfig源码读取比XML读取的方法较为清晰
AnnotationConfig父类GenericApplicationContext和ClassPathXmlApplicationContext父类AbstractXmlApplicationContext
是Spring Framework中的两个应用程序上下文的实现类。
共同点:
都是应用程序上下文的具体实现类,用于管理和组织Spring应用程序的Bean。
都继承自抽象类ApplicationContext,并实现了相应的接口,提供了通用的上下文功能,如Bean的注册、获取、生命周期管理等。
不同点:
GenericApplicationContext
是一个通用的应用程序上下文,支持多种方式的Bean定义加载,如通过XML、注解、Java配置等。它的加载方式更加灵活,可以根据需要选择合适的方式加载Bean定义。
AbstractXmlApplicationContext
是基于XML配置的应用程序上下文,专门用于加载和解析XML格式的Bean定义。它通过解析XML文件来创建和配置Bean实例。
GenericApplicationContext
的配置方式更为灵活,可以通过编程的方式进行配置,可以在运行时动态地注册和修改Bean定义。
AbstractXmlApplicationContext
的配置方式是静态的,需要提前将Bean定义配置在XML文件中,然后通过解析XML文件来完成上下文的初始化。
GenericApplicationContext
可以与不同类型的Bean定义读取器(如AnnotatedBeanDefinitionReader、ClassPathBeanDefinitionScanner等)结合使用,以支持不同的加载方式。
AbstractXmlApplicationContext
内部使用XmlBeanDefinitionReader
来解析XML文件,并加载XML中定义的Bean。
GenericApplicationContext是从Spring Framework 2.5版本引入的,它是一个通用的应用程序上下文实现,可以用于加载和管理各种类型的Bean定义,包括XML、注解和Java配置等。
AbstractXmlApplicationContext是早期版本的Spring Framework中的一个应用程序上下文实现,它专门用于加载和解析基于XML配置的Bean定义。
小结:
GenericApplicationContext
是一个通用且灵活的应用程序上下文,可以支持多种方式的Bean定义加载,而AbstractXmlApplicationContext
则是基于XML配置的应用程序上下文,专注于加载和解析XML格式的Bean定义。