zoukankan      html  css  js  c++  java
  • Spring注解开发之@Configuration解析

    简单看一下Spring容器创建时,如何解析@Configuration配置类。
    此处以SpringBoot2.1.8版本新建的一个简单HelloWorld Web项目为例学习相关源码。
    大致路径如下:

    1. 创建容器时(构造方法或者父类的构造方法中)会创建一个AnnotatedBeanDefinitionReader,在其初始化的时候会调用AnnotationConfigUtils.registerAnnotationConfigProcessors(this.registry)方法为容器注册一些内部的组件。
      ConfigurationClassPostProcessor就是在此处注册。
    2. ConfigurationClassPostProcessor根据源码可以看出其实现了BeanDefinitionRegistryPostProcessor接口(该接口实现了BeanFactoryPostProcessor接口)。主要有两个方法postProcessBeanFactory(后执行,仅加了@Configuration注解的配置类会创建代理类CGLIB)和postProcessBeanDefinitionRegistry,两个方法中都有这一段逻辑:processConfigBeanDefinitions(registry);在此方法中实例化了一个ConfigurationClassParser
    3. ConfigurationClassParser类的parse方法正式处理我们的@Configuration配置类

    从启动类开始:

    SpringApplication.run(PracticeApplication.class, args);
    ------->进入run方法
    SpringApplication  308行
    context = createApplicationContext();
    

    由于该项目添加了Web模块,所以创建的为AnnotationConfigServletWebServerApplicationContext;
    看一下构造函数:

    public AnnotationConfigServletWebServerApplicationContext() {
    		this.reader = new AnnotatedBeanDefinitionReader(this);
    		this.scanner = new ClassPathBeanDefinitionScanner(this);
    	}
    

    进入AnnotatedBeanDefinitionReader构造函数:

    public AnnotatedBeanDefinitionReader(BeanDefinitionRegistry registry) {
    		this(registry, getOrCreateEnvironment(registry));
    	}
    最终调用到
    AnnotationConfigUtils.registerAnnotationConfigProcessors(this.registry);
    

    AnnotationConfigUtils

    来看一下AnnotationConfigUtils的该方法做了什么,取出默认的DefaultListableBeanFactory ,为其注册相关组件。组件org.springframework.context.annotation.internalConfigurationAnnotationProcessor=ConfigurationClassPostProcessor就是在此处注册的,还有其他的一些组件。

    
    public static final String CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME =
    			"org.springframework.context.annotation.internalConfigurationAnnotationProcessor";
    			.....
    public static Set<BeanDefinitionHolder> registerAnnotationConfigProcessors(
    			BeanDefinitionRegistry registry, @Nullable Object source) {
    //获取DefaultListableBeanFactory 
    		DefaultListableBeanFactory beanFactory = unwrapDefaultListableBeanFactory(registry);
     .......
    		Set<BeanDefinitionHolder> beanDefs = new LinkedHashSet<>(8);
    		//注册org.springframework.context.annotation.internalConfigurationAnnotationProcessor=ConfigurationClassPostProcessor
    		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));
    		}
       .......
    		return beanDefs;
    	}
    

    ConfigurationClassPostProcessor

    看一下简单类图和源码
    在这里插入图片描述

    public class ConfigurationClassPostProcessor implements BeanDefinitionRegistryPostProcessor,
    		PriorityOrdered, ResourceLoaderAware, BeanClassLoaderAware, EnvironmentAware {
    		...
    	}
    
    public interface BeanDefinitionRegistryPostProcessor extends BeanFactoryPostProcessor {
    ...
    }
    

    以上可以看出,ConfigurationClassPostProcessor 实现了BeanDefinitionRegistryPostProcessor接口(该接口继承自BeanFactoryPostProcessor),该接口继承自BeanFactoryPostProcessor 。这样在容器创建刷新时将会调用ConfigurationClassPostProcessor 的postProcessBeanFactory(后执行,仅加了@Configuration注解的配置类会创建代理类CGLIB)和postProcessBeanDefinitionRegistry方法。

    // Invoke factory processors registered as beans in the context.
    invokeBeanFactoryPostProcessors(beanFactory);
    

    实际调用在这

    	public void processConfigBeanDefinitions (BeanDefinitionRegistry registry) {
    		List<BeanDefinitionHolder> configCandidates = new ArrayList<>();
    		//此处获取的candidateNames:-->register的配置类名和在初始化时注册的Spring内部处理类
    		String[] candidateNames = registry.getBeanDefinitionNames();
    		
    		//for循环的目的是找出未被处理过的加了@Configuration等注解的bean
    		for (String beanName : candidateNames) {
    			BeanDefinition beanDef = registry.getBeanDefinition(beanName);
    
    			//如果beanDef是full或者lite则表明是已经被处理过的
    			// full为加了@Configuration注解的,
    			// lite为未加@Configuration,@Component、@ComponentScan、@Import、@ImportResource和方法上是否有@Bean注解
    			if (ConfigurationClassUtils.isFullConfigurationClass(beanDef) || ConfigurationClassUtils.isLiteConfigurationClass(beanDef)) {
    				if (logger.isDebugEnabled()) {
    					logger.debug("Bean definition has already been processed as a configuration class: " + beanDef);
    				}
    
    			} else if (ConfigurationClassUtils.checkConfigurationClassCandidate(beanDef, this.metadataReaderFactory)) {
    				//将配置类添加到集合,以便下方处理
    				configCandidates.add(new BeanDefinitionHolder(beanDef, beanName));
    			}
    		}
    
    		//如果没有找到配置类,则立即返回
    		if (configCandidates.isEmpty()) {
    			return;
    		}
    		//根据优先级排序
    		// Sort by previously determined @Order value, if applicable
    		configCandidates.sort((bd1, bd2) -> {
    			int i1 = ConfigurationClassUtils.getOrder(bd1.getBeanDefinition());
    			int i2 = ConfigurationClassUtils.getOrder(bd2.getBeanDefinition());
    			return Integer.compare(i1, i2);
    		});
    
    		// Detect any custom bean name generation strategy supplied through the enclosing application context
    		//设置BeanName的生成策略
    		SingletonBeanRegistry sbr = null;
    		if (registry instanceof SingletonBeanRegistry) {
    			sbr = (SingletonBeanRegistry) registry;
    			if (!this.localBeanNameGeneratorSet) {
    				BeanNameGenerator generator = (BeanNameGenerator) sbr.getSingleton(CONFIGURATION_BEAN_NAME_GENERATOR);
    				if (generator != null) {
    					this.componentScanBeanNameGenerator = generator;
    					this.importBeanNameGenerator = generator;
    				}
    			}
    		}
    
    		if (this.environment == null) {
    			this.environment = new StandardEnvironment();
    		}
    
    		// Parse each @Configuration class
    		/*
    		 *  新建一个ConfigurationClassParser去解析每个加了@Configuration的类,registry=DefaultListableBeanFactory
    		 */
    		ConfigurationClassParser parser = new ConfigurationClassParser(this.metadataReaderFactory,
    				this.problemReporter, this.environment, this.resourceLoader, this.componentScanBeanNameGenerator,
    				registry);
    
    		Set<BeanDefinitionHolder> candidates = new LinkedHashSet<>(configCandidates);
    		Set<ConfigurationClass> alreadyParsed = new HashSet<>(configCandidates.size());
    
    		//处理候选的配置类或者扫描到的类
    		do {
                //实际处理逻辑
    			parser.parse(candidates);
          
                ************************
    

    最终会调用到:
    在这里插入图片描述

    源码如下:

    	@Nullable
    	protected final SourceClass doProcessConfigurationClass(ConfigurationClass configClass, SourceClass sourceClass)
    			throws IOException {
           //处理@Component注解
    		if (configClass.getMetadata().isAnnotated(Component.class.getName())) {
    			// Recursively process any member (nested) classes first
    			processMemberClasses(configClass, sourceClass);
    		}
           //处理 @PropertySource注解
    		// Process any @PropertySource annotations
    		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注解
    		// Process any @ComponentScan annotations
    		Set<AnnotationAttributes> 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<BeanDefinitionHolder> 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注解
    		// Process any @Import annotations
    		processImports(configClass, sourceClass, getImports(sourceClass), true);
    
    		// Process any @ImportResource annotations
    		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的方法
    		// Process individual @Bean methods
    		Set<MethodMetadata> beanMethods = retrieveBeanMethodMetadata(sourceClass);
    		for (MethodMetadata methodMetadata : beanMethods) {
    			configClass.addBeanMethod(new BeanMethod(methodMetadata, configClass));
    		}
            //处理接口的默认方法
    		// Process default methods on interfaces
    		processInterfaces(configClass, sourceClass);
    
    		// Process superclass, if any
    		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();
    			}
    		}
    
    		// No superclass -> processing is complete
    		return null;
    	}
    
  • 相关阅读:
    Oracle 11g db_ultra_safe参数
    How To Configure NTP On Windows 2008 R2 (zt)
    Brocade光纤交换机密码重置 (ZT)
    perl如何访问Oracle (ZT)
    Nagios check_nrpe : Socket timeout after 10 seconds
    oracle10g单机使用ASM存储数据
    Xmanager无法连接Solaris10 (ZT)
    Solaris10配置iscsi initiator
    oracle 11g dataguard 创建过程
    Nagios check_procs pst3 报错
  • 原文地址:https://www.cnblogs.com/demo-alen/p/13547216.html
Copyright © 2011-2022 走看看