当前位置: 首页 > news >正文

重庆大渡口网站建设解决方案株洲最新通知今天

重庆大渡口网站建设解决方案,株洲最新通知今天,站台建筑,互联网保险发展现状【前言】 我们在使用Spring注入Bean对象时#xff0c;会使用不同注解#xff0c;比如Component Service Controller Import Bean等。由于Service Controller 等都可以归为Component#xff0c;那么Component 和Import 、Bean是何时被加载的#xff0c;以及他们之间的顺序呢…【前言】 我们在使用Spring注入Bean对象时会使用不同注解比如Component Service Controller Import Bean等。由于Service Controller 等都可以归为Component那么Component 和Import 、Bean是何时被加载的以及他们之间的顺序呢下面就来分析一下。 【源码解析】 首先Spring的启动肯定是由AbstractApplicationContext.refresh()方法开始的。之后直接进入invokeBeanFactoryPostProcessors(beanFactory)方法该方法用来处理要载入的Bean对象。会进入PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, getBeanFactoryPostProcessors())方法。 之后会进入ConfigurationClassPostProcessor类的postProcessBeanDefinitionRegistry方法。 public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) {int registryId System.identityHashCode(registry);if (this.registriesPostProcessed.contains(registryId)) {throw new IllegalStateException(postProcessBeanDefinitionRegistry already called on this post-processor against registry);}if (this.factoriesPostProcessed.contains(registryId)) {throw new IllegalStateException(postProcessBeanFactory already called on this post-processor against registry);}this.registriesPostProcessed.add(registryId);processConfigBeanDefinitions(registry);} 进入processConfigBeanDefinitions(registry);该方法主要加载就是如下这段 ........................ ConfigurationClassParser parser new ConfigurationClassParser(this.metadataReaderFactory, this.problemReporter, this.environment,this.resourceLoader, this.componentScanBeanNameGenerator, registry);SetBeanDefinitionHolder candidates new LinkedHashSet(configCandidates);SetConfigurationClass alreadyParsed new HashSet(configCandidates.size());do {parser.parse(candidates);parser.validate();SetConfigurationClass configClasses new LinkedHashSet(parser.getConfigurationClasses());configClasses.removeAll(alreadyParsed);// Read the model and create bean definitions based on its contentif (this.reader null) {this.reader new ConfigurationClassBeanDefinitionReader(registry, this.sourceExtractor, this.resourceLoader, this.environment,this.importBeanNameGenerator, parser.getImportRegistry());}this.reader.loadBeanDefinitions(configClasses);} ........................ 这段parser.parse(candidates);中candidates就是最初启动的bean对象名字比如springboot应用中的主类带Springboot标识的如下 SpringBootApplication public class DemoApplication {public static void main(String[] args) {new SpringApplication(DemoApplication.class).run(args);} } 那么candidates 就会包含这个DemoApplication 。进入parser.parse(candidates)方法 public void parse(SetBeanDefinitionHolder configCandidates) {for (BeanDefinitionHolder holder : configCandidates) {BeanDefinition bd holder.getBeanDefinition();try {if (bd instanceof AnnotatedBeanDefinition) {parse(((AnnotatedBeanDefinition) bd).getMetadata(), holder.getBeanName());}else if (bd instanceof AbstractBeanDefinition ((AbstractBeanDefinition) bd).hasBeanClass()) {parse(((AbstractBeanDefinition) bd).getBeanClass(), holder.getBeanName());}else {parse(bd.getBeanClassName(), holder.getBeanName());}}catch (BeanDefinitionStoreException ex) {throw ex;}catch (Throwable ex) {throw new BeanDefinitionStoreException(Failed to parse configuration class [ bd.getBeanClassName() ], ex);}}this.deferredImportSelectorHandler.process();} 会继续进行解析根据不同类型但一般都是AnnotatedBeanDefinition。之后继续进入 protected final void parse(AnnotationMetadata metadata, String beanName) throws IOException {processConfigurationClass(new ConfigurationClass(metadata, beanName));}protected void processConfigurationClass(ConfigurationClass configClass) throws IOException {if (this.conditionEvaluator.shouldSkip(configClass.getMetadata(), ConfigurationPhase.PARSE_CONFIGURATION)) {return;}ConfigurationClass existingClass this.configurationClasses.get(configClass);if (existingClass ! null) {if (configClass.isImported()) {if (existingClass.isImported()) {existingClass.mergeImportedBy(configClass);}// Otherwise ignore new imported config class; existing non-imported class overrides it.return;}else {// Explicit bean definition found, probably replacing an import.// Lets remove the old one and go with the new one.this.configurationClasses.remove(configClass);this.knownSuperclasses.values().removeIf(configClass::equals);}}// Recursively process the configuration class and its superclass hierarchy.SourceClass sourceClass asSourceClass(configClass);do {sourceClass doProcessConfigurationClass(configClass, sourceClass);}while (sourceClass ! null);this.configurationClasses.put(configClass, configClass);} 主要就是将 DemoApplication 封装成ConfigurationClass类。然后通过asSourceClass(configClass)解析出原始类DemoApplication.class。之后调用doProcessConfigurationClass方法 protected final SourceClass doProcessConfigurationClass(ConfigurationClass configClass, SourceClass sourceClass)throws IOException {// **1**if (configClass.getMetadata().isAnnotated(Component.class.getName())) {// Recursively process any member (nested) classes firstprocessMemberClasses(configClass, sourceClass);}// Process any PropertySource annotationsfor (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);}}// **2**SetAnnotationAttributes 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// ** 2.1 **SetBeanDefinitionHolder scannedBeanDefinitions this.componentScanParser.parse(componentScan, sourceClass.getMetadata().getClassName());// Check the set of scanned definitions for any further config classes and parse recursively if neededfor (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());}}}}// Process any Import annotations// **3**processImports(configClass, sourceClass, getImports(sourceClass), true);// Process any ImportResource annotationsAnnotationAttributes 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);}}// Process individual Bean methods// **4**SetMethodMetadata beanMethods retrieveBeanMethodMetadata(sourceClass);for (MethodMetadata methodMetadata : beanMethods) {configClass.addBeanMethod(new BeanMethod(methodMetadata, configClass));}// Process default methods on interfacesprocessInterfaces(configClass, sourceClass);// Process superclass, if anyif (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 recursereturn sourceClass.getSuperClass();}}// No superclass - processing is completereturn null;} //  **1** 处理内部类。比如我有一个Component的类里面有内部类A且内部类中也有包含Bean、Component、Import的注解那么会继续处理内部类A。 private void processMemberClasses(ConfigurationClass configClass, SourceClass sourceClass) throws IOException {CollectionSourceClass memberClasses sourceClass.getMemberClasses();if (!memberClasses.isEmpty()) {ListSourceClass candidates new ArrayList(memberClasses.size());for (SourceClass memberClass : memberClasses) {if (ConfigurationClassUtils.isConfigurationCandidate(memberClass.getMetadata()) !memberClass.getMetadata().getClassName().equals(configClass.getMetadata().getClassName())) {candidates.add(memberClass);}}OrderComparator.sort(candidates);for (SourceClass candidate : candidates) {if (this.importStack.contains(configClass)) {this.problemReporter.error(new CircularImportProblem(configClass, this.importStack));}else {this.importStack.push(configClass);try {processConfigurationClass(candidate.asConfigClass(configClass));}finally {this.importStack.pop();}}}}} 在处理内部类中会继续调用processConfigurationClass方法。此时的入参会将内部类A封装成ConfigurationClass类。 //  **2** 处理Component中包含ComponentScans注解的去扫描其他Component对象并直接注册成Bean。在  //  ** 2.1 ** 方法中实现。 //  **3** 处理Import注解。该方法会将Import分为三类。一类是ImportSelector例如EnableAutoConfiguration中的AutoConfigurationImportSelector。第二类是ImportBeanDefinitionRegistrar。第三类就当作Component继续处理。代码如下 private void processImports(ConfigurationClass configClass, SourceClass currentSourceClass,CollectionSourceClass importCandidates, boolean checkForCircularImports) {if (importCandidates.isEmpty()) {return;}if (checkForCircularImports isChainedImportOnStack(configClass)) {this.problemReporter.error(new CircularImportProblem(configClass, this.importStack));}else {this.importStack.push(configClass);try {for (SourceClass candidate : importCandidates) {if (candidate.isAssignable(ImportSelector.class)) {// Candidate class is an ImportSelector - delegate to it to determine importsClass? candidateClass candidate.loadClass();ImportSelector selector BeanUtils.instantiateClass(candidateClass, ImportSelector.class);ParserStrategyUtils.invokeAwareMethods(selector, this.environment, this.resourceLoader, this.registry);if (selector instanceof DeferredImportSelector) {this.deferredImportSelectorHandler.handle(configClass, (DeferredImportSelector) selector);}else {String[] importClassNames selector.selectImports(currentSourceClass.getMetadata());CollectionSourceClass importSourceClasses asSourceClasses(importClassNames);processImports(configClass, currentSourceClass, importSourceClasses, false);}}else if (candidate.isAssignable(ImportBeanDefinitionRegistrar.class)) {// Candidate class is an ImportBeanDefinitionRegistrar -// delegate to it to register additional bean definitionsClass? candidateClass candidate.loadClass();ImportBeanDefinitionRegistrar registrar BeanUtils.instantiateClass(candidateClass, ImportBeanDefinitionRegistrar.class);ParserStrategyUtils.invokeAwareMethods(registrar, this.environment, this.resourceLoader, this.registry);configClass.addImportBeanDefinitionRegistrar(registrar, currentSourceClass.getMetadata());}else {// Candidate class not an ImportSelector or ImportBeanDefinitionRegistrar -// process it as an Configuration classthis.importStack.registerImport(currentSourceClass.getMetadata(), candidate.getMetadata().getClassName());processConfigurationClass(candidate.asConfigClass(configClass));}}}catch (BeanDefinitionStoreException ex) {throw ex;}catch (Throwable ex) {throw new BeanDefinitionStoreException(Failed to process import candidates for configuration class [ configClass.getMetadata().getClassName() ], ex);}finally {this.importStack.pop();}}} //  **4** 处理类中带Bean的方法。SetMethodMetadata beanMethods retrieveBeanMethodMetadata(sourceClass);方法获取每个方法中带有Bean注解的方法。 private SetMethodMetadata retrieveBeanMethodMetadata(SourceClass sourceClass) {AnnotationMetadata original sourceClass.getMetadata();SetMethodMetadata beanMethods original.getAnnotatedMethods(Bean.class.getName());..............} 并且加入到之前封装的configClass的beanMethod方法中 SetMethodMetadata beanMethods retrieveBeanMethodMetadata(sourceClass);for (MethodMetadata methodMetadata : beanMethods) {configClass.addBeanMethod(new BeanMethod(methodMetadata, configClass));} 至此刚才的processConfigBeanDefinitions(registry);方法的parse方法就完事了。把上面的代码站下来。 SetBeanDefinitionHolder candidates new LinkedHashSet(configCandidates);SetConfigurationClass alreadyParsed new HashSet(configCandidates.size());do {parser.parse(candidates);parser.validate();SetConfigurationClass configClasses new LinkedHashSet(parser.getConfigurationClasses());configClasses.removeAll(alreadyParsed);// Read the model and create bean definitions based on its contentif (this.reader null) {this.reader new ConfigurationClassBeanDefinitionReader(registry, this.sourceExtractor, this.resourceLoader, this.environment,this.importBeanNameGenerator, parser.getImportRegistry());}this.reader.loadBeanDefinitions(configClasses); 执行完 parser.parse(candidates) 此时Spring容器中装载的Bean有 DemoApplication 扫描下的所有Component注解的类以及该类中包含ComponentScan路径下带有Component注解的类。至于内部类和Import中的第二类ImportBeanDefinitionRegistrar以及BeanMethod还没有装载。 继续执行this.reader.loadBeanDefinitions(configClasses); public void loadBeanDefinitions(SetConfigurationClass configurationModel) {TrackedConditionEvaluator trackedConditionEvaluator new TrackedConditionEvaluator();for (ConfigurationClass configClass : configurationModel) {loadBeanDefinitionsForConfigurationClass(configClass, trackedConditionEvaluator);}}private void loadBeanDefinitionsForConfigurationClass(ConfigurationClass configClass, TrackedConditionEvaluator trackedConditionEvaluator) {// 1if (trackedConditionEvaluator.shouldSkip(configClass)) {String beanName configClass.getBeanName();if (StringUtils.hasLength(beanName) this.registry.containsBeanDefinition(beanName)) {this.registry.removeBeanDefinition(beanName);}this.importRegistry.removeImportingClass(configClass.getMetadata().getClassName());return;}// 2if (configClass.isImported()) {registerBeanDefinitionForImportedConfigurationClass(configClass);}// 3for (BeanMethod beanMethod : configClass.getBeanMethods()) {loadBeanDefinitionsForBeanMethod(beanMethod);}loadBeanDefinitionsFromImportedResources(configClass.getImportedResources());// 4loadBeanDefinitionsFromRegistrars(configClass.getImportBeanDefinitionRegistrars());} //1判断之前生成的configclass 是否符合注入条件就是判断包含的Conditional注解。如果不符合直接return //2判断是否为内部类如果是且带Component就注入。比如 A 类中有内部类B且类B也有Component注解那么此时Spring容器才会将B注入。 //3将之前类中包含Bean的method方法注入Spring容器中当作Bean对象。 //4注入实现ImportBeanDefinitionRegistrar接口的类比如aop的AspectJAutoProxyRegistrar。 【总结】 1、执行完 parser.parse(candidates) 此时Spring容器中装载的Bean有 DemoApplication 扫描下的所有Component注解的类以及该类中包含ComponentScan路径下带有Component注解的类。 2、注入内部类 3、注入Bean方法 4、注入实现ImportBeanDefinitionRegistrar接口的类
http://www.dnsts.com.cn/news/110942.html

