Spring IOC 容器 源码阅读 和 | 介绍 debug | 一步一步 | 详细深入 | 解读源码 | 加阅读源码方法

先做个介绍

官方文档介绍

IoC也称为依赖注入(DI)。这是一个过程,通过这个过程,对象只能通过构造函数参数,工厂方法的参数或在构造或从工厂方法返回后在对象实例上设置的属性来定义它们的依赖关系(即,它们使用的其他对象)。 。然后容器在创建bean时注入这些依赖项。此过程基本上是bean本身的逆(因此名称,控制反转),通过使用类的直接构造或诸如服务定位器模式的机制来控制其依赖关系的实例化或位置。

使用DI原则的代码更清晰,当对象提供其依赖项时,解耦更有效。该对象不查找其依赖项,也不知道依赖项的位置或类。因此,您的类变得更容易测试,特别是当依赖关系在接口或抽象基类上时,这允许在单元测试中使用存根或模拟实现。

 

下面开始阅读源码

1准备工作、一共三个文件 

 

下边是一个maven String 项目的目录(看黄色部分的就好了)

Spring IOC 容器 源码阅读 和 | 介绍 debug | 一步一步 | 详细深入 | 解读源码 | 加阅读源码方法_第1张图片

 

一、Hello.java 类

package com.superman.test;

public class Hello {

	public void work() {
		System.out.println("来了哟!");
	}
}

 

二、spring-config-test.xml 配置文件



    
     
       
    
    

 

三、Test 测试启动类

package com.superman.test;

import com.superman.test.Hello;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.FileSystemXmlApplicationContext;

/**
 * 模拟以下ioc执行,顺便找下源码执行
 * 
 * @author yushen
 *
 */
public class Test {
	
    @SuppressWarnings("resource")
	public static void main(String[] args) throws ClassNotFoundException {
    	//读取xml(完成注入将控制权限交予spring)
		ApplicationContext ctx = new FileSystemXmlApplicationContext("src/main/resources/spring-config-test.xml");
        System.out.println("number : " + ctx.getBeanDefinitionCount());
        //调用方法(就是反转)
        ((Hello) ctx.getBean("Hello")).work();
        
    }
    
}

 

2.通过debug模式启动记得打个断点 开始注入bean对象

 

1创建新的filesystemxmlapplicationContext,加载定义,并自动刷新上下文。

/**
	 * Create a new FileSystemXmlApplicationContext, loading the definitions
	 * from the given XML file and automatically refreshing the context.
	 * @param configLocation file path
	 * @throws BeansException if context creation failed
	 */
	public FileSystemXmlApplicationContext(String configLocation) throws BeansException {
		this(new String[] {configLocation}, true, null);
	}

 

2使用给定的父级创建一个新的filesystemxmlapplicationContext,从给定的XML文件加载定义。

/**
	 * Create a new FileSystemXmlApplicationContext with the given parent,
	 * loading the definitions from the given XML files.
	 * @param configLocations array of file paths
	 * @param refresh whether to automatically refresh the context,
	 * loading all bean definitions and creating all singletons.
	 * Alternatively, call refresh manually after further configuring the context.
	 * @param parent the parent context
	 * @throws BeansException if context creation failed
	 * @see #refresh()
	 */
	public FileSystemXmlApplicationContext(String[] configLocations, boolean refresh, ApplicationContext parent)
			throws BeansException {
        //设置此应用程序上下文的父级。
		super(parent);
        //设置此应用程序上下文的配置位置
		setConfigLocations(configLocations);
        //刷新上下文
		if (refresh) {
			refresh();
		}
	}

 

3设置此应用程序上下文的父级。

/**
	 * Set the parent of this application context.
	 * 

The parent {@linkplain ApplicationContext#getEnvironment() environment} is * {@linkplain ConfigurableEnvironment#merge(ConfigurableEnvironment) merged} with * this (child) application context environment if the parent is non-{@code null} and * its environment is an instance of {@link ConfigurableEnvironment}. * @see ConfigurableEnvironment#merge(ConfigurableEnvironment) */ @Override public void setParent(ApplicationContext parent) { this.parent = parent; if (parent != null) { Environment parentEnvironment = parent.getEnvironment(); if (parentEnvironment instanceof ConfigurableEnvironment) { getEnvironment().merge((ConfigurableEnvironment) parentEnvironment); } } }

 

4.设置此应用程序上下文的配置位置。如果没有设置,则实现可以根据需要使用默认值。

