• Spring源码分析之IOC的三种常见用法及源码实现(二)


    Spring源码分析之IOC的三种常见用法及源码实现(二)

    回顾上文 我们研究的是

           AnnotationConfigApplicationContext annotationConfigApplication = new AnnotationConfigApplicationContext (MainConfig.class);
    
           Person person2 = (Person)annotationConfigApplication.getBean("person2");
    

    这两句话的实现,其中来到了主角儿AnnotationConfigApplicationContext的构造器实现:

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

    其中this()和register(annotatedClasses);看完了,我们这次来看看refresh();

    一、跟进refresh()的代码

    	public void refresh() throws BeansException, IllegalStateException {
    		synchronized (this.startupShutdownMonitor) {
    			// Prepare this context for refreshing.
    			prepareRefresh();
    
    			// Tell the subclass to refresh the internal bean factory.
    			ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
    
    			// Prepare the bean factory for use in this context.
    			prepareBeanFactory(beanFactory);
    
    			try {
    				// Allows post-processing of the bean factory in context subclasses.
    				postProcessBeanFactory(beanFactory);
    
    				// Invoke factory processors registered as beans in the context.
    				invokeBeanFactoryPostProcessors(beanFactory);
    
    				// Register bean processors that intercept bean creation.
    				registerBeanPostProcessors(beanFactory);
    
    				// 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.
    				finishBeanFactoryInitialization(beanFactory);
    
    				// Last step: publish corresponding event.
    				finishRefresh();
    			}
    			catch (BeansException ex) {
    				if (logger.isWarnEnabled()) {
    					logger.warn("Exception encountered during context initialization - " +
    							"cancelling refresh attempt: " + ex);
    				}
    				// Destroy already created singletons to avoid dangling resources.
    				destroyBeans();
    				// Reset 'active' flag.
    				cancelRefresh(ex);
    				// Propagate exception to caller.
    				throw ex;
    			}
    			finally {
    				// Reset common introspection caches in Spring's core, since we
    				// might not ever need metadata for singleton beans anymore...
    				resetCommonCaches();
    			}
    		}
    	}
    

    讲这个之前铺垫一点前置基础知识

    Spring中事件驱动开发

    spring中是通过ApplicationListener及ApplicationEventMulticaster来进行事件驱动开发的,即实现观察者设计模式或发布-订阅模式。

    ApplicationListener:监听容器中发布的事件,只要事件发生,就触发监听器的回调,来完成事件驱动开发。属于观察者设计模式中的Observer对象。

    ApplicationEventMulticaster:用来通知所有的观察者对象,属于观察者设计模式中的Subject对象。

    Spring后置处理器

    BeanFactoryPostProcessor:继承这个的类它的实现方法可以在spring的bean定义好之后 而未实例化的时候做一些逻辑操作

    BeanDefinitionRegistryPostProcessor:继承这个类它的实现方法可以在spring的bean未加载定义之前加些我们自己定义的bean定义

    ok讲完了,回到代码。

    我们铺垫了前置知识那么就对其中的

    initApplicationEventMulticaster();
    

    registerListeners();
    

    进行讲解

    二、refresh()中的initApplicationEventMulticaster

    	protected void initApplicationEventMulticaster() {
    		ConfigurableListableBeanFactory beanFactory = getBeanFactory();
    		if (beanFactory.containsLocalBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME)) {
    			this.applicationEventMulticaster =
    					beanFactory.getBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, ApplicationEventMulticaster.class);
    			if (logger.isDebugEnabled()) {
    				logger.debug("Using ApplicationEventMulticaster [" + this.applicationEventMulticaster + "]");
    			}
    		}
    		else {
    			this.applicationEventMulticaster = new SimpleApplicationEventMulticaster(beanFactory);
    			beanFactory.registerSingleton(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, this.applicationEventMulticaster);
    			if (logger.isDebugEnabled()) {
    				logger.debug("Unable to locate ApplicationEventMulticaster with name '" +
    						APPLICATION_EVENT_MULTICASTER_BEAN_NAME +
    						"': using default [" + this.applicationEventMulticaster + "]");
    			}
    		}
    	}
    

    非常好懂,就一个if else,首先获取beanfactory,翻看源码知道这个beanfactory就是上篇文章讲的初始化父类时创建的DefaultListableBeanFactory,拿到这玩意。还是围绕这玩意的功能操作

    接下来判断beanfactory里是不是有这个APPLICATION_EVENT_MULTICASTER_BEAN_NAME,翻看源码:

    public static final String APPLICATION_EVENT_MULTICASTER_BEAN_NAME = "applicationEventMulticaster";
    

    是不是就是之前铺垫知识的listener?用来通知事件的。看看它在不在容器里面,不在的话走else创建一个,并且作为单例注册进去,在的话就从容器里面取出来赋值给当前this对象即我们的主角儿AnnotationConfigApplicationContext,而主角本身没定义这个是在主角父类AbstractApplicationContext里定义的,我们看看:

    /** Helper class used in event publishing */
    private ApplicationEventMulticaster applicationEventMulticaster;
    

    看看,给了注释,辅助类 :用于事件派发的。

    综上所述,这个initApplicationEventMulticaster()这行代码就是获取事件通知发布类的,没有的话就以单例创建一个放到容器并拿给主角儿,否则就直接拿到给主角儿。接下来看另一个registerListeners();

    三、refresh()中的registerListeners();

    源码如下:

    	protected void registerListeners() {
    		// Register statically specified listeners first.
    		for (ApplicationListener<?> listener : getApplicationListeners()) {
    			getApplicationEventMulticaster().addApplicationListener(listener);
    		}
    
    		// Do not initialize FactoryBeans here: We need to leave all regular beans
    		// uninitialized to let post-processors apply to them!
    		String[] listenerBeanNames = getBeanNamesForType(ApplicationListener.class, true, false);
    		for (String listenerBeanName : listenerBeanNames) {
    			   getApplicationEventMulticaster().addApplicationListenerBean(listenerBeanName);
    		}
    
    		// Publish early application events now that we finally have a multicaster...
    		Set<ApplicationEvent> earlyEventsToProcess = this.earlyApplicationEvents;
    		this.earlyApplicationEvents = null;
    		if (earlyEventsToProcess != null) {
    			for (ApplicationEvent earlyEvent : earlyEventsToProcess) {
    				getApplicationEventMulticaster().multicastEvent(earlyEvent);
    			}
    		}
    	}
    
    

    第一个for循环是把所有listener都加到Multicaster里了(它用来通知相关事件)。其中

    	String[] listenerBeanNames = getBeanNamesForType(ApplicationListener.class, true, false);
    	for (String listenerBeanName : listenerBeanNames) {
    		   getApplicationEventMulticaster().addApplicationListenerBean(listenerBeanName);
    	}
    

    这个是从容器中拿ApplicationListener.class类型的,从名字也可以看出来getBeanForType,拿出来之后也放到Multicaster里(它用来通知相关事件),这也就是为什么我们可以自己实现ApplicationListener接口并且打上@Component注解之后能通知的原因了!它在这里加进去了。

    最后一段是获取早期事件,获取了之后for循环进行触发事件。我们来看看它到底是个怎么触发的。

    	Set<ApplicationEvent> earlyEventsToProcess = this.earlyApplicationEvents;
    	this.earlyApplicationEvents = null;
    	if (earlyEventsToProcess != null) {
    		for (ApplicationEvent earlyEvent : earlyEventsToProcess) {
    			getApplicationEventMulticaster().multicastEvent(earlyEvent);
    		}
    	}
    

    打开里面的multicastEvent方法

    	@Override
    	public void multicastEvent(ApplicationEvent event) {
    		multicastEvent(event, resolveDefaultEventType(event));
    	}
    
    
    	public void multicastEvent(final ApplicationEvent event, ResolvableType eventType) {
    		ResolvableType type = (eventType != null ? eventType : resolveDefaultEventType(event));
    		for (final ApplicationListener<?> listener : getApplicationListeners(event, type)) {
    			Executor executor = getTaskExecutor();
    			if (executor != null) {
    				executor.execute(new Runnable() {
    					@Override
    					public void run() {
    						invokeListener(listener, event);
    					}
    				});
    			}
    			else {
    				invokeListener(listener, event);
    			}
    		}
    	}
    

    一个解析类型、一个执行invokeListener,进去再看看这个咋invokeListener调用的

    	protected void invokeListener(ApplicationListener listener, ApplicationEvent event) {
    		ErrorHandler errorHandler = getErrorHandler();
    		if (errorHandler != null) {
    			try {
    				listener.onApplicationEvent(event);
    			}
    			catch (Throwable err) {
    				errorHandler.handleError(err);
    			}
    		}
    		else {
    			try {
    				listener.onApplicationEvent(event);
    			}
    			catch (ClassCastException ex) {
    				String msg = ex.getMessage();
    				if (msg == null || msg.startsWith(event.getClass().getName())) {
    					// Possibly a lambda-defined listener which we could not resolve the generic event type for
    					Log logger = LogFactory.getLog(getClass());
    					if (logger.isDebugEnabled()) {
    						logger.debug("Non-matching event type for listener: " + listener, ex);
    					}
    				}
    				else {
    					throw ex;
    				}
    			}
    		}
    	}
    

    仔细看下就发现重点了,其实最终就是调用listener.onApplicationEvent(event);,而这个onApplicationEvent就是ApplicationListener接口唯一的方法。换句话说,你只要实现这个接口类,并加入@Compent加入容器中,就会调用你实现类的onApplicationEvent里你自己的代码!

    可能细心的同学会发现刚刚前面看到的registerListeners中最后一段里获取的是earlyApplicationEvents,这个early是什么意思?实际上是把Multicaster还没创建时就已经缓存的事件给获取播放,因为之前来了事件也不能丢掉啊。那么什么时候会有这个early事件呢?实际上是在refresh()代码里的registerListeners方法的前一句onRefresh方法中,这个方法默认是没有early事件的,会在springboot中使用.

    至此registerListeners方法也讲完了。

    接下来我们来讲讲refresh()中的invokeBeanFactoryPostProcessors(beanFactory);

    四、refresh()中的invokeBeanFactoryPostProcessors(beanFactory);

    	/**
    	 * 按照明确的顺序实例化并调用所有在BeanFactoryPostProcessor注册的bean
    	 * <p>Must be called before singleton instantiation.
    	 */
    	protected void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory) {
    		PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, getBeanFactoryPostProcessors());
    
    		// Detect a LoadTimeWeaver and prepare for weaving, if found in the meantime
    		// (e.g. through an @Bean method registered by ConfigurationClassPostProcessor)
    		if (beanFactory.getTempClassLoader() == null && beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {
                
    			beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));
                
    			beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));
    		}
    	}
    

    很明显继续跟进这个invokeBeanFactoryPostProcessors同名方法:

    	public static void invokeBeanFactoryPostProcessors(
    			ConfigurableListableBeanFactory beanFactory, List<BeanFactoryPostProcessor> beanFactoryPostProcessors) {
    
    		// Invoke BeanDefinitionRegistryPostProcessors first, if any.
    		Set<String> processedBeans = new HashSet<String>();
    
    		if (beanFactory instanceof BeanDefinitionRegistry) {
    			BeanDefinitionRegistry registry = (BeanDefinitionRegistry) beanFactory;
    			List<BeanFactoryPostProcessor> regularPostProcessors = new LinkedList<BeanFactoryPostProcessor>();
    			List<BeanDefinitionRegistryPostProcessor> registryPostProcessors =
    					new LinkedList<BeanDefinitionRegistryPostProcessor>();
    
    			for (BeanFactoryPostProcessor postProcessor : beanFactoryPostProcessors) {
    				if (postProcessor instanceof BeanDefinitionRegistryPostProcessor) {
    					BeanDefinitionRegistryPostProcessor registryPostProcessor =
    							(BeanDefinitionRegistryPostProcessor) postProcessor;
    					registryPostProcessor.postProcessBeanDefinitionRegistry(registry);
    					registryPostProcessors.add(registryPostProcessor);
    				}
    				else {
    					regularPostProcessors.add(postProcessor);
    				}
    			}
    
    			// Do not initialize FactoryBeans here: We need to leave all regular beans
    			// uninitialized to let the bean factory post-processors apply to them!
    			// Separate between BeanDefinitionRegistryPostProcessors that implement
    			// PriorityOrdered, Ordered, and the rest.
    			String[] postProcessorNames =
    					beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
    
    			// First, invoke the BeanDefinitionRegistryPostProcessors that implement PriorityOrdered.
    			List<BeanDefinitionRegistryPostProcessor> priorityOrderedPostProcessors = new ArrayList<BeanDefinitionRegistryPostProcessor>();
    			for (String ppName : postProcessorNames) {
    				if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
    					priorityOrderedPostProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
    					processedBeans.add(ppName);
    				}
    			}
    			sortPostProcessors(beanFactory, priorityOrderedPostProcessors);
    			registryPostProcessors.addAll(priorityOrderedPostProcessors);
    			invokeBeanDefinitionRegistryPostProcessors(priorityOrderedPostProcessors, registry);
    
    			// Next, invoke the BeanDefinitionRegistryPostProcessors that implement Ordered.
    			postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
    			List<BeanDefinitionRegistryPostProcessor> orderedPostProcessors = new ArrayList<BeanDefinitionRegistryPostProcessor>();
    			for (String ppName : postProcessorNames) {
    				if (!processedBeans.contains(ppName) && beanFactory.isTypeMatch(ppName, Ordered.class)) {
    					orderedPostProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
    					processedBeans.add(ppName);
    				}
    			}
    			sortPostProcessors(beanFactory, orderedPostProcessors);
    			registryPostProcessors.addAll(orderedPostProcessors);
    			invokeBeanDefinitionRegistryPostProcessors(orderedPostProcessors, registry);
    
    			// Finally, invoke all other BeanDefinitionRegistryPostProcessors until no further ones appear.
    			boolean reiterate = true;
    			while (reiterate) {
    				reiterate = false;
    				postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
    				for (String ppName : postProcessorNames) {
    					if (!processedBeans.contains(ppName)) {
    						BeanDefinitionRegistryPostProcessor pp = beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class);
    						registryPostProcessors.add(pp);
    						processedBeans.add(ppName);
    						pp.postProcessBeanDefinitionRegistry(registry);
    						reiterate = true;
    					}
    				}
    			}
    
    			// Now, invoke the postProcessBeanFactory callback of all processors handled so far.
    			invokeBeanFactoryPostProcessors(registryPostProcessors, beanFactory);
    			invokeBeanFactoryPostProcessors(regularPostProcessors, beanFactory);
    		}
    
    		else {
    			// Invoke factory processors registered with the context instance.
    			invokeBeanFactoryPostProcessors(beanFactoryPostProcessors, beanFactory);
    		}
    
    		// Do not initialize FactoryBeans here: We need to leave all regular beans
    		// uninitialized to let the bean factory post-processors apply to them!
    		String[] postProcessorNames =
    				beanFactory.getBeanNamesForType(BeanFactoryPostProcessor.class, true, false);
    
    		// Separate between BeanFactoryPostProcessors that implement PriorityOrdered,
    		// Ordered, and the rest.
    		List<BeanFactoryPostProcessor> priorityOrderedPostProcessors = new ArrayList<BeanFactoryPostProcessor>();
    		List<String> orderedPostProcessorNames = new ArrayList<String>();
    		List<String> nonOrderedPostProcessorNames = new ArrayList<String>();
    		for (String ppName : postProcessorNames) {
    			if (processedBeans.contains(ppName)) {
    				// skip - already processed in first phase above
    			}
    			else if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
    				priorityOrderedPostProcessors.add(beanFactory.getBean(ppName, BeanFactoryPostProcessor.class));
    			}
    			else if (beanFactory.isTypeMatch(ppName, Ordered.class)) {
    				orderedPostProcessorNames.add(ppName);
    			}
    			else {
    				nonOrderedPostProcessorNames.add(ppName);
    			}
    		}
    
    		// First, invoke the BeanFactoryPostProcessors that implement PriorityOrdered.
    		sortPostProcessors(beanFactory, priorityOrderedPostProcessors);
    		invokeBeanFactoryPostProcessors(priorityOrderedPostProcessors, beanFactory);
    
    		// Next, invoke the BeanFactoryPostProcessors that implement Ordered.
    		List<BeanFactoryPostProcessor> orderedPostProcessors = new ArrayList<BeanFactoryPostProcessor>();
    		for (String postProcessorName : orderedPostProcessorNames) {
    			orderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class));
    		}
    		sortPostProcessors(beanFactory, orderedPostProcessors);
    		invokeBeanFactoryPostProcessors(orderedPostProcessors, beanFactory);
    
    		// Finally, invoke all other BeanFactoryPostProcessors.
    		List<BeanFactoryPostProcessor> nonOrderedPostProcessors = new ArrayList<BeanFactoryPostProcessor>();
    		for (String postProcessorName : nonOrderedPostProcessorNames) {
    			nonOrderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class));
    		}
    		invokeBeanFactoryPostProcessors(nonOrderedPostProcessors, beanFactory);
    
    		// Clear cached merged bean definitions since the post-processors might have
    		// modified the original metadata, e.g. replacing placeholders in values...
    		beanFactory.clearMetadataCache();
    	}
    

    仔细读里的逻辑会发现前半段是围绕:

    			List<BeanFactoryPostProcessor> regularPostProcessors = new LinkedList<BeanFactoryPostProcessor>();
    			List<BeanDefinitionRegistryPostProcessor> registryPostProcessors =
    					new LinkedList<BeanDefinitionRegistryPostProcessor>();
    

    这两个list进行不断筛选分类 然后进行invokeBeanDefinitionRegistryPostProcessors方法调用

    而后半段是围绕:

    		List<BeanFactoryPostProcessor> priorityOrderedPostProcessors = new ArrayList<BeanFactoryPostProcessor>();
    		List<String> orderedPostProcessorNames = new ArrayList<String>();
    		List<String> nonOrderedPostProcessorNames = new ArrayList<String>();
    

    三个list进行分类添加进去,然后进行invokeBeanDefinitionRegistryPostProcessors方法调用

    综上核心就是这个invokeBeanDefinitionRegistryPostProcessors的逻辑,我们来看看:

    	private static void invokeBeanFactoryPostProcessors(
    			Collection<? extends BeanFactoryPostProcessor> postProcessors, ConfigurableListableBeanFactory beanFactory) {
    
    		for (BeanFactoryPostProcessor postProcessor : postProcessors) {
    			postProcessor.postProcessBeanFactory(beanFactory);
    		}
    	}
    

    遍历集合,并调用对应方法,继续查看源码:

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

    设置注册id、然后这里显然主要逻辑在processConfigBeanDefinitions,继续查看:

    	public void processConfigBeanDefinitions(BeanDefinitionRegistry registry) {
    		List<BeanDefinitionHolder> configCandidates = new ArrayList<BeanDefinitionHolder>();
    		String[] candidateNames = registry.getBeanDefinitionNames();
    
    		for (String beanName : candidateNames) {
    			BeanDefinition beanDef = registry.getBeanDefinition(beanName);
    			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));
    			}
    		}
    
    		// Return immediately if no @Configuration classes were found
    		if (configCandidates.isEmpty()) {
    			return;
    		}
    
    		// Sort by previously determined @Order value, if applicable
    		Collections.sort(configCandidates, new Comparator<BeanDefinitionHolder>() {
    			@Override
    			public int compare(BeanDefinitionHolder bd1, BeanDefinitionHolder bd2) {
    				int i1 = ConfigurationClassUtils.getOrder(bd1.getBeanDefinition());
    				int i2 = ConfigurationClassUtils.getOrder(bd2.getBeanDefinition());
    				return (i1 < i2) ? -1 : (i1 > i2) ? 1 : 0;
    			}
    		});
    
    		// Detect any custom bean name generation strategy supplied through the enclosing application context
    		SingletonBeanRegistry sbr = null;
    		if (registry instanceof SingletonBeanRegistry) {
    			sbr = (SingletonBeanRegistry) registry;
    			if (!this.localBeanNameGeneratorSet && sbr.containsSingleton(CONFIGURATION_BEAN_NAME_GENERATOR)) {
    				BeanNameGenerator generator = (BeanNameGenerator) sbr.getSingleton(CONFIGURATION_BEAN_NAME_GENERATOR);
    				this.componentScanBeanNameGenerator = generator;
    				this.importBeanNameGenerator = generator;
    			}
    		}
    
    		// Parse each @Configuration class
    		ConfigurationClassParser parser = new ConfigurationClassParser(
    				this.metadataReaderFactory, this.problemReporter, this.environment,
    				this.resourceLoader, this.componentScanBeanNameGenerator, registry);
    
    		Set<BeanDefinitionHolder> candidates = new LinkedHashSet<BeanDefinitionHolder>(configCandidates);
    		Set<ConfigurationClass> alreadyParsed = new HashSet<ConfigurationClass>(configCandidates.size());
    		do {
    			parser.parse(candidates);
    			parser.validate();
    
    			Set<ConfigurationClass> configClasses = new LinkedHashSet<ConfigurationClass>(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);
    
    			candidates.clear();
    			if (registry.getBeanDefinitionCount() > candidateNames.length) {
    				String[] newCandidateNames = registry.getBeanDefinitionNames();
    				Set<String> oldCandidateNames = new HashSet<String>(Arrays.asList(candidateNames));
    				Set<String> alreadyParsedClasses = new HashSet<String>();
    				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) {
    			if (!sbr.containsSingleton(IMPORT_REGISTRY_BEAN_NAME)) {
    				sbr.registerSingleton(IMPORT_REGISTRY_BEAN_NAME, parser.getImportRegistry());
    			}
    		}
    
    		if (this.metadataReaderFactory instanceof CachingMetadataReaderFactory) {
    			((CachingMetadataReaderFactory) this.metadataReaderFactory).clearCache();
    		}
    	}
    

    比较长,分几部分看,第一部分刚开始是创建一个ArrayList,类型是BeanDefinitionHolder,我们看看这个:

    public class BeanDefinitionHolder implements BeanMetadataElement {
        private final BeanDefinition beanDefinition;
        private final String beanName;
        private final String[] aliases;
        .......
    }
    

    可以看出,这个BeanDefinitionHolder实际上就是个BeanDefinition的一个小包装。

    继续看,后面的代码就是从registry容器中拿bean名字出来然后又根据名字把BeanDefinition拿出来,最后把名字和BeanDefinition本身一起装到list里面去了,再排个序。后面又创建了两bean名字生成器。

    现在可以看到重点了,有一行注释:

            // Parse each @Configuration class
    		ConfigurationClassParser parser = new ConfigurationClassParser(
    				this.metadataReaderFactory, this.problemReporter, this.environment,
    				this.resourceLoader, this.componentScanBeanNameGenerator, registry);
    
    		Set<BeanDefinitionHolder> candidates = new LinkedHashSet<BeanDefinitionHolder>(configCandidates);
    		Set<ConfigurationClass> alreadyParsed = new HashSet<ConfigurationClass>(configCandidates.size());
    		do {
    			parser.parse(candidates);
    			parser.validate();
                ......
            }while(....)
                .....
    

    这里来到了核心重点,要解析我们的配置类了!弄了个do while循环保证这些都list里的东西都解析完,我们来看看解析方法parser.parse(candidates);吧!它是怎么解析的:

    	public void parse(Set<BeanDefinitionHolder> configCandidates) {
    		this.deferredImportSelectors = new LinkedList<DeferredImportSelectorHolder>();
    
    		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);
    			}
    		}
    
    		processDeferredImportSelectors();
    	}
    

    这里又是分了三种情况去解析,第一种从名字可以看出来注解的那种解析,第二种是AbstractBeanDefinition这是对XML配置方式的解析,很明显我们看第一种,继续查看源码:

    	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.
    				// Let's remove the old one and go with the new one.
    				this.configurationClasses.remove(configClass);
    				for (Iterator<ConfigurationClass> it = this.knownSuperclasses.values().iterator(); it.hasNext();) {
    					if (configClass.equals(it.next())) {
    						it.remove();
    					}
    				}
    			}
    		}
    
    		// 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);
    	}
    

    我们看Spring源码会发现,Spring源码里真正干活的都是doXXX方法,会发现这里终于也发现一个了,

    前面是对配置类的一个判断处理,后面就是doProcessConfigurationClass真正处理了,处理完之后加入到configurationClasses中,也就是最后一句话。我们查看源码:

    	protected final SourceClass doProcessConfigurationClass(ConfigurationClass configClass, SourceClass sourceClass)
    			throws IOException {
    
    		// Recursively process any member (nested) classes first
    		processMemberClasses(configClass, sourceClass);
    
    		// 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.warn("Ignoring @PropertySource annotation on [" + sourceClass.getMetadata().getClassName() +
    						"]. Reason: Environment must implement ConfigurableEnvironment");
    			}
    		}
    
    		// 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) {
    					if (ConfigurationClassUtils.checkConfigurationClassCandidate(
    							holder.getBeanDefinition(), this.metadataReaderFactory)) {
    						parse(holder.getBeanDefinition().getBeanClassName(), holder.getBeanName());
    					}
    				}
    			}
    		}
    
    		// Process any @Import annotations
    		processImports(configClass, sourceClass, getImports(sourceClass), true);
    
    		// Process any @ImportResource annotations
    		if (sourceClass.getMetadata().isAnnotated(ImportResource.class.getName())) {
    			AnnotationAttributes importResource =
    					AnnotationConfigUtils.attributesFor(sourceClass.getMetadata(), ImportResource.class);
    			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
    		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.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注解吧!

    IOC三大常用springbean配置用法,还有个是通过@ComponentScan配置的,SpringBoot也是通过这种。

    @Target({ElementType.TYPE})
    @Retention(RetentionPolicy.RUNTIME)
    @Documented
    @Inherited
    @SpringBootConfiguration
    @EnableAutoConfiguration
    @ComponentScan(
        excludeFilters = {@Filter(
        type = FilterType.CUSTOM,
        classes = {TypeExcludeFilter.class}
    ), @Filter(
        type = FilterType.CUSTOM,
        classes = {AutoConfigurationExcludeFilter.class}
    )}
    )
    public @interface SpringBootApplication {
    		....
    }
    

    @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) {
    					if (ConfigurationClassUtils.checkConfigurationClassCandidate(
    							holder.getBeanDefinition(), this.metadataReaderFactory)) {
    						parse(holder.getBeanDefinition().getBeanClassName(), holder.getBeanName());
    					}
    				}
    			}
    		}
    

    这里的第一句

    		Set<AnnotationAttributes> componentScans = AnnotationConfigUtils.attributesForRepeatable(
    				sourceClass.getMetadata(), ComponentScans.class, ComponentScan.class);
    

    是把我们的配置类也就是sourceClass,获取了元数据传到这个注解工具类里去了,是把配置类里面的@ComponentScan注解解析为对象了,这样方便后面拿到注解里设置的值。

    然后往后看

    Set<BeanDefinitionHolder> scannedBeanDefinitions =
    						this.componentScanParser.parse(componentScan, 		   sourceClass.getMetadata().getClassName());
    

    就是继续解析了,查看源码:

    	public Set<BeanDefinitionHolder> parse(AnnotationAttributes componentScan, final String declaringClass) {
    		Assert.state(this.environment != null, "Environment must not be null");
    		Assert.state(this.resourceLoader != null, "ResourceLoader must not be null");
    
    		ClassPathBeanDefinitionScanner scanner = new ClassPathBeanDefinitionScanner(this.registry,
    				componentScan.getBoolean("useDefaultFilters"), this.environment, this.resourceLoader);
    
    		Class<? extends BeanNameGenerator> generatorClass = componentScan.getClass("nameGenerator");
    		boolean useInheritedGenerator = (BeanNameGenerator.class == generatorClass);
    		scanner.setBeanNameGenerator(useInheritedGenerator ? this.beanNameGenerator :
    				BeanUtils.instantiateClass(generatorClass));
    
    		ScopedProxyMode scopedProxyMode = componentScan.getEnum("scopedProxy");
    		if (scopedProxyMode != ScopedProxyMode.DEFAULT) {
    			scanner.setScopedProxyMode(scopedProxyMode);
    		}
    		else {
    			Class<? extends ScopeMetadataResolver> resolverClass = componentScan.getClass("scopeResolver");
    			scanner.setScopeMetadataResolver(BeanUtils.instantiateClass(resolverClass));
    		}
    
    		scanner.setResourcePattern(componentScan.getString("resourcePattern"));
    
    		for (AnnotationAttributes filter : componentScan.getAnnotationArray("includeFilters")) {
    			for (TypeFilter typeFilter : typeFiltersFor(filter)) {
    				scanner.addIncludeFilter(typeFilter);
    			}
    		}
    		for (AnnotationAttributes filter : componentScan.getAnnotationArray("excludeFilters")) {
    			for (TypeFilter typeFilter : typeFiltersFor(filter)) {
    				scanner.addExcludeFilter(typeFilter);
    			}
    		}
    
    		boolean lazyInit = componentScan.getBoolean("lazyInit");
    		if (lazyInit) {
    			scanner.getBeanDefinitionDefaults().setLazyInit(true);
    		}
    
    		Set<String> basePackages = new LinkedHashSet<String>();
    		String[] basePackagesArray = componentScan.getStringArray("basePackages");
    		for (String pkg : basePackagesArray) {
    			String[] tokenized = StringUtils.tokenizeToStringArray(this.environment.resolvePlaceholders(pkg),
    					ConfigurableApplicationContext.CONFIG_LOCATION_DELIMITERS);
    			basePackages.addAll(Arrays.asList(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);
    			}
    		});
    		return scanner.doScan(StringUtils.toStringArray(basePackages));
    	}
    

    又是一堆代码...总体看下来会发现,前面95%都是给下面这句话设置参数:

    ClassPathBeanDefinitionScanner scanner = new ClassPathBeanDefinitionScanner(this.registry,componentScan.getBoolean("useDefaultFilters"), this.environment, this.resourceLoader);
    

    很明显ClassPathBeanDefinitionScanner是真正用来扫描类的,类注释写了“A bean definition scanner that detects bean candidates on the classpath”,后面都是给扫描器设置各种名字生成器、scope、resourcePattern、以及include和exclude和是否懒加载,直到下面这段时候才开始注意路径:

    		Set<String> basePackages = new LinkedHashSet<String>();
    		String[] basePackagesArray = componentScan.getStringArray("basePackages");
    		for (String pkg : basePackagesArray) {
    			String[] tokenized = StringUtils.tokenizeToStringArray(this.environment.resolvePlaceholders(pkg),
    					ConfigurableApplicationContext.CONFIG_LOCATION_DELIMITERS);
    			basePackages.addAll(Arrays.asList(tokenized));
    		}
    		for (Class<?> clazz : componentScan.getClassArray("basePackageClasses")) {
    			basePackages.add(ClassUtils.getPackageName(clazz));
    		}
    		if (basePackages.isEmpty()) {
    			basePackages.add(ClassUtils.getPackageName(declaringClass));
    		}
    

    获取我们在注解里写的basePackages,进行环境路径设置,最后加到之前创建的hashset类型的basePackages变量里去。然后设置排除filter到扫描器。最后一句又到了核心代码了。

    		return scanner.doScan(StringUtils.toStringArray(basePackages));
    

    这里就是最后真正扫描了,查看源码:

    	protected Set<BeanDefinitionHolder> doScan(String... basePackages) {
    		Assert.notEmpty(basePackages, "At least one base package must be specified");
    		Set<BeanDefinitionHolder> beanDefinitions = new LinkedHashSet<BeanDefinitionHolder>();
    		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) {
    					AnnotationConfigUtils.processCommonDefinitionAnnotations((AnnotatedBeanDefinition) candidate);
    				}
    				if (checkCandidate(beanName, candidate)) {
    					BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(candidate, beanName);
    					definitionHolder =
    							AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);
    					beanDefinitions.add(definitionHolder);
    					registerBeanDefinition(definitionHolder, this.registry);
    				}
    			}
    		}
    		return beanDefinitions;
    	}
    

    for循环遍历basePackages,再通过findCandidateComponents方法拿到每个basePageage下的类BeanDefinition们,后面就是给每个BeanDefinition进行配置。

    那我们就先来看看findCandidateComponents方法源码是怎么把这些BeanDefinition搞出来的:

    	public Set<BeanDefinition> findCandidateComponents(String basePackage) {
    		Set<BeanDefinition> candidates = new LinkedHashSet<BeanDefinition>();
    		try {
    			String packageSearchPath = ResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX +
    					resolveBasePackage(basePackage) + '/' + this.resourcePattern;
    			Resource[] resources = this.resourcePatternResolver.getResources(packageSearchPath);
    			boolean traceEnabled = logger.isTraceEnabled();
    			boolean debugEnabled = logger.isDebugEnabled();
    			for (Resource resource : resources) {
    				if (traceEnabled) {
    					logger.trace("Scanning " + resource);
    				}
    				if (resource.isReadable()) {
    					try {
    						MetadataReader metadataReader = this.metadataReaderFactory.getMetadataReader(resource);
    						if (isCandidateComponent(metadataReader)) {
    							ScannedGenericBeanDefinition sbd = new ScannedGenericBeanDefinition(metadataReader);
    							sbd.setResource(resource);
    							sbd.setSource(resource);
    							if (isCandidateComponent(sbd)) {
    								if (debugEnabled) {
    									logger.debug("Identified candidate component class: " + resource);
    								}
    								candidates.add(sbd);
    							}
    							else {
    								if (debugEnabled) {
    									logger.debug("Ignored because not a concrete top-level class: " + resource);
    								}
    							}
    						}
    						else {
    							if (traceEnabled) {
    								logger.trace("Ignored because not matching any filter: " + resource);
    							}
    						}
    					}
    					catch (Throwable ex) {
    						throw new BeanDefinitionStoreException(
    								"Failed to read candidate component class: " + resource, ex);
    					}
    				}
    				else {
    					if (traceEnabled) {
    						logger.trace("Ignored because not readable: " + resource);
    					}
    				}
    			}
    		}
    		catch (IOException ex) {
    			throw new BeanDefinitionStoreException("I/O failure during classpath scanning", ex);
    		}
    		return candidates;
    	}
    

    这里的办法就比较好懂了,可能有些自己平时都写过。第一个明显拼字符串,拼最终要读取的资源文件路径,然后把文件路径交给resourcePatternResolver,获取一个Resource类(继承自InputStreamSource),这个就是个IO流读取。

    这里大段都是try catch了,因为涉及到很多失败的情况,都做了处理。

    里面主要还做了filter的判断,判断是不是你是不是exclude了一些 这样就不读了,然后读出来是不是打了Component注解的,最后条件都满足的话就把读出来的信息就加到 最终的一个LinkedHashSet的集合里去了,进行返回。

    全读出来之后,返回上层doScan方法的这里:

    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) {
    					AnnotationConfigUtils.processCommonDefinitionAnnotations((AnnotatedBeanDefinition) candidate);
    				}
    				if (checkCandidate(beanName, candidate)) {
    					BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(candidate, beanName);
    					definitionHolder =
    							AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);
    					beanDefinitions.add(definitionHolder);
    					registerBeanDefinition(definitionHolder, this.registry);
    				}
    			}
    

    给扫描出来的BeanDefinition设置scope,单例多例、搞一个名字给这个BeanDefinition,以及判断是注解形式配置的还是XML形式配置的给它设置一些默认的配置,比如默认的懒加载设置各种,spring有默认的或者读你设置的。最后把这个BeanDefinition和名字一起包装成BeanDefinitionHolder,通过:

    BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(candidate, beanName);
    definitionHolder=AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata,definitionHolder, this.registry);
    beanDefinitions.add(definitionHolder);
    registerBeanDefinition(definitionHolder, this.registry);
    

    最后registerBeanDefinition注册到容器里去。说实话我又好奇是咋注册的,不断打开源码:

    public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition)
    			throws BeanDefinitionStoreException {
    
    		Assert.hasText(beanName, "Bean name must not be empty");
    		Assert.notNull(beanDefinition, "BeanDefinition must not be null");
    
    		if (beanDefinition instanceof AbstractBeanDefinition) {
    			try {
    				((AbstractBeanDefinition) beanDefinition).validate();
    			}
    			catch (BeanDefinitionValidationException ex) {
    				throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName,
    						"Validation of bean definition failed", ex);
    			}
    		}
    
    		BeanDefinition oldBeanDefinition;
    
    		oldBeanDefinition = this.beanDefinitionMap.get(beanName);
    		if (oldBeanDefinition != null) {
    			if (!isAllowBeanDefinitionOverriding()) {
    				throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName,
    						"Cannot register bean definition [" + beanDefinition + "] for bean '" + beanName +
    						"': There is already [" + oldBeanDefinition + "] bound.");
    			}
    			else if (oldBeanDefinition.getRole() < beanDefinition.getRole()) {
    				// e.g. was ROLE_APPLICATION, now overriding with ROLE_SUPPORT or ROLE_INFRASTRUCTURE
    				if (this.logger.isWarnEnabled()) {
    					this.logger.warn("Overriding user-defined bean definition for bean '" + beanName +
    							"' with a framework-generated bean definition: replacing [" +
    							oldBeanDefinition + "] with [" + beanDefinition + "]");
    				}
    			}
    			else if (!beanDefinition.equals(oldBeanDefinition)) {
    				if (this.logger.isInfoEnabled()) {
    					this.logger.info("Overriding bean definition for bean '" + beanName +
    							"' with a different definition: replacing [" + oldBeanDefinition +
    							"] with [" + beanDefinition + "]");
    				}
    			}
    			else {
    				if (this.logger.isDebugEnabled()) {
    					this.logger.debug("Overriding bean definition for bean '" + beanName +
    							"' with an equivalent definition: replacing [" + oldBeanDefinition +
    							"] with [" + beanDefinition + "]");
    				}
    			}
    			this.beanDefinitionMap.put(beanName, beanDefinition);
    		}
    		else {
    			if (hasBeanCreationStarted()) {
    				// Cannot modify startup-time collection elements anymore (for stable iteration)
    				synchronized (this.beanDefinitionMap) {
    					this.beanDefinitionMap.put(beanName, beanDefinition);
    					List<String> updatedDefinitions = new ArrayList<String>(this.beanDefinitionNames.size() + 1);
    					updatedDefinitions.addAll(this.beanDefinitionNames);
    					updatedDefinitions.add(beanName);
    					this.beanDefinitionNames = updatedDefinitions;
    					if (this.manualSingletonNames.contains(beanName)) {
    						Set<String> updatedSingletons = new LinkedHashSet<String>(this.manualSingletonNames);
    						updatedSingletons.remove(beanName);
    						this.manualSingletonNames = updatedSingletons;
    					}
    				}
    			}
    			else {
    				// Still in startup registration phase
    				this.beanDefinitionMap.put(beanName, beanDefinition);
    				this.beanDefinitionNames.add(beanName);
    				this.manualSingletonNames.remove(beanName);
    			}
    			this.frozenBeanDefinitionNames = null;
    		}
    
    		if (oldBeanDefinition != null || containsSingleton(beanName)) {
    			resetBeanDefinition(beanName);
    		}
    	}
    

    啰嗦了很长一大段,其实是一些校验、对同名BeanDefinition的处理啥的,核心就一句:

    this.beanDefinitionMap.put(beanName, beanDefinition);
    

    查看这个beanDefinitionMap

    private final Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<String, BeanDefinition>(256);
    

    就是个ConcurrentHashMap,在DefaultListableBeanFactory类里的一个private私有成员变量,所以也可见DefaultListableBeanFactory类的重要性,BeanDefinition都存在它这了,容器。

    ok,一探到底了,开始回到上层调用吧。

    回到之前的ConfigurationClassParser类的doProcessConfigurationClass方法中,是这个方法里开始的各种注解的解析:

    		// 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) {
    					if (ConfigurationClassUtils.checkConfigurationClassCandidate(
    							holder.getBeanDefinition(), this.metadataReaderFactory)) {
    						parse(holder.getBeanDefinition().getBeanClassName(), holder.getBeanName());
    					}
    				}
    			}
    		}
    

    我们之前是对这里的:

    Set<BeanDefinitionHolder> scannedBeanDefinitions =
    						this.componentScanParser.parse(componentScan, sourceClass.getMetadata().getClassName());
    

    进行的不断深挖,那就往下看吧:

    for (BeanDefinitionHolder holder : scannedBeanDefinitions) {
    	if (ConfigurationClassUtils.checkConfigurationClassCandidate(
    		holder.getBeanDefinition(), this.metadataReaderFactory)) {
    		parse(holder.getBeanDefinition().getBeanClassName(), holder.getBeanName());
    	}
    }
    

    这里是检查ComponentScan扫出来的类是不是又打了ComonentScan注解,可能就需要递归解析了。

    OK,那我们就把@ComponentScan相关源码分析完了。

    这个方法里还有别的注解的解析。比如我们这个系列最开始给的例子:通过Java配置类配置bean 就是用的@Bean注解。那我们来看看@Bean注解。

    @Bean源码

    // Process individual @Bean methods
    Set<MethodMetadata> beanMethods = retrieveBeanMethodMetadata(sourceClass);
    for (MethodMetadata methodMetadata : beanMethods) {
    	configClass.addBeanMethod(new BeanMethod(methodMetadata, configClass));
    }
    

    这里面这个addBeanMethod方法打开一看:

    	public void addBeanMethod(BeanMethod method) {
    		this.beanMethods.add(method);
    	}
    

    而beanMehtods是个private final Set beanMethods = new LinkedHashSet();

    感觉是啥也没干,就是加进去了而已。只能看看retrieveBeanMethodMetadata是在干嘛了,打开:

    	private Set<MethodMetadata> retrieveBeanMethodMetadata(SourceClass sourceClass) {
    		AnnotationMetadata original = sourceClass.getMetadata();
    		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.
    			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<MethodMetadata>(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...
    			}
    		}
    		return beanMethods;
    	}
    

    这里貌似也没干啥,就是把配置类里面的打了bean注解的方法返回拿出来了,啥也没干。那么这个@Bean注解标注里的创建对象到底在哪里创建并加到容器呢?

    这里明显就是个预操作,那么真正的操作在上层调用后面(实际上这个parse解析方法里也就只有@ComponentScan的真正处理了),我们返回上层直到有parse方法的地方:来到ConfigurationClassPostProcessor的processConfigBeanDefinitions方法:

    public void processConfigBeanDefinitions(BeanDefinitionRegistry registry) {
    		List<BeanDefinitionHolder> configCandidates = new ArrayList<BeanDefinitionHolder>();
    		String[] candidateNames = registry.getBeanDefinitionNames();
    
    		for (String beanName : candidateNames) {
    			BeanDefinition beanDef = registry.getBeanDefinition(beanName);
    			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));
    			}
    		}
    
    		// Return immediately if no @Configuration classes were found
    		if (configCandidates.isEmpty()) {
    			return;
    		}
    
    		// Sort by previously determined @Order value, if applicable
    		Collections.sort(configCandidates, new Comparator<BeanDefinitionHolder>() {
    			@Override
    			public int compare(BeanDefinitionHolder bd1, BeanDefinitionHolder bd2) {
    				int i1 = ConfigurationClassUtils.getOrder(bd1.getBeanDefinition());
    				int i2 = ConfigurationClassUtils.getOrder(bd2.getBeanDefinition());
    				return (i1 < i2) ? -1 : (i1 > i2) ? 1 : 0;
    			}
    		});
    
    		// Detect any custom bean name generation strategy supplied through the enclosing application context
    		SingletonBeanRegistry sbr = null;
    		if (registry instanceof SingletonBeanRegistry) {
    			sbr = (SingletonBeanRegistry) registry;
    			if (!this.localBeanNameGeneratorSet && sbr.containsSingleton(CONFIGURATION_BEAN_NAME_GENERATOR)) {
    				BeanNameGenerator generator = (BeanNameGenerator) sbr.getSingleton(CONFIGURATION_BEAN_NAME_GENERATOR);
    				this.componentScanBeanNameGenerator = generator;
    				this.importBeanNameGenerator = generator;
    			}
    		}
    
    		// Parse each @Configuration class
    		ConfigurationClassParser parser = new ConfigurationClassParser(
    				this.metadataReaderFactory, this.problemReporter, this.environment,
    				this.resourceLoader, this.componentScanBeanNameGenerator, registry);
    
    		Set<BeanDefinitionHolder> candidates = new LinkedHashSet<BeanDefinitionHolder>(configCandidates);
    		Set<ConfigurationClass> alreadyParsed = new HashSet<ConfigurationClass>(configCandidates.size());
    		do {
    			parser.parse(candidates);
    			parser.validate();
    
    			Set<ConfigurationClass> configClasses = new LinkedHashSet<ConfigurationClass>(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);
    
    			candidates.clear();
    			if (registry.getBeanDefinitionCount() > candidateNames.length) {
    				String[] newCandidateNames = registry.getBeanDefinitionNames();
    				Set<String> oldCandidateNames = new HashSet<String>(Arrays.asList(candidateNames));
    				Set<String> alreadyParsedClasses = new HashSet<String>();
    				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) {
    			if (!sbr.containsSingleton(IMPORT_REGISTRY_BEAN_NAME)) {
    				sbr.registerSingleton(IMPORT_REGISTRY_BEAN_NAME, parser.getImportRegistry());
    			}
    		}
    
    		if (this.metadataReaderFactory instanceof CachingMetadataReaderFactory) {
    			((CachingMetadataReaderFactory) this.metadataReaderFactory).clearCache();
    		}
    	}
    

    我们只看我们之前查看源代码的parse方法那附近和后面就行了,有个do while循环解析那:

    do {
    			parser.parse(candidates);
    			parser.validate();
    
    			Set<ConfigurationClass> configClasses = new LinkedHashSet<ConfigurationClass>(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);
    
    			candidates.clear();
    			if (registry.getBeanDefinitionCount() > candidateNames.length) {
    				String[] newCandidateNames = registry.getBeanDefinitionNames();
    				Set<String> oldCandidateNames = new HashSet<String>(Arrays.asList(candidateNames));
    				Set<String> alreadyParsedClasses = new HashSet<String>();
    				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());
    

    parser.parse(candidates);后面是校验和创建配置类的Set。注意到有一个方法:

    this.reader.loadBeanDefinitions(configClasses);
    

    这个操作reader的loadBeanDefinitions比较贴近意思了,点进去看看:

    	/**
    	 * 读取 {@code configurationModel}, 根据其内容在registry中注册bean定义.
    	 */
    	public void loadBeanDefinitions(Set<ConfigurationClass> configurationModel) {
    		TrackedConditionEvaluator trackedConditionEvaluator = new TrackedConditionEvaluator();
    		for (ConfigurationClass configClass : configurationModel) {
    			loadBeanDefinitionsForConfigurationClass(configClass, trackedConditionEvaluator);
    		}
    	}
    

    这个注释提示得非常明显,继续跟进loadBeanDefinitionsForConfigurationClass:

    	/**
    	 * Read a particular {@link ConfigurationClass}, registering bean definitions
    	 * for the class itself and all of its {@link Bean} methods.
    	 */
    	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;
    		}
    
    		if (configClass.isImported()) {
    			registerBeanDefinitionForImportedConfigurationClass(configClass);
    		}
    		for (BeanMethod beanMethod : configClass.getBeanMethods()) {
    			loadBeanDefinitionsForBeanMethod(beanMethod);
    		}
    		loadBeanDefinitionsFromImportedResources(configClass.getImportedResources());
    		loadBeanDefinitionsFromRegistrars(configClass.getImportBeanDefinitionRegistrars());
    	}
    

    注意到里面有个重点啊:

    		for (BeanMethod beanMethod : configClass.getBeanMethods()) {
    			loadBeanDefinitionsForBeanMethod(beanMethod);
    		}
    

    这也太明显了哈,把配置的bean方法拿出来,一个个去加载,继续跟进:

    	/**
    	 * Read the given {@link BeanMethod}, registering bean definitions
    	 * with the BeanDefinitionRegistry based on its contents.
    	 */
    	private void loadBeanDefinitionsForBeanMethod(BeanMethod beanMethod) {
    		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;
    		}
    
    		// Consider name and any aliases
    		AnnotationAttributes bean = AnnotationConfigUtils.attributesFor(metadata, Bean.class);
    		List<String> names = new ArrayList<String>(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)) {
    			return;
    		}
    
    		ConfigurationClassBeanDefinition beanDef = new ConfigurationClassBeanDefinition(configClass, metadata);
    		beanDef.setResource(configClass.getResource());
    		beanDef.setSource(this.sourceExtractor.extractSource(metadata, configClass.getResource()));
    
    		if (metadata.isStatic()) {
    			// static @Bean method
    			beanDef.setBeanClassName(configClass.getMetadata().getClassName());
    			beanDef.setFactoryMethodName(methodName);
    		}
    		else {
    			// instance @Bean method
    			beanDef.setFactoryBeanName(configClass.getBeanName());
    			beanDef.setUniqueFactoryMethodName(methodName);
    		}
    		beanDef.setAutowireMode(RootBeanDefinition.AUTOWIRE_CONSTRUCTOR);
    		beanDef.setAttribute(RequiredAnnotationBeanPostProcessor.SKIP_REQUIRED_CHECK_ATTRIBUTE, Boolean.TRUE);
    
    		AnnotationConfigUtils.processCommonDefinitionAnnotations(beanDef, metadata);
    
    		Autowire autowire = bean.getEnum("autowire");
    		if (autowire.isAutowire()) {
    			beanDef.setAutowireMode(autowire.value());
    		}
    
    		String initMethodName = bean.getString("initMethod");
    		if (StringUtils.hasText(initMethodName)) {
    			beanDef.setInitMethodName(initMethodName);
    		}
    
    		String destroyMethodName = bean.getString("destroyMethod");
    		if (destroyMethodName != null) {
    			beanDef.setDestroyMethodName(destroyMethodName);
    		}
    
    		// Consider scoping
    		ScopedProxyMode proxyMode = ScopedProxyMode.NO;
    		AnnotationAttributes attributes = AnnotationConfigUtils.attributesFor(metadata, Scope.class);
    		if (attributes != null) {
    			beanDef.setScope(attributes.getString("value"));
    			proxyMode = attributes.getEnum("proxyMode");
    			if (proxyMode == ScopedProxyMode.DEFAULT) {
    				proxyMode = ScopedProxyMode.NO;
    			}
    		}
    
    		// Replace the original bean definition with the target one, if necessary
    		BeanDefinition beanDefToRegister = beanDef;
    		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);
    		}
    
    		if (logger.isDebugEnabled()) {
    			logger.debug(String.format("Registering bean definition for @Bean method %s.%s()",
    					configClass.getMetadata().getClassName(), beanName));
    		}
    
    		this.registry.registerBeanDefinition(beanName, beanDefToRegister);
    	}
    

    通过方法注释更加确定了,最后一句代码正是容器注册代码。

    我们大致来看看,前三句是把配置类拿出来、拿方法数据、方法名。后面两个判断是要看看要不要跳过,跳过就直接return了,不注册。再往后是把@Bean注解里的name对应的值拿出来,也就是别名拿出来并注册,后面也是各种把@Bean注解里的东西取出来操作,autowire模型(通过id还是name?)、initMethod、destroyMethod,各种细节配置就不多说了。最后通过this.registry.registerBeanDefinition就注册进去了

    值得注意的是beanName来自里面的:

    List<String> names = new ArrayList<String(Arrays.asList(bean.getStringArray("name")));
    String beanName = (!names.isEmpty() ? names.remove(0) : methodName);
    

    也就是你的@Bean注解里面没有写name的时候,实际上默认就是拿方法名做beanName了!

    至此,@Bean注解也分析完毕.

    至此ioc构造器的三大方法中的refresh(),里的invokeBeanFactoryPostProcessors的部分就讲完了,剩下的下篇文章继续分析。

  • 相关阅读:
    523. Continuous Subarray Sum
    517. Super Washing Machines
    516. Longest Palindromic Subsequence
    486. Predict the Winner
    467. Unique Substrings in Wraparound String
    474. Ones and Zeroes
    语法小结
    互评作业:使用数组
    466. Count The Repetitions
    1052 卖个萌 (20 分)
  • 原文地址:https://www.cnblogs.com/chz-blogs/p/11709996.html
Copyright © 2020-2023  润新知