Spring源码分析:@Configuration原理

摘要:
{@OverridepublicDoggetObject()throwsException{returnnewDog();System.out.println(applicationContext.getBean(“&refresh();this.reader=newAnnotatedBeanDefinitionReader(this);this.registry=registry;

1.本文基于spring5.3.x。

环境搭建

bean:

public class Cat {
}

public class Dog {
}

public class DogFactoryBean implements FactoryBean<Dog> {
	@Override
	public Dog getObject() throws Exception {
		return new Dog();
	}

	@Override
	public Class<?> getObjectType() {
		return Dog.class;
	}
}

public class Person {
}

@Service
public class HelloService {
}

配置类:

@Configuration
@Import(Cat.class)
@ComponentScan("com.wj")
public class MyConfiguration {

	@Bean
	Person person(){
		return new Person();
	}

	@Bean
	DogFactoryBean dogFactoryBean() {
		return new DogFactoryBean();
	}
}

@Configuration
public class MyConfiguration2 {

	@Bean
	Person person2(){
		return new Person();
	}

}

启动类·:

public class Main {
	public static void main(String[] args) {
		ApplicationContext applicationContext = new AnnotationConfigApplicationContext(MyConfiguration.class);
		System.out.println(Arrays.toString(applicationContext.getBeanDefinitionNames()));
		System.out.println(applicationContext.getBean("dogFactoryBean"));
		System.out.println(applicationContext.getBean("&dogFactoryBean"));
	}
}

包结构如下:

image-20211202163431255

运行结果:

image-20211202163350260

断点调试

直接调用new AnnotationConfigApplicationContext(MyConfiguration.class);,会进入该类的构造方法。

	public AnnotationConfigApplicationContext(Class<?>... componentClasses) {
		this();
		register(componentClasses);
		refresh();
	}

this()

this方法表面上东西少,实际上有一个很重要的步骤

	public AnnotationConfigApplicationContext() {
		StartupStep createAnnotatedBeanDefReader = this.getApplicationStartup().start("spring.context.annotated-bean-reader.create");
		this.reader = new AnnotatedBeanDefinitionReader(this);
		createAnnotatedBeanDefReader.end();
		this.scanner = new ClassPathBeanDefinitionScanner(this);
	}

这里先创建一个AnnotatedBeanDefinitionReader,走到如下方法:

	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(this.registry),内部又会调用它的重载方法如下:

	//在给定注册表中注册所有相关的注释后置处理器
	public static Set<BeanDefinitionHolder> registerAnnotationConfigProcessors(
			BeanDefinitionRegistry registry, @Nullable Object source) {
		//获取到DefaultListableBeanFactory,便于注册bean定义信息
		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());
			}
		}
		//创建BeanDefinitionHolder集合
		Set<BeanDefinitionHolder> beanDefs = new LinkedHashSet<>(8);
		//注册ConfigurationClassPostProcessor  ==> BeanDefinitionRegistryPostProcessor ==> BeanFactoryPostProcessor
		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));
		}
		//注册AutowiredAnnotationBeanPostProcessor
		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,如果有jsr250,会注册CommonAnnotationBeanPostProcessor,用于解析@Resource、@PostConstruct这些注解
		// Check for JSR-250 support, and if present add the CommonAnnotationBeanPostProcessor.
		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
		// Check for JPA support, and if present add the 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));
		}
		//注册EventListenerMethodProcessor,用于解析@EventListener标注的方法
		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));
		}
		//注册DefaultEventListenerFactory
		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中注册了ConfigurationClassPostProcessor,后面整个配置类的解析都由它来完成。

image-20211202170144725

register(componentClasses)

this()方法结束后,调用register(componentClasses)

	@Override
	public void register(Class<?>... componentClasses) {
		Assert.notEmpty(componentClasses, "At least one component class must be specified");
		StartupStep registerComponentClass = this.getApplicationStartup().start("spring.context.component-classes.register")
				.tag("classes", () -> Arrays.toString(componentClasses));
		this.reader.register(componentClasses);
		registerComponentClass.end();
	}

这里会调用this.reader.register(componentClasses),这里的reader就是上一步this()中创建的AnnotatedBeanDefinitionReader,该类的register方法最后会走到doRegisterBean方法:

	private <T> void doRegisterBean(Class<T> beanClass, @Nullable String name,
			@Nullable Class<? extends Annotation>[] qualifiers, @Nullable Supplier<T> supplier,
			@Nullable BeanDefinitionCustomizer[] customizers) {
		//创建AnnotatedGenericBeanDefinition,内部封装了beanClass(MyConfiguration类)的Class信息和该类的相关注解元信息
		AnnotatedGenericBeanDefinition abd = new AnnotatedGenericBeanDefinition(beanClass);
		if (this.conditionEvaluator.shouldSkip(abd.getMetadata())) {
			return;
		}

		abd.setInstanceSupplier(supplier);
                //获取并设置Scope信息
		ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(abd);
		abd.setScope(scopeMetadata.getScopeName());
                //生成bean名字
		String beanName = (name != null ? name : this.beanNameGenerator.generateBeanName(abd, this.registry));
		//获取配置类上的@Lazy、@Primary、@DependsOn、@Role、@Description相关信息并设置到定义信息中
		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));
				}
			}
		}
		if (customizers != null) {
			for (BeanDefinitionCustomizer customizer : customizers) {
				customizer.customize(abd);
			}
		}
		//创建BeanDefinitionHolder
		BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(abd, beanName);
		definitionHolder = AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);
                //将定义信息注册到registry中
		BeanDefinitionReaderUtils.registerBeanDefinition(definitionHolder, this.registry);
	}