/**
	 * Set the config locations for this application context.
	 * 

If not set, the implementation may use a default as appropriate. */ public void setConfigLocations(String... locations) { if (locations != null) { Assert.noNullElements(locations, "Config locations must not be null"); this.configLocations = new String[locations.length]; for (int i = 0; i < locations.length; i++) { this.configLocations[i] = resolvePath(locations[i]).trim(); } } else { this.configLocations = null; } }

 

5.刷新上下文

@Override
	public void refresh() throws BeansException, IllegalStateException {
		synchronized (this.startupShutdownMonitor) {
			// 准备刷新此上下文。
			prepareRefresh();

			// 告诉子类刷新内部bean工厂。
			ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

			// 准备bean工厂以便在此上下文中使用。
			prepareBeanFactory(beanFactory);

			try {
				//允许在上下文子类中对bean工厂进行后处理。
				postProcessBeanFactory(beanFactory);

				// 在上下文中调用注册为bean的工厂处理器。
				invokeBeanFactoryPostProcessors(beanFactory);

				//注册拦截bean创建的bean处理器。
				registerBeanPostProcessors(beanFactory);

				// 为此上下文初始化消息源。
				initMessageSource();

				// 为此上下文初始化事件多主机。
				initApplicationEventMulticaster();

				// 初始化特定上下文子类中的其他特殊bean。
				onRefresh();

				// 检查侦听器bean并注册它们。
				registerListeners();

				// 实例化所有剩余的(非lazy init)单例。
				finishBeanFactoryInitialization(beanFactory);

				// 最后一步:发布对应的事件。
				finishRefresh();
			}

			catch (BeansException ex) {
				if (logger.isWarnEnabled()) {
					logger.warn("Exception encountered during context initialization - " +
							"cancelling refresh attempt: " + ex);
				}

				// 销毁已经创建的单例以避免资源悬空。
				destroyBeans();

				// 重置“活动”标志。
				cancelRefresh(ex);

				// 将异常传播到调用方。
				throw ex;
			}

			finally {
				// 重置春天核心的常见内省缓存,因为我们
				// 可能不再需要用于singleton bean的元数据了…
				resetCommonCaches();
			}
		}
	}

 

6.准备刷新此上下文,设置其启动日期和,活动标志以及对属性源执行任何初始化。

/**
	 * Prepare this context for refreshing, setting its startup date and
	 * active flag as well as performing any initialization of property sources.
	 */
	protected void prepareRefresh() {
		this.startupDate = System.currentTimeMillis();
		this.closed.set(false);
		this.active.set(true);

		if (logger.isInfoEnabled()) {
			logger.info("Refreshing " + this);
		}

		// Initialize any placeholder property sources in the context environment
		initPropertySources();

		// Validate that all properties marked as required are resolvable
		// see ConfigurablePropertyResolver#setRequiredProperties
		getEnvironment().validateRequiredProperties();

		// Allow for the collection of early ApplicationEvents,
		// to be published once the multicaster is available...
		this.earlyApplicationEvents = new LinkedHashSet();
	}

 

7告诉子类刷新内部bean工厂。

/**
	 * Tell the subclass to refresh the internal bean factory.
	 * @return the fresh BeanFactory instance
	 * @see #refreshBeanFactory()
	 * @see #getBeanFactory()
	 */
	protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
		refreshBeanFactory();
		ConfigurableListableBeanFactory beanFactory = getBeanFactory();
		if (logger.isDebugEnabled()) {
			logger.debug("Bean factory for " + getDisplayName() + ": " + beanFactory);
		}
		return beanFactory;
	}

 

8配置工厂的标准上下文特征,*例如上下文的类加载器和后处理器。

