ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

Spring Bean的加载机制

2021-09-17 21:03:15  阅读:317  来源: 互联网

标签:NAME Spring BEAN Bean registry new 注解 def 加载


1.spring 注解的加载
在 Spring 容器的核心基类 AbstractApplicationContext refresh 中设置后置处理器时,AnnotatedBeanDefinitionReader 调用 AnnotationConfigUtils.registerAnnotationConfigProcessors(this.registry)的方法,将注解的解析处理器注册到当前 Spring容器上下文中。正是通过这些注解解析器,实现了对注解的解析及Bean的注入等功能。
public AnnotatedBeanDefinitionReader(BeanDefinitionRegistry registry, Environment environment) {
Assert.notNull(registry, “BeanDefinitionRegistry must not be null”);
Assert.notNull(environment, “Environment must not be null”);
this.registry = registry;
this.conditionEvaluator = new ConditionEvaluator(registry, environment, null);
AnnotationConfigUtils.registerAnnotationConfigProcessors(this.registry);
}
AnnotationConfigUtils.RegisterAnnotationConfigProcessors方法的实现源码如下:
public static Set registerAnnotationConfigProcessors(
BeanDefinitionRegistry registry, @Nullable Object source) {
//将BeanDefinitionRegistry转换为DefaultListableBeanFactory实例
DefaultListableBeanFactory beanFactory = unwrapDefaultListableBeanFactory(registry);
if (beanFactory != null) {
if (!(beanFactory.getDependencyComparator() instanceof AnnotationAwareOrderComparator)) {
beanFactory.setDependencyComparator(AnnotationAwareOrderComparator.INSTANCE);
}
//设置注解自动注入解析器
if (!(beanFactory.getAutowireCandidateResolver() instanceof ContextAnnotationAutowireCandidateResolver)) {
beanFactory.setAutowireCandidateResolver(new ContextAnnotationAutowireCandidateResolver());
}
}

Set beanDefs = new LinkedHashSet<>(8);

//在bean定义中设置bean工厂的后置处理器
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);
def.setSource(source);
beanDefs.add(registerPostProcessor(registry, def, AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME));
}

//如果存在JSR-250支持包,添加AnnotationBeanPostProcessor后置处理器
if (jsr250Present && !registry.containsBeanDefinition(COMMON_ANNOTATION_PROCESSOR_BEAN_NAME)) {
RootBeanDefinition def = new RootBeanDefinition(CommonAnnotationBeanPostProcessor.class);
def.setSource(source);
beanDefs.add(registerPostProcessor(registry, def, COMMON_ANNOTATION_PROCESSOR_BEAN_NAME));
}

// 如果存在JPA支持包, 添加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;
}
在注解配置上下文时,为当前Beanfactory设置了很多BeanPostProcessor,然后spring通过ConfigurationClassPostProcessor 实现了对 Bean 配置类注解的解析和注册(如@Bean、@Configuration注解);AutowiredAnnotationBeanPostProcessor实现了对自动注入类注解的解析和注册(如@Autowired、@Value注解)。
1.1ConfigurationClassPostProcessor
该类用于处理spring上下文Bean定义信息的重要方法是postProcessBeanFactory,具体实现如下:
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) {
int factoryId = System.identityHashCode(beanFactory);
if (this.factoriesPostProcessed.contains(factoryId)) {
throw new IllegalStateException(
"postProcessBeanFactory already called on this post-processor against " + beanFactory);
}
this.factoriesPostProcessed.add(factoryId);
if (!this.registriesPostProcessed.contains(factoryId)) {
// BeanDefinitionRegistryPostProcessor hook apparently not supported…
// Simply call processConfigurationClasses lazily at this point then.
processConfigBeanDefinitions((BeanDefinitionRegistry) beanFactory);
}

//利用cglib动态代理创建configuration注解Bean
enhanceConfigurationClasses(beanFactory);
//为bean工厂注册自动导入bean的后置处理器
beanFactory.addBeanPostProcessor(new ImportAwareBeanPostProcessor(beanFactory));
}
PostProcessBeanFactory是在refresh方法中调用的,并且在Spring容器加载时触发调用。
2.注解bean的解析和注册
通过 postProcessBeanDefinitionRegistry方法调用processConfigBeanDefinitions,来处理bean描述信息实体的排序,以及configuration bean的解析和读取,processConfigBeanDefinitions的源码如下:
// 处理标注@Order注解值的排序
configCandidates.sort((bd1, bd2) -> {
int i1 = ConfigurationClassUtils.getOrder(bd1.getBeanDefinition());
int i2 = ConfigurationClassUtils.getOrder(bd2.getBeanDefinition());
return Integer.compare(i1, i2);
});
// 解析 @Configuration注解类
ConfigurationClassParser parser = new ConfigurationClassParser(
this.metadataReaderFactory, this.problemReporter, this.environment,
this.resourceLoader, this.componentScanBeanNameGenerator, registry);
//处理自动导入类bean
if (sbr != null && !sbr.containsSingleton(IMPORT_REGISTRY_BEAN_NAME)) {
sbr.registerSingleton(IMPORT_REGISTRY_BEAN_NAME, parser.getImportRegistry());
}
解析过程利用了ConfigurationClassParser,其执行流程大致为: parse->processConfigurationClass->doProcessConfigurationClass,doProcessConfigurationClass解析实现如下:
// 处理@PropertySource注解
for (AnnotationAttributes propertySource : AnnotationConfigUtils.attributesForRepeatable(
sourceClass.getMetadata(), PropertySources.class,
org.springframework.context.annotation.PropertySource.class)) {
if (this.environment instanceof ConfigurableEnvironment) {
processPropertySource(propertySource);
}
else {
logger.info(“Ignoring @PropertySource annotation on [” + sourceClass.getMetadata().getClassName() +
“]. Reason: Environment must implement ConfigurableEnvironment”);
}
}
// 处理@ComponentScan注解
Set componentScans = AnnotationConfigUtils.attributesForRepeatable(
sourceClass.getMetadata(), ComponentScans.class, ComponentScan.class);
if (!componentScans.isEmpty() &&
!this.conditionEvaluator.shouldSkip(sourceClass.getMetadata(), ConfigurationPhase.REGISTER_BEAN)) {
for (AnnotationAttributes componentScan : componentScans) {
// The config class is annotated with @ComponentScan -> perform the scan immediately
Set scannedBeanDefinitions =
this.componentScanParser.parse(componentScan, sourceClass.getMetadata().getClassName());
// Check the set of scanned definitions for any further config classes and parse recursively if needed
for (BeanDefinitionHolder holder : scannedBeanDefinitions) {
BeanDefinition bdCand = holder.getBeanDefinition().getOriginatingBeanDefinition();
if (bdCand == null) {
bdCand = holder.getBeanDefinition();
}
if (ConfigurationClassUtils.checkConfigurationClassCandidate(bdCand, this.metadataReaderFactory)) {
parse(bdCand.getBeanClassName(), holder.getBeanName());
}
}
}
}