这一步走完后,DefaultListableBeanFactory中注册了如下五个bean的定义信息:

image-20211202172244406

refresh()

接下来进入到经典的refresh方法:

@Override
	public void refresh() throws BeansException, IllegalStateException {
		synchronized (this.startupShutdownMonitor) {
			StartupStep contextRefresh = this.applicationStartup.start("spring.context.refresh");

			// Prepare this context for refreshing.
			//准备刷新
			prepareRefresh();

			// Tell the subclass to refresh the internal bean factory.
			//获取刷新好的bean工厂
			ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

			// Prepare the bean factory for use in this context.
			//注册环境信息等,增加postProcessor,增加一些spring内置的必要的组件
			prepareBeanFactory(beanFactory);

			try {
				// Allows post-processing of the bean factory in context subclasses.
				postProcessBeanFactory(beanFactory);

				StartupStep beanPostProcess = this.applicationStartup.start("spring.context.beans.post-process");
				// Invoke factory processors registered as beans in the context.
				//执行bean工厂的后置增强
				invokeBeanFactoryPostProcessors(beanFactory);

				// Register bean processors that intercept bean creation.
				//注册所有的BeanPostProcessor
				registerBeanPostProcessors(beanFactory);
				beanPostProcess.end();

				// Initialize message source for this context.
				initMessageSource();

				// Initialize event multicaster for this context.
				initApplicationEventMulticaster();

				// Initialize other special beans in specific context subclasses.
				onRefresh();

				// Check for listener beans and register them.
				//注册监听器
				registerListeners();

				// Instantiate all remaining (non-lazy-init) singletons.
				//完成BeanFactor的初始化(工厂里面所有的组件都准备好)
				finishBeanFactoryInitialization(beanFactory);

				// Last step: publish corresponding event.
				finishRefresh();
			}
			//后面省略

invokeBeanFactoryPostProcessors

refresh方法中有重要一步,invokeBeanFactoryPostProcessors,该方法会执行所有的BeanFactoryPostProcessorBeanDefinitionRegistryPostProcessor

调用:PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, getBeanFactoryPostProcessors());

image-20211202173512412

这里先执行BeanDefinitionRegistryPostProcessor,默认情况下只有先前导入的ConfigurationClassPostProcessor.

调用postProcessBeanDefinitionRegistry方法:

image-20211202173744249

执行processConfigBeanDefinitions方法:

第一步:拿到beanDefinitionRegistry中所有的配置类:

image-20211202174027874

第二步:创建importBean和componentScan导入容器的名字生成器

image-20211202174401934

第三步:解析每一个配置类

解析配置类

		//创建配置类的解析器
		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 {
			StartupStep processConfig = this.applicationStartup.start("spring.context.config-classes.parse");
                        //执行配置类的解析器的parse方法
			parser.parse(candidates);
			parser.validate();

			Set<ConfigurationClass> configClasses = new LinkedHashSet<>(parser.getConfigurationClasses());
			configClasses.removeAll(alreadyParsed);

			// Read the model and create bean definitions based on its content
			if (this.reader == null) {
				this.reader = new ConfigurationClassBeanDefinitionReader(
						registry, this.sourceExtractor, this.resourceLoader, this.environment,
						this.importBeanNameGenerator, parser.getImportRegistry());
			}
			this.reader.loadBeanDefinitions(configClasses);
			alreadyParsed.addAll(configClasses);
			processConfig.tag("classCount", () -> String.valueOf(configClasses.size())).end();

			candidates.clear();
			if (registry.getBeanDefinitionCount() > candidateNames.length) {
				String[] newCandidateNames = registry.getBeanDefinitionNames();
				Set<String> oldCandidateNames = new HashSet<>(Arrays.asList(candidateNames));
				Set<String> alreadyParsedClasses = new HashSet<>();
				for (ConfigurationClass configurationClass : alreadyParsed) {
					alreadyParsedClasses.add(configurationClass.getMetadata().getClassName());
				}
				for (String candidateName : newCandidateNames) {
					if (!oldCandidateNames.contains(candidateName)) {
						BeanDefinition bd = registry.getBeanDefinition(candidateName);
						if (ConfigurationClassUtils.checkConfigurationClassCandidate(bd, this.metadataReaderFactory) &&
								!alreadyParsedClasses.contains(bd.getBeanClassName())) {
							candidates.add(new BeanDefinitionHolder(bd, candidateName));
						}
					}
				}
				candidateNames = newCandidateNames;
			}
		}
		while (!candidates.isEmpty());

		// Register the ImportRegistry as a bean in order to support ImportAware @Configuration classes
		if (sbr != null && !sbr.containsSingleton(IMPORT_REGISTRY_BEAN_NAME)) {
			sbr.registerSingleton(IMPORT_REGISTRY_BEAN_NAME, parser.getImportRegistry());
		}

		if (this.metadataReaderFactory instanceof CachingMetadataReaderFactory) {
			// Clear cache in externally provided MetadataReaderFactory; this is a no-op
			// for a shared cache since it'll be cleared by the ApplicationContext.
			((CachingMetadataReaderFactory) this.metadataReaderFactory).clearCache();
		}

parse方法最后会走到processConfigurationClass方法:

image-20211202174923533

执行doProcessConfigurationClass方法:

	@Nullable
	protected final SourceClass doProcessConfigurationClass(
			ConfigurationClass configClass, SourceClass sourceClass, Predicate<String> filter)
			throws IOException {

		if (configClass.getMetadata().isAnnotated(Component.class.getName())) {
			// Recursively process any member (nested) classes first
			processMemberClasses(configClass, sourceClass, filter);
		}

		// Process any @PropertySource annotations 解析@PropertySource
		//解析PropertySource这里省略

		// Process any @ComponentScan annotations 解析@ComponentScan
		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());
					}
				}
			}
		}

		// Process any @Import annotations
		processImports(configClass, sourceClass, getImports(sourceClass), filter, 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);
			}
		}

		// Process individual @Bean methods
                //解析@Bean方法
		Set<MethodMetadata> beanMethods = retrieveBeanMethodMetadata(sourceClass);
                //将@Bean方法的信息保存到ConfigurationClass中
		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;
	}