/**
	 * Configure the factory's standard context characteristics,
	 * such as the context's ClassLoader and post-processors.
	 * @param beanFactory the BeanFactory to configure
	 */
	protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory) {
		// Tell the internal bean factory to use the context's class loader etc.
		beanFactory.setBeanClassLoader(getClassLoader());
		beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver(beanFactory.getBeanClassLoader()));
		beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this, getEnvironment()));

		// Configure the bean factory with context callbacks.
		beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));
		beanFactory.ignoreDependencyInterface(EnvironmentAware.class);
		beanFactory.ignoreDependencyInterface(EmbeddedValueResolverAware.class);
		beanFactory.ignoreDependencyInterface(ResourceLoaderAware.class);
		beanFactory.ignoreDependencyInterface(ApplicationEventPublisherAware.class);
		beanFactory.ignoreDependencyInterface(MessageSourceAware.class);
		beanFactory.ignoreDependencyInterface(ApplicationContextAware.class);

		// BeanFactory interface not registered as resolvable type in a plain factory.
		// MessageSource registered (and found for autowiring) as a bean.
		beanFactory.registerResolvableDependency(BeanFactory.class, beanFactory);
		beanFactory.registerResolvableDependency(ResourceLoader.class, this);
		beanFactory.registerResolvableDependency(ApplicationEventPublisher.class, this);
		beanFactory.registerResolvableDependency(ApplicationContext.class, this);

		// Register early post-processor for detecting inner beans as ApplicationListeners.
		beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(this));

		// Detect a LoadTimeWeaver and prepare for weaving, if found.
		if (beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {
			beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));
			// Set a temporary ClassLoader for type matching.
			beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));
		}

		// Register default environment beans.
		if (!beanFactory.containsLocalBean(ENVIRONMENT_BEAN_NAME)) {
			beanFactory.registerSingleton(ENVIRONMENT_BEAN_NAME, getEnvironment());
		}
		if (!beanFactory.containsLocalBean(SYSTEM_PROPERTIES_BEAN_NAME)) {
			beanFactory.registerSingleton(SYSTEM_PROPERTIES_BEAN_NAME, getEnvironment().getSystemProperties());
		}
		if (!beanFactory.containsLocalBean(SYSTEM_ENVIRONMENT_BEAN_NAME)) {
			beanFactory.registerSingleton(SYSTEM_ENVIRONMENT_BEAN_NAME, getEnvironment().getSystemEnvironment());
		}
	}

 

9在应用程序上下文的标准之后修改其内部bean工厂*初始化。所有bean定义都将被加载,但没有bean*将被实例化。这允许特殊注册

/**
	 * Modify the application context's internal bean factory after its standard
	 * initialization. All bean definitions will have been loaded, but no beans
	 * will have been instantiated yet. This allows for registering special
	 * BeanPostProcessors etc in certain ApplicationContext implementations.
	 * @param beanFactory the bean factory used by the application context
	 */
	protected void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) {
	}

 

10实例化并调用所有注册的BeanFactoryPostProcessorBean,*遵守明确的命令。*

必须在单例实例化之前调用。

/**
	 * Instantiate and invoke all registered BeanFactoryPostProcessor beans,
	 * respecting explicit order if given.
	 * 

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

 

11实例化并调用所有注册的beanPostProcessor bean,*遵守明确的命令。*

必须在应用程序bean的任何实例化之前调用。

/**
	 * Instantiate and invoke all registered BeanPostProcessor beans,
	 * respecting explicit order if given.
	 * 

Must be called before any instantiation of application beans. */ protected void registerBeanPostProcessors(ConfigurableListableBeanFactory beanFactory) { PostProcessorRegistrationDelegate.registerBeanPostProcessors(beanFactory, this); }

 

12*初始化消息源。*如果在此上下文中没有定义,则使用父级。

/**
	 * Initialize the MessageSource.
	 * Use parent's if none defined in this context.
	 */
	protected void initMessageSource() {
		ConfigurableListableBeanFactory beanFactory = getBeanFactory();
		if (beanFactory.containsLocalBean(MESSAGE_SOURCE_BEAN_NAME)) {
			this.messageSource = beanFactory.getBean(MESSAGE_SOURCE_BEAN_NAME, MessageSource.class);
			// Make MessageSource aware of parent MessageSource.
			if (this.parent != null && this.messageSource instanceof HierarchicalMessageSource) {
				HierarchicalMessageSource hms = (HierarchicalMessageSource) this.messageSource;
				if (hms.getParentMessageSource() == null) {
					// Only set parent context as parent MessageSource if no parent MessageSource
					// registered already.
					hms.setParentMessageSource(getInternalParentMessageSource());
				}
			}
			if (logger.isDebugEnabled()) {
				logger.debug("Using MessageSource [" + this.messageSource + "]");
			}
		}
		else {
			// Use empty MessageSource to be able to accept getMessage calls.
			DelegatingMessageSource dms = new DelegatingMessageSource();
			dms.setParentMessageSource(getInternalParentMessageSource());
			this.messageSource = dms;
			beanFactory.registerSingleton(MESSAGE_SOURCE_BEAN_NAME, this.messageSource);
			if (logger.isDebugEnabled()) {
				logger.debug("Unable to locate MessageSource with name '" + MESSAGE_SOURCE_BEAN_NAME +
						"': using default [" + this.messageSource + "]");
			}
		}
	}

 