// 处理@Import注解
processImports(configClass, sourceClass, getImports(sourceClass), true);

// 处理@ImportResource注解
AnnotationAttributes importResource =
AnnotationConfigUtils.attributesFor(sourceClass.getMetadata(), ImportResource.class);
if (importResource != null) {
String[] resources = importResource.getStringArray(“locations”);
Class<? extends BeanDefinitionReader> readerClass = importResource.getClass(“reader”);
for (String resource : resources) {
String resolvedResource = this.environment.resolveRequiredPlaceholders(resource);
configClass.addImportedResource(resolvedResource, readerClass);
}
}
// 处理@Bean注解
Set beanMethods = retrieveBeanMethodMetadata(sourceClass);
for (MethodMetadata methodMetadata : beanMethods) {
configClass.addBeanMethod(new BeanMethod(methodMetadata, configClass));
}

//处理接口的default方法
processInterfaces(configClass, sourceClass);
// 处理父类
if (sourceClass.getMetadata().hasSuperClass()) {
String superclass = sourceClass.getMetadata().getSuperClassName();
if (superclass != null && !superclass.startsWith(“java”) &&
!this.knownSuperclasses.containsKey(superclass)) {
this.knownSuperclasses.put(superclass, configClass);
// Superclass found, return its annotation metadata and recurse
return sourceClass.getSuperClass();
}
}
3.AutowiredAnnotationBeanPostProcessor
AutowiredAnnotationBeanPostProcessor是Bean后置处理器,用于处理自动注入注解。
我们都知道,Spring 的注入分为构造方法、方法、参数、属性和注解类型,其核心原理就是使用Java反射技术来实现属性赋值:
protected void inject(Object target, @Nullable String requestingBeanName, @Nullable PropertyValues pvs) throws Throwable {
if (this.isField) {
Field field = (Field) this.member;
ReflectionUtils.makeAccessible(field);
field.set(target, getResourceToInject(target, requestingBeanName));
}
else {
if (checkPropertySkipping(pvs)) {
return;
}
try {
Method method = (Method) this.member;
ReflectionUtils.makeAccessible(method);
method.invoke(target, getResourceToInject(target, requestingBeanName));
}
catch (InvocationTargetException ex) {
throw ex.getTargetException();
}
}
}

Spring注解构造方法自动注入的核心实现逻辑是在选取构造方法后找到依赖属性,然后在 BeanFactory获取 Bean时或者单例方法启动初始化时,反射当前构造方法来实现 DI(依赖注入)的自动注入。
Spring的注解注入比较复杂而且Bean的注解定义模型和XML标签定义模型不同,这里先看看Spring Bean注解解析的类图,如图所示。
在这里插入图片描述

从图中可以看出,注解加载的核心聚合属性类是ConfigurationClass,它支持读取配置文件和注解描述,并且支持 selectImport 函数。ConfigurationClassParser 负责把BeanDefinitionHolder解析成ConfigurationClass(在BeanDefinitionHolder中只持有配置了Configuration 注解的类的描述信息)。ConfigurationClassBeanDefinitionReader 读取ConfigurationClass并把这些注解的描述信息注册到BeanFactory中。

标签:NAME,Spring,BEAN,Bean,registry,new,注解,def,加载
来源: https://blog.csdn.net/weixin_50763382/article/details/120356715

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有