解析@ComponentScan注解

因为MyConfiguration注解上标注了@ComponentScan,所以该类上面的@ComponentScan会被解析,解析类是ComponentScanAnnotationParser,执行parse方法:

	public Set<BeanDefinitionHolder> parse(AnnotationAttributes componentScan, final String declaringClass) {
                //创建可以扫描类路径bean定义信息的扫描器
		ClassPathBeanDefinitionScanner scanner = new ClassPathBeanDefinitionScanner(this.registry,
				componentScan.getBoolean("useDefaultFilters"), this.environment, this.resourceLoader);
		//向scanner中设置一系列属性:BeanNameGenerator、ScopedProxyMode、resourcePattern、includeFilters、excludeFilters等
        ....
		
                //设置扫描的包名  
		Set<String> basePackages = new LinkedHashSet<>();
		String[] basePackagesArray = componentScan.getStringArray("basePackages");
		for (String pkg : basePackagesArray) {
			String[] tokenized = StringUtils.tokenizeToStringArray(this.environment.resolvePlaceholders(pkg),
					ConfigurableApplicationContext.CONFIG_LOCATION_DELIMITERS);
			Collections.addAll(basePackages, tokenized);
		}
		for (Class<?> clazz : componentScan.getClassArray("basePackageClasses")) {
			basePackages.add(ClassUtils.getPackageName(clazz));
		}
		if (basePackages.isEmpty()) {
			basePackages.add(ClassUtils.getPackageName(declaringClass));
		}

		scanner.addExcludeFilter(new AbstractTypeHierarchyTraversingFilter(false, false) {
			@Override
			protected boolean matchClassName(String className) {
				return declaringClass.equals(className);
			}
		});
                //执行ClassPathBeanDefinitionScanner的doScan方法
		return scanner.doScan(StringUtils.toStringArray(basePackages));
	}

doScan方法:

	protected Set<BeanDefinitionHolder> doScan(String... basePackages) {
		Assert.notEmpty(basePackages, "At least one base package must be specified");
		Set<BeanDefinitionHolder> beanDefinitions = new LinkedHashSet<>();
		for (String basePackage : basePackages) {
                        //查找所有候选的组件
			Set<BeanDefinition> candidates = findCandidateComponents(basePackage);
			for (BeanDefinition candidate : candidates) {
				ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(candidate);
				candidate.setScope(scopeMetadata.getScopeName());
				String beanName = this.beanNameGenerator.generateBeanName(candidate, this.registry);
				if (candidate instanceof AbstractBeanDefinition) {
					postProcessBeanDefinition((AbstractBeanDefinition) candidate, beanName);
				}
				if (candidate instanceof AnnotatedBeanDefinition) {
                                          //解析配置类上的@Lazy、@Primary、@DependsOn、@Role、@Description的注解信息
					AnnotationConfigUtils.processCommonDefinitionAnnotations((AnnotatedBeanDefinition) candidate);
				}
                                //检查定义信息是否已经在registry中存在
				if (checkCandidate(beanName, candidate)) {
                                        //注册上面扫描到的所有bean定义信息到registry中
					BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(candidate, beanName);
					definitionHolder =
							AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);
					beanDefinitions.add(definitionHolder);
					registerBeanDefinition(definitionHolder, this.registry);
				}
			}
		}
		return beanDefinitions;
	}

findCandidateComponents方法内部会调用scanCandidateComponents方法,该方法会找到类路径下的所有组件:我这里最后找到了两个组件MyCongfiguration2HelloService

image-20211202181148101

当前配置类的@ComponentScan注解扫描完后,会用循环parse解析上一步找到的所有配置类,解析的步骤与上面一样。

image-20211203092847253
解析@Import注解