13初始化ApplicationEventMulticaster。*如果上下文中没有定义,则使用SimpleApplicationEventMulticaster。

/**
	 * Initialize the ApplicationEventMulticaster.
	 * Uses SimpleApplicationEventMulticaster if none defined in the context.
	 * @see org.springframework.context.event.SimpleApplicationEventMulticaster
	 */
	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 + "]");
			}
		}
	}

 

14模板方法,可被重写以添加特定于上下文的刷新工作。*在实例化单例之前调用特殊bean的初始化。

/**
	 * Template method which can be overridden to add context-specific refresh work.
	 * Called on initialization of special beans, before instantiation of singletons.
	 * 

This implementation is empty. * @throws BeansException in case of errors * @see #refresh() */ protected void onRefresh() throws BeansException { // For subclasses: do nothing by default. }

 

15添加将ApplicationListener实现为侦听器的bean。*不会影响其他侦听器,这些侦听器可以在不使用bean的情况下添加。

/**
	 * Add beans that implement ApplicationListener as listeners.
	 * Doesn't affect other listeners, which can be added without being beans.
	 */
	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 earlyEventsToProcess = this.earlyApplicationEvents;
		this.earlyApplicationEvents = null;
		if (earlyEventsToProcess != null) {
			for (ApplicationEvent earlyEvent : earlyEventsToProcess) {
				getApplicationEventMulticaster().multicastEvent(earlyEvent);
			}
		}
	}

 

16完成此上下文的bean工厂的初始化,*正在初始化所有剩余的单例bean。

/**
	 * Finish the initialization of this context's bean factory,
	 * initializing all remaining singleton beans.
	 */
	protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {
		// Initialize conversion service for this context.
		if (beanFactory.containsBean(CONVERSION_SERVICE_BEAN_NAME) &&
				beanFactory.isTypeMatch(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class)) {
			beanFactory.setConversionService(
					beanFactory.getBean(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class));
		}

		// Register a default embedded value resolver if no bean post-processor
		// (such as a PropertyPlaceholderConfigurer bean) registered any before:
		// at this point, primarily for resolution in annotation attribute values.
		if (!beanFactory.hasEmbeddedValueResolver()) {
			beanFactory.addEmbeddedValueResolver(new StringValueResolver() {
				@Override
				public String resolveStringValue(String strVal) {
					return getEnvironment().resolvePlaceholders(strVal);
				}
			});
		}

		// Initialize LoadTimeWeaverAware beans early to allow for registering their transformers early.
		String[] weaverAwareNames = beanFactory.getBeanNamesForType(LoadTimeWeaverAware.class, false, false);
		for (String weaverAwareName : weaverAwareNames) {
			getBean(weaverAwareName);
		}

		// Stop using the temporary ClassLoader for type matching.
		beanFactory.setTempClassLoader(null);

		// Allow for caching all bean definition metadata, not expecting further changes.
		beanFactory.freezeConfiguration();

		// Instantiate all remaining (non-lazy-init) singletons.
		beanFactory.preInstantiateSingletons();
	}

 

17完成此上下文的刷新,调用LifecycleProcessor的*onrefresh()方法并发布

/**
	 * Finish the refresh of this context, invoking the LifecycleProcessor's
	 * onRefresh() method and publishing the
	 * {@link org.springframework.context.event.ContextRefreshedEvent}.
	 */
	protected void finishRefresh() {
		// Initialize lifecycle processor for this context.
		initLifecycleProcessor();

		// Propagate refresh to lifecycle processor first.
		getLifecycleProcessor().onRefresh();

		// Publish the final event.
		publishEvent(new ContextRefreshedEvent(this));

		// Participate in LiveBeansView MBean, if active.
		LiveBeansView.registerApplicationContext(this);
	}

 

18 如果报错异》常用于销毁此上下文管理的所有bean的模板方法。*默认实现销毁此上下文中所有缓存的单例,