相关文章:

  • 韩国时尚网站欣赏深圳网站建设推广平台
  • 你买域名我送网站免费技能培训在哪里报名
  • 东莞外贸网站建设哪家好苏州做网站优化公司哪家好
  • 饰品做商城网站模式金泉网做网站
  • 忘记网站后台账号wordpress cart插件
  • 定制网站本地企业告别厅北京告别厅
  • 唐山市建设局网站网站产品 模块
  • 网站宣传策略国内顶尖网站设计公司
  • 淘客怎么做网站单页网站规划网站建设报价表
  • 网校网站建设企业app商城开发网站建设
  • 做公寓酒店跟网站合作有什么技巧有什么网站做生鲜配送的
  • 天津网站建设是什么做网站公司哪个比较好
  • 南京做南京华美整容网站wordpress漫画主题
  • 新能源网站建设哪家好优化网址
  • 南宁网站建设服务台商网站建设公司黄页
  • 招远网站建设公司地址关于网站建设的电话销售话术
  • 数据库网站开发教程友情链接检索数据分析
  • 网站流量报表佛山房地产新闻
  • 电商网站开发系统架构电商运营培训学费多少
  • 受雇去建设网站类网站东莞网站建设方案维护
  • 梧州单身相亲网站网站建设免费建站源代码
  • 做网站通过什么挣钱静态企业网站模板下载
  • 中小企业网站建设框架建什么类型的网站访问量比较大
  • 网站做标题有用吗wordpress小型论坛插件
  • 网站建设项目前分析重庆建设工程监督管理局网站
  • 饰品网站模板装潢设计可以考二建吗
  • 成都企业网站制作重庆网站制作有哪些
  • 中国互联网站建设中心wordpress启动插件出错
  • 做wd网站实训报告总结合川网站建设
  • 以橙色为主的网站网络管理软件app