上面@ComponentScan解析结束后,紧接着调用processImports方法。

	private void processImports(ConfigurationClass configClass, SourceClass currentSourceClass,
			Collection<SourceClass> importCandidates, Predicate<String> exclusionFilter,
			boolean checkForCircularImports) {
		//判断@Import是否导入了组件,如果没有直接结束方法
		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) {
                                        //判断是否是ImportSelector类
					if (candidate.isAssignable(ImportSelector.class)) {
						// Candidate class is an ImportSelector -> delegate to it to determine imports
						Class<?> candidateClass = candidate.loadClass();
                                                //实例化ImportSelector
						ImportSelector selector = ParserStrategyUtils.instantiateClass(candidateClass, ImportSelector.class,
								this.environment, this.resourceLoader, this.registry);
						Predicate<String> selectorFilter = selector.getExclusionFilter();
						if (selectorFilter != null) {
							exclusionFilter = exclusionFilter.or(selectorFilter);
						}
                                                //判断ImportSelector是否是DeferredImportSelector
						if (selector instanceof DeferredImportSelector) {
							this.deferredImportSelectorHandler.handle(configClass, (DeferredImportSelector) selector);
						}
						else {
                                                        //调用ImportSelector的selectImports方法
							String[] importClassNames = selector.selectImports(currentSourceClass.getMetadata());
							Collection<SourceClass> importSourceClasses = asSourceClasses(importClassNames, exclusionFilter);
                                                      //递归解析需要Import的bean
							processImports(configClass, currentSourceClass, importSourceClasses, exclusionFilter, false);
						}
					}
                                        //判断是否实现了ImportBeanDefinitionRegistrar接口
					else if (candidate.isAssignable(ImportBeanDefinitionRegistrar.class)) {
						// Candidate class is an ImportBeanDefinitionRegistrar ->
						// delegate to it to register additional bean definitions
						Class<?> candidateClass = candidate.loadClass();
                                                //实例化ImportBeanDefinitionRegistrar
						ImportBeanDefinitionRegistrar registrar =
								ParserStrategyUtils.instantiateClass(candidateClass, ImportBeanDefinitionRegistrar.class,
										this.environment, this.resourceLoader, this.registry);
                                                 //将ImportBeanDefinitionRegistrar信息保存到importBeanDefinitionRegistrars字段中
						configClass.addImportBeanDefinitionRegistrar(registrar, currentSourceClass.getMetadata());
					}
					else {
						// Candidate class not an ImportSelector or ImportBeanDefinitionRegistrar ->
						// process it as an @Configuration class
						this.importStack.registerImport(
								currentSourceClass.getMetadata(), candidate.getMetadata().getClassName());
                                                //调用processConfigurationClass进行解析该类(这里步骤跟上面解析配置类一样)
						processConfigurationClass(candidate.asConfigClass(configClass), exclusionFilter);
					}
				}
			}
			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();
			}
		}
	}

注意,这里解析import注解,并没有直接将要import的组件注册到registry中。

解析@Bean注解

解析@ImportResource这里跳过,下面就是解析@Bean注解,调用了retrieveBeanMethodMetadata方法:

	private Set<MethodMetadata> retrieveBeanMethodMetadata(SourceClass sourceClass) {
		AnnotationMetadata original = sourceClass.getMetadata();
        //获取所有标注了@Bean的方法:底层是获取到该类的所有方法,然后遍历方法判断该方法上是否标注了@Bean注解
		Set<MethodMetadata> beanMethods = original.getAnnotatedMethods(Bean.class.getName());
		if (beanMethods.size() > 1 && original instanceof StandardAnnotationMetadata) {
			// Try reading the class file via ASM for deterministic declaration order...
			// Unfortunately, the JVM's standard reflection returns methods in arbitrary
			// order, even between different runs of the same application on the same JVM.
                        //下面采用ASM方式读取class,以确保方法的声明顺序
			try {
				AnnotationMetadata asm =
						this.metadataReaderFactory.getMetadataReader(original.getClassName()).getAnnotationMetadata();
				Set<MethodMetadata> asmMethods = asm.getAnnotatedMethods(Bean.class.getName());
				if (asmMethods.size() >= beanMethods.size()) {
					Set<MethodMetadata> selectedMethods = new LinkedHashSet<>(asmMethods.size());
					for (MethodMetadata asmMethod : asmMethods) {
						for (MethodMetadata beanMethod : beanMethods) {
							if (beanMethod.getMethodName().equals(asmMethod.getMethodName())) {
								selectedMethods.add(beanMethod);
								break;
							}
						}
					}
					if (selectedMethods.size() == beanMethods.size()) {
						// All reflection-detected methods found in ASM method set -> proceed
						beanMethods = selectedMethods;
					}
				}
			}
			catch (IOException ex) {
				logger.debug("Failed to read class file via ASM for determining @Bean method order", ex);
				// No worries, let's continue with the reflection metadata we started with...
			}
		}
                //返回找到的所有@Bean方法
		return beanMethods;
	}
解析父接口

解析@Bean后,调用processInterfaces方法:

	private void processInterfaces(ConfigurationClass configClass, SourceClass sourceClass) throws IOException {\
                  //获取到该类的父接口
		for (SourceClass ifc : sourceClass.getInterfaces()) {
                        //查找到父接口中的@Bean方法
			Set<MethodMetadata> beanMethods = retrieveBeanMethodMetadata(ifc);
			for (MethodMetadata methodMetadata : beanMethods) {
				if (!methodMetadata.isAbstract()) {
					// A default method or other concrete method on a Java 8+ interface...
                                        //将接口的@Bean方法保存到BeanMethod中
					configClass.addBeanMethod(new BeanMethod(methodMetadata, configClass));
				}
			}
                        //递归解析父接口
			processInterfaces(configClass, ifc);
		}
	}
解析父类

解析父接口后,会解析父类:

		//判断该类是否有父类
		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();
			}
		}

注意这里返回后,仍然在parse的while循环中,并且会将配置类的父类作为配置类解析,并继续往上找父类,直至找到Object类。

加载配置类中所有的bean定义信息:loadBeanDefinitions