/**
	 * Template method for destroying all beans that this context manages.
	 * The default implementation destroy all cached singletons in this context,
	 * invoking {@code DisposableBean.destroy()} and/or the specified
	 * "destroy-method".
	 * 

Can be overridden to add context-specific bean destruction steps * right before or right after standard singleton destruction, * while the context's BeanFactory is still active. * @see #getBeanFactory() * @see org.springframework.beans.factory.config.ConfigurableBeanFactory#destroySingletons() */ protected void destroyBeans() { getBeanFactory().destroySingletons(); }

 

19如果报错异》取消此上下文的刷新尝试,重置@code active标志*在抛出异常之后。

/**
	 * Cancel this context's refresh attempt, resetting the {@code active} flag
	 * after an exception got thrown.
	 * @param ex the exception that led to the cancellation
	 */
	protected void cancelRefresh(BeansException ex) {
		this.active.set(false);
	}

 

20重置Spring的通用核心缓存,特别是@link reflectionutils,

/**
	 * Reset Spring's common core caches, in particular the {@link ReflectionUtils},
	 * {@link ResolvableType} and {@link CachedIntrospectionResults} caches.
	 * @since 4.2
	 * @see ReflectionUtils#clearCache()
	 * @see ResolvableType#clearCache()
	 * @see CachedIntrospectionResults#clearClassLoader(ClassLoader)
	 */
	protected void resetCommonCaches() {
		ReflectionUtils.clearCache();
		ResolvableType.clearCache();
		CachedIntrospectionResults.clearClassLoader(getClassLoader());
	}

 

下面就是调用 bean 的方法

1 调用工厂 并调用方法

//调用方法(就是反转)
        ((Hello) ctx.getBean("Hello")).work();

2.调用getBean 调用bean 

@Override
	public Object getBean(String name) throws BeansException {
		assertBeanFactoryActive();
		return getBeanFactory().getBean(name);
	}

3.断言此上下文的BeanFactory当前处于活动状态,*如果没有,则引发@link illegalStateException。

/**
	 * Assert that this context's BeanFactory is currently active,
	 * throwing an {@link IllegalStateException} if it isn't.
	 * 

Invoked by all {@link BeanFactory} delegation methods that depend * on an active context, i.e. in particular all bean accessor methods. *

The default implementation checks the {@link #isActive() 'active'} status * of this context overall. May be overridden for more specific checks, or for a * no-op if {@link #getBeanFactory()} itself throws an exception in such a case. */ protected void assertBeanFactoryActive() { if (!this.active.get()) { if (this.closed.get()) { throw new IllegalStateException(getDisplayName() + " has been closed already"); } else { throw new IllegalStateException(getDisplayName() + " has not been refreshed yet"); } } }

 

4.执行方法

public void work() {
		System.out.println("来了哟!");
	}

 

5.系统调用此方法以提供线程*有机会在它真正退出之前清理干净。

 /**
     * This method is called by the system to give a Thread
     * a chance to clean up before it actually exits.
     */
    private void exit() {
        if (group != null) {
            group.threadTerminated(this);
            group = null;
        }
        /* Aggressively null out all reference fields: see bug 4006245 */
        target = null;
        /* Speed the release of some of these resources */
        threadLocals = null;
        inheritableThreadLocals = null;
        inheritedAccessControlContext = null;
        blocker = null;
        uncaughtExceptionHandler = null;
    }

 

6.通知组线程@code t已终止。

/**
     * Notifies the group that the thread {@code t} has terminated.
     *
     * 

Destroy the group if all of the following conditions are * true: this is a daemon thread group; there are no more alive * or unstarted threads in the group; there are no subgroups in * this thread group. * * @param t * the Thread that has terminated */ void threadTerminated(Thread t) { synchronized (this) { remove(t); if (nthreads == 0) { notifyAll(); } if (daemon && (nthreads == 0) && (nUnstartedThreads == 0) && (ngroups == 0)) { destroy(); } } }

 

完毕!

到这里整个 ioc 控制反转流程就 走完喽

 

总结

简单介绍ioc控制反转:

  • 解释:1先将类注入到spring 的BeanFactory工厂中2.在执行类的时候3.由工厂来调用类及方法
  • 实现:1.ioc 的di 依赖注入 到工厂 2.执行控制权交给工厂3.工厂调用方法

 

 

文章会根据spring版本 持续更新

转载文章表明出处,方便看到最新更新的内容

https://blog.csdn.net/weixin_42749765/article/details/87188998

 

 

 

 

 

 

 

你可能感兴趣的:(spring,ioc,源码解读,spring,ioc,源码解读,spring,ioc,源码解读)