解析完配置类后,processConfigBeanDefinitions下面就会加载组件定义信息:

			if (this.reader == null) {
                                //先创建ConfigurationClassBeanDefinitionReader
				this.reader = new ConfigurationClassBeanDefinitionReader(
						registry, this.sourceExtractor, this.resourceLoader, this.environment,
						this.importBeanNameGenerator, parser.getImportRegistry());
			}
			//执行reader的loadBeanDefinitions方法
			this.reader.loadBeanDefinitions(configClasses);

loadBeanDefinitions方法如下:会将上一步解析配置类时候扫描到的所有ConfigurationClass调用loadBeanDefinitionsForConfigurationClass,去加载该类中的定义信息。

public void loadBeanDefinitions(Set<ConfigurationClass> configurationModel) {
   TrackedConditionEvaluator trackedConditionEvaluator = new TrackedConditionEvaluator();
   for (ConfigurationClass configClass : configurationModel) {
      loadBeanDefinitionsForConfigurationClass(configClass, trackedConditionEvaluator);
   }
}

该方法如下:

	private void loadBeanDefinitionsForConfigurationClass(
			ConfigurationClass configClass, TrackedConditionEvaluator trackedConditionEvaluator) {

		if (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;
		}
		//判断当前类是否是被@Import进来的
		if (configClass.isImported()) {
                        //注册当前类
			registerBeanDefinitionForImportedConfigurationClass(configClass);
		}
                //获取配置类中的所有@bean方法
		for (BeanMethod beanMethod : configClass.getBeanMethods()) {
                        //注册BeanMethod(@Bean方法)
			loadBeanDefinitionsForBeanMethod(beanMethod);
		}
		//注册@ImportedResources
		loadBeanDefinitionsFromImportedResources(configClass.getImportedResources());
		loadBeanDefinitionsFromRegistrars(configClass.getImportBeanDefinitionRegistrars());
	}

下面会对这个方法的每一步进行说明。

注册@Import导入的类

执行registerBeanDefinitionForImportedConfigurationClass方法:

	private void registerBeanDefinitionForImportedConfigurationClass(ConfigurationClass configClass) {
		AnnotationMetadata metadata = configClass.getMetadata();
        //创建BeanDefinition
		AnnotatedGenericBeanDefinition configBeanDef = new AnnotatedGenericBeanDefinition(metadata);
		//设置scope信息
		ScopeMetadata scopeMetadata = scopeMetadataResolver.resolveScopeMetadata(configBeanDef);
		configBeanDef.setScope(scopeMetadata.getScopeName());
                //生成bean的名字
		String configBeanName = this.importBeanNameGenerator.generateBeanName(configBeanDef, this.registry);
                //解析配置类上的@Lazy、@Primary、@DependsOn、@Role、@Description的注解信息
		AnnotationConfigUtils.processCommonDefinitionAnnotations(configBeanDef, metadata);
		//创建该类的BeanDefinitionHolder
		BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(configBeanDef, configBeanName);
                //根据ScopedProxyMode生成对应的definitionHolder
		definitionHolder = AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);
                //注册到registry
		this.registry.registerBeanDefinition(definitionHolder.getBeanName(), definitionHolder.getBeanDefinition());
                //设置beanName
		configClass.setBeanName(configBeanName);

		if (logger.isTraceEnabled()) {
			logger.trace("Registered bean definition for imported class '" + configBeanName + "'");
		}
	}
注册@Bean方法

调用loadBeanDefinitionsForBeanMethod方法:

	private void loadBeanDefinitionsForBeanMethod(BeanMethod beanMethod) {
                //获取当前@bean方法的配置类
		ConfigurationClass configClass = beanMethod.getConfigurationClass();
                //获取方法信息
		MethodMetadata metadata = beanMethod.getMetadata();
		String methodName = metadata.getMethodName();

		// Do we need to mark the bean as skipped by its condition?
		if (this.conditionEvaluator.shouldSkip(metadata, ConfigurationPhase.REGISTER_BEAN)) {
			configClass.skippedBeanMethods.add(methodName);
			return;
		}
		if (configClass.skippedBeanMethods.contains(methodName)) {
			return;
		}
		//获取@Bean注解对应的属性值
		AnnotationAttributes bean = AnnotationConfigUtils.attributesFor(metadata, Bean.class);
		Assert.state(bean != null, "No @Bean annotation attributes");

		// Consider name and any aliases
                //获取beanName
		List<String> names = new ArrayList<>(Arrays.asList(bean.getStringArray("name")));
		String beanName = (!names.isEmpty() ? names.remove(0) : methodName);

		// Register aliases even when overridden
                //注册别名
		for (String alias : names) {
			this.registry.registerAlias(beanName, alias);
		}

		// Has this effectively been overridden before (e.g. via XML)?
		if (isOverriddenByExistingDefinition(beanMethod, beanName)) {
			if (beanName.equals(beanMethod.getConfigurationClass().getBeanName())) {
				throw new BeanDefinitionStoreException(beanMethod.getConfigurationClass().getResource().getDescription(),
						beanName, "Bean name derived from @Bean method '" + beanMethod.getMetadata().getMethodName() +
						"' clashes with bean name for containing configuration class; please make those names unique!");
			}
			return;
		}
		//创建beanMethod对应的ConfigurationClassBeanDefinition
		ConfigurationClassBeanDefinition beanDef = new ConfigurationClassBeanDefinition(configClass, metadata, beanName);
		beanDef.setSource(this.sourceExtractor.extractSource(metadata, configClass.getResource()));
		//判断@Bean方法是否是static
		if (metadata.isStatic()) {
			// static @Bean method
			if (configClass.getMetadata() instanceof StandardAnnotationMetadata) {
                                //设置setBeanClass
				beanDef.setBeanClass(((StandardAnnotationMetadata) configClass.getMetadata()).getIntrospectedClass());
			}
			else {
                                //设置setBeanClass
				beanDef.setBeanClassName(configClass.getMetadata().getClassName());
			}
                        //设置UniqueFactoryMethodName
			beanDef.setUniqueFactoryMethodName(methodName);
		}
		else {
			// instance @Bean method
                        //设置FactoryBeanName和UniqueFactoryMethodName
			beanDef.setFactoryBeanName(configClass.getBeanName());
			beanDef.setUniqueFactoryMethodName(methodName);
		}

		if (metadata instanceof StandardMethodMetadata) {
                        //设置需要被处理的方法(即@Bean标注的方法),被保存到factoryMethodToIntrospect字段中
			beanDef.setResolvedFactoryMethod(((StandardMethodMetadata) metadata).getIntrospectedMethod());
		}

		beanDef.setAutowireMode(AbstractBeanDefinition.AUTOWIRE_CONSTRUCTOR);
		beanDef.setAttribute(org.springframework.beans.factory.annotation.RequiredAnnotationBeanPostProcessor.
				SKIP_REQUIRED_CHECK_ATTRIBUTE, Boolean.TRUE);

		AnnotationConfigUtils.processCommonDefinitionAnnotations(beanDef, metadata);

		//........... 中间向bean定义信息中设置autowire、autowireCandidate、initMethod、destroyMethod、Scope省略

		// Replace the original bean definition with the target one, if necessary
		BeanDefinition beanDefToRegister = beanDef;
                //根据ScopedProxyMode的值做相关处理
		if (proxyMode != ScopedProxyMode.NO) {
			BeanDefinitionHolder proxyDef = ScopedProxyCreator.createScopedProxy(
					new BeanDefinitionHolder(beanDef, beanName), this.registry,
					proxyMode == ScopedProxyMode.TARGET_CLASS);
			beanDefToRegister = new ConfigurationClassBeanDefinition(
					(RootBeanDefinition) proxyDef.getBeanDefinition(), configClass, metadata, beanName);
		}

		if (logger.isTraceEnabled()) {
			logger.trace(String.format("Registering bean definition for @Bean method %s.%s()",
					configClass.getMetadata().getClassName(), beanName));
		}
                //注册到registry
		this.registry.registerBeanDefinition(beanName, beanDefToRegister);
	}

执行完后,这里需要注意:

  • @Bean方法被保存到factoryMethodToIntrospect字段中了

  • 静态的@Bean方法没有设置FactoryBeanName字段

  • 无论静态方法还是实例方法,都会调用setUniqueFactoryMethodName

    public void setUniqueFactoryMethodName(String name) {
       Assert.hasText(name, "Factory method name must not be empty");
       //设置factoryMethodName
       setFactoryMethodName(name);
       //设置isFactoryMethodUnique
       this.isFactoryMethodUnique = true;
    }
    
从@ImportedResources中加载bean定义信息

方法比较简单:

	private void loadBeanDefinitionsFromImportedResources(
			Map<String, Class<? extends BeanDefinitionReader>> importedResources) {

		Map<Class<?>, BeanDefinitionReader> readerInstanceCache = new HashMap<>();
		//遍历importedResources
		importedResources.forEach((resource, readerClass) -> {
			// Default reader selection necessary?
			if (BeanDefinitionReader.class == readerClass) {
                                //判断导入的配置文件是否是.groovy结尾的
				if (StringUtils.endsWithIgnoreCase(resource, ".groovy")) {
					// When clearly asking for Groovy, that's what they'll get...
                                        //设置GroovyBeanDefinitionReader
					readerClass = GroovyBeanDefinitionReader.class;
				}
                                //是否支持xml
				else if (shouldIgnoreXml) {
					throw new UnsupportedOperationException("XML support disabled");
				}
				else {
                                        //设置XmlBeanDefinitionReader
					// Primarily ".xml" files but for any other extension as well
					readerClass = XmlBeanDefinitionReader.class;
				}
			}
			//从缓存中获取BeanDefinitionReader
			BeanDefinitionReader reader = readerInstanceCache.get(readerClass);
                        //获取不到则创建一个reader
			if (reader == null) {
				try {
					// Instantiate the specified BeanDefinitionReader
					reader = readerClass.getConstructor(BeanDefinitionRegistry.class).newInstance(this.registry);
					// Delegate the current ResourceLoader to it if possible
					if (reader instanceof AbstractBeanDefinitionReader) {
						AbstractBeanDefinitionReader abdr = ((AbstractBeanDefinitionReader) reader);
						abdr.setResourceLoader(this.resourceLoader);
						abdr.setEnvironment(this.environment);
					}
					readerInstanceCache.put(readerClass, reader);
				}
				catch (Throwable ex) {
					throw new IllegalStateException(
							"Could not instantiate BeanDefinitionReader class [" + readerClass.getName() + "]");
				}
			}
			//调用reader的loadBeanDefinitions加载bean定义信息(如果是xml配置文件,这里就会解析xml)
			// TODO SPR-6310: qualify relative path locations as done in AbstractContextLoader.modifyLocations
			reader.loadBeanDefinitions(resource);
		});
	}
执行ImportBeanDefinitionRegistrar

加载完ImportedResources后,紧接着调用loadBeanDefinitionsFromRegistrars方法:

比较简单,for循环执行所有ImportBeanDefinitionRegistrarregisterBeanDefinitions方法。

	private void loadBeanDefinitionsFromRegistrars(Map<ImportBeanDefinitionRegistrar, AnnotationMetadata> registrars) {
		registrars.forEach((registrar, metadata) ->
				registrar.registerBeanDefinitions(metadata, this.registry, this.importBeanNameGenerator));
	}

检查候选集合

在processConfigBeanDefinitions中加载配置类中所有的bean定义信息(reader.loadBeanDefinitions)后,有检查的操作(保证所有的配置类都能完成解析并加载beanDefinition)

			alreadyParsed.addAll(configClasses);
			processConfig.tag("classCount", () -> String.valueOf(configClasses.size())).end();

			candidates.clear();
			if (registry.getBeanDefinitionCount() > candidateNames.length) {
				String[] newCandidateNames = registry.getBeanDefinitionNames();//已经在registry的定义信息
				Set<String> oldCandidateNames = new HashSet<>(Arrays.asList(candidateNames));//未调用该解析方法前的已经在registry的定义信息
				Set<String> alreadyParsedClasses = new HashSet<>();//已经解析的配置类
				for (ConfigurationClass configurationClass : alreadyParsed) {
					alreadyParsedClasses.add(configurationClass.getMetadata().getClassName());
				}
				for (String candidateName : newCandidateNames) {
					if (!oldCandidateNames.contains(candidateName)) {
						BeanDefinition bd = registry.getBeanDefinition(candidateName);
						//是配置类,但是还没有被解析的
						if (ConfigurationClassUtils.checkConfigurationClassCandidate(bd, this.metadataReaderFactory) &&
								!alreadyParsedClasses.contains(bd.getBeanClassName())) {
							//放到候选集合中
							candidates.add(new BeanDefinitionHolder(bd, candidateName));
						}
					}
				}
				candidateNames = newCandidateNames;
			}

注册ImportRegistry

这里会向IOC单例池中放入ImportRegistryImportRegistry中主要存放着引用@Import注解的注解的元数据。

		// Register the ImportRegistry as a bean in order to support ImportAware @Configuration classes
		if (sbr != null && !sbr.containsSingleton(IMPORT_REGISTRY_BEAN_NAME)) {
			sbr.registerSingleton(IMPORT_REGISTRY_BEAN_NAME, parser.getImportRegistry());
		}

postProcessBeanFactory

ConfigurationClassPostProcessorpostProcessBeanDefinitionRegistry方法执行完成后,跟配置类相关的bean定义信息都注册到了DefaultListableBeanFactory中。

PostProcessorRegistrationDelegate类中又会调用ConfigurationClassPostProcessorpostProcessBeanFactory方法.

	@Override
	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);
		}

		enhanceConfigurationClasses(beanFactory);
		beanFactory.addBeanPostProcessor(new ImportAwareBeanPostProcessor(beanFactory));
	}

里面主要有两大步:enhanceConfigurationClassesbeanFactory.addBeanPostProcessor

enhanceConfigurationClasses

代码如下:

	public void enhanceConfigurationClasses(ConfigurableListableBeanFactory beanFactory) {
		StartupStep enhanceConfigClasses = this.applicationStartup.start("spring.context.config-classes.enhance");
		Map<String, AbstractBeanDefinition> configBeanDefs = new LinkedHashMap<>();
		for (String beanName : beanFactory.getBeanDefinitionNames()) {
			BeanDefinition beanDef = beanFactory.getBeanDefinition(beanName);
			//这里会获取所有的bean定义信息,然后检查对应的bean是否需要增强,需要的会放到configBeanDefs Map中
                        //检查的步骤这里省略
		}
		if (configBeanDefs.isEmpty() || NativeDetector.inNativeImage()) {
			// nothing to enhance -> return immediately
			enhanceConfigClasses.end();
			return;
		}

		ConfigurationClassEnhancer enhancer = new ConfigurationClassEnhancer();
		for (Map.Entry<String, AbstractBeanDefinition> entry : configBeanDefs.entrySet()) {
			AbstractBeanDefinition beanDef = entry.getValue();
			// If a @Configuration class gets proxied, always proxy the target class
			beanDef.setAttribute(AutoProxyUtils.PRESERVE_TARGET_CLASS_ATTRIBUTE, Boolean.TRUE);
			// Set enhanced subclass of the user-specified bean class
			Class<?> configClass = beanDef.getBeanClass();
                        //使用cglib对配置类进行增强
			Class<?> enhancedClass = enhancer.enhance(configClass, this.beanClassLoader);
			if (configClass != enhancedClass) {
				if (logger.isTraceEnabled()) {
					logger.trace(String.format("Replacing bean definition '%s' existing class '%s' with " +
							"enhanced class '%s'", entry.getKey(), configClass.getName(), enhancedClass.getName()));
				}
                                //把增强后的类设置到bean定义信息中
				beanDef.setBeanClass(enhancedClass);
			}
		}
		enhanceConfigClasses.tag("classCount", () -> String.valueOf(configBeanDefs.keySet().size())).end();
	}

image-20211203163808188

增加ImportAwareBeanPostProcessor组件

使用cglib代理增强配置类后,会向容器中导入ImportAwareBeanPostProcessor组件。

	private static class ImportAwareBeanPostProcessor implements InstantiationAwareBeanPostProcessor {

		private final BeanFactory beanFactory;

		public ImportAwareBeanPostProcessor(BeanFactory beanFactory) {
			this.beanFactory = beanFactory;
		}

		@Override
		public PropertyValues postProcessProperties(@Nullable PropertyValues pvs, Object bean, String beanName) {
			// Inject the BeanFactory before AutowiredAnnotationBeanPostProcessor's
			// postProcessProperties method attempts to autowire other configuration beans.
			if (bean instanceof EnhancedConfiguration) {
				((EnhancedConfiguration) bean).setBeanFactory(this.beanFactory);
			}
			return pvs;
		}

		@Override
		public Object postProcessBeforeInitialization(Object bean, String beanName) {
			if (bean instanceof ImportAware) {
                              //从容器中获取ImportRegistry (在上一步postProcessBeanDefinitionRegistry中,容器导入ImportRegistry到单例池中)
                                //ImportRegistry中包含了所有@Import注解所在注解的元信息
				ImportRegistry ir = this.beanFactory.getBean(IMPORT_REGISTRY_BEAN_NAME, ImportRegistry.class);
				AnnotationMetadata importingClass = ir.getImportingClassFor(ClassUtils.getUserClass(bean).getName());
				if (importingClass != null) {
					((ImportAware) bean).setImportMetadata(importingClass);
				}
			}
			return bean;
		}
	}

这个类比较简单,当bean创建的时候,因为该类实现了BeanPostProcessor,会干预bean的创建过程,它会判断bean是否实现了ImportAware,如果实现了,就会将它导入到容器中的那个注解的元信息设置到setImportMetadata方法中。这也是ImportAware的原理。

例如:@EnableMBeanExport注解

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import(MBeanExportConfiguration.class)
public @interface EnableMBeanExport {

	String defaultDomain() default "";

	String server() default "";

	RegistrationPolicy registration() default RegistrationPolicy.FAIL_ON_EXISTING;
}

该注解@Import MBeanExportConfiguration配置类,该配置通过实现ImportAware,重写了setImportMetadata,通过该方法,获取到@EnableMBeanExport的注解元信息。

@Configuration(proxyBeanMethods = false)
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
public class MBeanExportConfiguration implements ImportAware, EnvironmentAware, BeanFactoryAware {

	private static final String MBEAN_EXPORTER_BEAN_NAME = "mbeanExporter";

	@Nullable
	private AnnotationAttributes enableMBeanExport;

	@Nullable
	private Environment environment;

	@Nullable
	private BeanFactory beanFactory;


	@Override
	public void setImportMetadata(AnnotationMetadata importMetadata) {
                //获取到@EnableMBeanExport注解中配置的属性
		Map<String, Object> map = importMetadata.getAnnotationAttributes(EnableMBeanExport.class.getName());
		this.enableMBeanExport = AnnotationAttributes.fromMap(map);
		if (this.enableMBeanExport == null) {
			throw new IllegalArgumentException(
					"@EnableMBeanExport is not present on importing class " + importMetadata.getClassName());
		}
	}

免责声明:文章转载自《Spring源码分析:@Configuration原理》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇ios播放声音中断后台音乐的问题原生JDBC下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

字典的快速赋值 setValuesForKeysWithDictionary

前言 在学习解析数据的时候,我们经常是这么写的:PersonModel.h文件中 @property (nonatomic,copy)NSString *name; @property (nonatomic,copy)NSString *sex; @property (nonatomic,copy)NSString *age; 字...

解决studio 3T时间到期的两种方法

解决studio 3T时间到期的两种方法 此教程并非真正破解,而是通过重置studio 3t的试用时间解决的。 第一种方法 按住运win 和 r 键输入 regedit 找到以下路径HKEY_USERSS-1-5-21-xxxxxxxxxxxxxxSOFTWAREJavaSoftPrefs3tmongochefenterprise 将除了 inst...

java 调用webservice的各种方法总结

java 调用webservice的各种方法总结(本文转自:http://www.blogjava.net/zjhiphop/archive/2009/04/29/webservice.html) 现在webservice加xml技术已经逐渐成熟,但要真正要用起来还需时日!! 由于毕业设计缘故,我看了很多关于webservice方面的知识,今天和大家一...

PLSQL常用配置之窗口/版面保存、SQL格式化/美化、SQL注释去掉注释等快捷键配置、登陆历史修改配置

http://blog.csdn.net/hyeidolon/article/details/8251791   PLSQL常用配置之窗口/版面保存、SQL格式化/美化、SQL注释去掉注释等快捷键配置、登陆历史修改配置1、PL/SQL Developer记住登陆密码 在使用PL/SQL Developer时,为了工作方便希望PL/SQL Develop...

Dubbo的优雅下线原理分析

文/朱季谦 Dubbo如何实现优雅下线? 这个问题困扰了我一阵,既然有优雅下线这种说法,那么,是否有非优雅下线的说法呢? 这,还真有。 可以从linux进程关闭说起,其实,我们经常使用到杀进程的指令背后,就涉及到是否优雅下线的理念。 在日常开发当中,经常用到kill来关掉正在运行的进程,可能你曾看到过一些文章是不推荐使用kill -9 pid的指令来删除进...

django 数据库迁移

一,简单的数据导出与导入(简单的迁移) 1. django 项目提供了一个导出的方法 python manage.py dumpdata, 不指定 appname 时默认为导出所有的app 1 python manage.py dumpdata [appname] > appname_data.json 比如我们有一个项目叫 mysite, 里...