Spring core principle

Java Bean (java bean is evolved by the Applet Bean) ------------> EJB (Enterprise java beans) ---------> POJO (plain ordinary java Obect, simple the java bean)

 

Four basic strategies to simplify the development of Spring

1, based on lightweight and minimally invasive programming of POJO

2, through the interface for loose coupling and dependency injection

3, based on declarative programming section and inertia

4, by reducing the section and the stencil-like format codes

 

The relationship between AOP, DI, IOC

The AOP (Aspect Oriented Programming) dependent IOC, DI (DI) depends IOC (inversion control)

 

 

Spring core module
Module Name The main function
spring-core IOC dependency injection to achieve the most basic and DI
spring-beans Bean and Bean factory assembly
spring-context Spring basis for the definition of the context Context (sub-tank)
spring-context-support Extended Support for spring ioc containers, sub-containers and IOC
spring-context-indexer Spring classes set up and manage Classpath scanning
spring-expression Spring Expression Language
   
   
   
   
   

 


 

 

 

 

 

 

 

 

 

 

 

 

 

The basic idea of ​​the realization of Spring

1, the configuration phase

Configuring web.xml: Dispatcher Servlet

Setting init-param: contextConfigLocation = classpath: application.xml

Set url-pattern: / *

配置Annotation:@Controller  @Service  @Autowrited   @RequsetMapping

 

2, the initialization phase

Call the init () method: loading a configuration file

IOC initialization container: Map <String, Object>

Scan-classes: scan-package = "com.tealala"

IOC -> and saved to create an instance of the container: by reflex mechanisms instantiate the class into vessel IOC

DI ----> for DI Operation: Example scanning IOC container, not assigned to an attribute assigned automatically

MVC -> Initialization HandlerMapping: Method a URL and a one to one association mapping Map <String, Method>

 

3, the operational phase

Call doPost () / doGet (): web container calls doPost / doGet way, a request / response objects

Match HandlerMapping: url obtaining request object from a user input, find the corresponding Method

Reflection to invoke method.invoker (): method call by reflection and returns the result

response.getWrite () write ():. outputs the result to the browser

 

 

IOC (Inversion of Control) Control Reverse: creates object code to be achieved, dependent on the code to inverting the container to help achieve.

DI (Dependency Injection) DI: it is dependent on the object class is not passively to find their own initiative, in other words, it means the object is not dependent on the class to find from the container, but it will be active at the time the container object is instantiated injection of dependent classes to it.

 

The relationship between the object and how to identify objects: xml / properties

Description of object-relational file storage Where: classpath / network / filesystem / servletContext

How unified standard configuration file: BeanDefinition

How to parse different profiles: Strategy Mode

 

BeanFactory: responsible for defining the container

BeanDefinition: responsible for storing configuration information

BeanDefinitionReader: responsible for reading configuration information

 

spring IOC container initialization trilogy:

Positioning (locate the configuration file and scan-related comments)

Loading (loading configuration information into memory)

Register (The information loaded by the IOC to the object initialization container)

 

FIG Spring core container class

1、BeanFactory

Spring bean factory to create a typical pattern, this series of Bean plants, namely IOC container provides a lot of convenience and basic services for the dependencies between developers managed objects, have realized for many of the IOC containers in Spring user selection and use, the following relationships:

Wherein, as the topmost layer of the BeanFactory an interface class, which defines the basic functional specification IOC containers, the BeanFactory three important subclasses: ListableBeanFactory, HierachicalBeanFactory and AutowireCapableBeanFactory. The final default implementation class is DefaultListableBeanFactory, it implements all interfaces.

It has different interface usage scenario, in order to distinguish primarily confined inside Spring during the conversion process and transfer operation of objects, data access to an object made. For example: ListableBeanFactory interface represents Bean is a list of these, and HierachicalBeanFactory indicate that these are Bean's inheritance, automatic assembly rules AutowireCapableBeanFactory Bean's interface definition. The three interfaces together define the relationship between the collection Bean, Bean, Bean and behavior.

To know how the plant is to produce objects, we need to see concrete realization of the IOC container, Spring provides an implementation of many of the IOC container. For example: GenericApplicationContext, ClasspathXmlApplicationContext and so on.

 

ApplicationContext is a senior IOC containers Spring offers, in addition to its basic functions to provide the IOC container, but also provides users with additional services. ApplicationContext from the interface implementation can be seen that has the following characteristics:

1, support information source, internationalization (MessageSource implements the interface)

2, access to resources (ResourcePatternResolver implement interfaces)

3, support for application events (ApplictionEventPublisher implement interfaces)

 

2、BeanDefinition

SpringIOC container management we define a variety of Bean object of their mutual relations, Bean implementation is subject to BeanDefinition described in the Spring, its inheritance as follows:

 

3、BeanDefinitionReader

Bean resolution process is very complex, functions are broken down, more expansion, we must ensure that there is sufficient flexibility to cope with possible changes. Bean resolution mainly to resolve the Spring configuration file. The resolution process is mainly done by BeanDefinitionReader. Its class structure is as follows:

 

WebIOC container first experience:

DispatcherServlet, the most important thing is the init method, but did not find the init method in DispatcherServlet, after recourse to find the init () method in HttpServletBean parent class: as follows:

@Override
	public final void init() throws ServletException {
		if (logger.isDebugEnabled()) {
			logger.debug("Initializing servlet '" + getServletName() + "'");
		}

		// Set bean properties from init parameters.
		PropertyValues pvs = new ServletConfigPropertyValues(getServletConfig(), this.requiredProperties);
		if (!pvs.isEmpty()) {
			try {
				//定位资源
				BeanWrapper bw = PropertyAccessorFactory.forBeanPropertyAccess(this);
				//加载配置信息
				ResourceLoader resourceLoader = new ServletContextResourceLoader(getServletContext());
				bw.registerCustomEditor(Resource.class, new ResourceEditor(resourceLoader, getEnvironment()));
				initBeanWrapper(bw);
				bw.setPropertyValues(pvs, true);
			}
			catch (BeansException ex) {
				if (logger.isErrorEnabled()) {
					logger.error("Failed to set bean properties on servlet '" + getServletName() + "'", ex);
				}
				throw ex;
			}
		}

		// Let subclasses do whatever initialization they like.
		initServletBean();

		if (logger.isDebugEnabled()) {
			logger.debug("Servlet '" + getServletName() + "' configured successfully");
		}
	}

 In the init () method, we find the logic initialization container is in fact initServletBean () method, and this method has been implemented in FrameworkServlet class,

@Override
	protected final void initServletBean() throws ServletException {
		getServletContext().log("Initializing Spring FrameworkServlet '" + getServletName() + "'");
		if (this.logger.isInfoEnabled()) {
			this.logger.info("FrameworkServlet '" + getServletName() + "': initialization started");
		}
		long startTime = System.currentTimeMillis();

		try {

			this.webApplicationContext = initWebApplicationContext();
			initFrameworkServlet();
		}
		catch (ServletException ex) {
			this.logger.error("Context initialization failed", ex);
			throw ex;
		}
		catch (RuntimeException ex) {
			this.logger.error("Context initialization failed", ex);
			throw ex;
		}

		if (this.logger.isInfoEnabled()) {
			long elapsedTime = System.currentTimeMillis() - startTime;
			this.logger.info("FrameworkServlet '" + getServletName() + "': initialization completed in " +
					elapsedTime + " ms");
		}
	}

 

The method herein initWebApplicationContext ()

protected WebApplicationContext initWebApplicationContext() {

		//先从ServletContext中获得父容器WebAppliationContext
		WebApplicationContext rootContext =
				WebApplicationContextUtils.getWebApplicationContext(getServletContext());
		//声明子容器
		WebApplicationContext wac = null;

		//建立父、子容器之间的关联关系
		if (this.webApplicationContext != null) {
			// A context instance was injected at construction time -> use it
			wac = this.webApplicationContext;
			if (wac instanceof ConfigurableWebApplicationContext) {
				ConfigurableWebApplicationContext cwac = (ConfigurableWebApplicationContext) wac;
				if (!cwac.isActive()) {
					// The context has not yet been refreshed -> provide services such as
					// setting the parent context, setting the application context id, etc
					if (cwac.getParent() == null) {
						// The context instance was injected without an explicit parent -> set
						// the root application context (if any; may be null) as the parent
						cwac.setParent(rootContext);
					}
					//这个方法里面调用了AbatractApplication的refresh()方法
					//模板方法,规定IOC初始化基本流程
					configureAndRefreshWebApplicationContext(cwac);
				}
			}
		}
		//先去ServletContext中查找Web容器的引用是否存在,并创建好默认的空IOC容器
		if (wac == null) {
			// No context instance was injected at construction time -> see if one
			// has been registered in the servlet context. If one exists, it is assumed
			// that the parent context (if any) has already been set and that the
			// user has performed any initialization such as setting the context id
			wac = findWebApplicationContext();
		}
		//给上一步创建好的IOC容器赋值
		if (wac == null) {
			// No context instance is defined for this servlet -> create a local one
			wac = createWebApplicationContext(rootContext);
		}

		//触发onRefresh方法
		if (!this.refreshEventReceived) {
			// Either the context is not a ConfigurableApplicationContext with refresh
			// support or the context injected at construction time had already been
			// refreshed -> trigger initial onRefresh manually here.
			onRefresh(wac);
		}

		if (this.publishContext) {
			// Publish the context as a servlet context attribute.
			String attrName = getServletContextAttributeName();
			getServletContext().setAttribute(attrName, wac);
			if (this.logger.isDebugEnabled()) {
				this.logger.debug("Published WebApplicationContext of servlet '" + getServletName() +
						"' as ServletContext attribute with name [" + attrName + "]");
			}
		}

		return wac;
	}
protected void configureAndRefreshWebApplicationContext(ConfigurableWebApplicationContext wac) {
		if (ObjectUtils.identityToString(wac).equals(wac.getId())) {
			// The application context id is still set to its original default value
			// -> assign a more useful id based on available information
			if (this.contextId != null) {
				wac.setId(this.contextId);
			}
			else {
				// Generate default id...
				wac.setId(ConfigurableWebApplicationContext.APPLICATION_CONTEXT_ID_PREFIX +
						ObjectUtils.getDisplayString(getServletContext().getContextPath()) + '/' + getServletName());
			}
		}

		wac.setServletContext(getServletContext());
		wac.setServletConfig(getServletConfig());
		wac.setNamespace(getNamespace());
		wac.addApplicationListener(new SourceFilteringListener(wac, new ContextRefreshListener()));

		// The wac environment's #initPropertySources will be called in any case when the context
		// is refreshed; do it eagerly here to ensure servlet property sources are in place for
		// use in any post-processing or initialization that occurs below prior to #refresh
		ConfigurableEnvironment env = wac.getEnvironment();
		if (env instanceof ConfigurableWebEnvironment) {
			((ConfigurableWebEnvironment) env).initPropertySources(getServletContext(), getServletConfig());
		}

		postProcessWebApplicationContext(wac);
		applyInitializers(wac);
		wac.refresh();
	}

configureAndRefreshWebApplicationContext method refresh () method is actually started inlet IOC container, after the container is initialized, the call DispathcerServlet OnRefresh () method, onfresh () method call has nine components SpringMVC initStrategies method initializes as follows:

@Override
	protected void onRefresh(ApplicationContext context) {
		initStrategies(context);
	}

	/**
	 * Initialize the strategy objects that this servlet uses.
	 * <p>May be overridden in subclasses in order to initialize further strategy objects.
	 */
	//初始化策略
	protected void initStrategies(ApplicationContext context) {
		//多文件上传的组件
		initMultipartResolver(context);
		//初始化本地语言环境
		initLocaleResolver(context);
		//初始化模板处理器
		initThemeResolver(context);
		//handlerMapping
		initHandlerMappings(context);
		//初始化参数适配器
		initHandlerAdapters(context);
		//初始化异常拦截器
		initHandlerExceptionResolvers(context);
		//初始化视图预处理器
		initRequestToViewNameTranslator(context);
		//初始化视图转换器
		initViewResolvers(context);
		//
		initFlashMapManager(context);
	}

 

XML-based IOC container initialization:

Resource Initialization IOC container comprises BeanDefinition positioning, loading and registering of these three basic processes. Now with ApplicationContext example,

ApplicationContext allow nesting context, a context may be maintained by holding down the parent system, may take place for finding Bean system in this context, checks the current context, followed by parent context, step by step upwards, thus providing for different applications Spring Bean definition of a shared environment.

1, to find the entrance

ClassPathXmlApplicationContext, () method starts by mian:

ApplicationContext app = new ClassPathXmlApplicationContext("application.xml");

Calling its constructor:

public ClassPathXmlApplicationContext(String[] configLocations, boolean refresh) throws BeansException {
		this(configLocations, refresh, null);
	}


public ClassPathXmlApplicationContext(
			String[] configLocations, boolean refresh, @Nullable ApplicationContext parent)
			throws BeansException {

		super(parent);
		setConfigLocations(configLocations);
		if (refresh) {
			refresh();
		}
	}

Similar ClassPathXmlApplicationContext there AnnotationApplicationContext, FileSystemXmlApplicationContext, XmlWebApplicationContext are all inherited from the parent container AbstractApplicationContext, the main use of the decorator pattern and strategy pattern, eventually calling the refresh () method;

 

 

2, the path configuration is obtained

When creating ClassPathXmlApplicationContext container construction method there are two important jobs:

1, call the parent container constructor super (parent) to set up Bean container resource loader.

2, call the parent class of AbstractRefreshableConfigApplicationConext setConfigLocations (configLocations) Bean configure the positioning method set route information. By the above structure class diagram, ClassPathApplicationContext succession system, the discovery made by the parent class is initialized AbstractApplicationContext IOC container main source as follows:

public abstract class AbstractApplicationContext extends DefaultResourceLoader
		implements ConfigurableApplicationContext {
//静态初始化块,在整个容器创建过程中只执行一次
	static {
		// Eagerly load the ContextClosedEvent class to avoid weird classloader issues
		// on application shutdown in WebLogic 8.1. (Reported by Dustin Woods.)
		//为了避免应用程序在Weblogic8.1关闭时出现类加载异常加载问题,加载IoC容
		//器关闭事件(ContextClosedEvent)类
		ContextClosedEvent.class.getName();
	}

/**
	 * Create a new AbstractApplicationContext with no parent.
	 */
	public AbstractApplicationContext() {
		this.resourcePatternResolver = getResourcePatternResolver();
	}

	/**
	 * Create a new AbstractApplicationContext with the given parent context.
	 * @param parent the parent context
	 */
	public AbstractApplicationContext(@Nullable ApplicationContext parent) {
		this();
		setParent(parent);
	}

//获取一个Spring Source的加载器用于读入Spring Bean定义资源文件
	protected ResourcePatternResolver getResourcePatternResolver() {
		//AbstractApplicationContext继承DefaultResourceLoader,因此也是一个资源加载器
		//Spring资源加载器,其getResource(String location)方法用于载入资源
		return new PathMatchingResourcePatternResolver(this);
	}


@Override
	public void setParent(@Nullable ApplicationContext parent) {
		this.parent = parent;
		if (parent != null) {
			Environment parentEnvironment = parent.getEnvironment();
			if (parentEnvironment instanceof ConfigurableEnvironment) {
				getEnvironment().merge((ConfigurableEnvironment) parentEnvironment);
			}
		}
	}



}

Call the constructor method PathMatchingResourcePatternResolver default constructor AbstractApplicationContext created in Spring resource loader:

public PathMatchingResourcePatternResolver(ResourceLoader resourceLoader) {
		Assert.notNull(resourceLoader, "ResourceLoader must not be null");
		//设置Spring的资源加载器
		this.resourceLoader = resourceLoader;
	}

After setting the container resource loader next execution ClassPathXmlApplicationContext setConfigLocations () method to locate configuration information Bean by calling the method of the parent class AbstractRefreshableConfigApplicationContext:

//解析Bean定义资源文件的路径,处理多个资源文件字符串数组
	public void setConfigLocations(@Nullable 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++) {
				// resolvePath为同一个类中将字符串解析为路径的方法
				this.configLocations[i] = resolvePath(locations[i]).trim();
			}
		}
		else {
			this.configLocations = null;
		}
	}

The argument list may be modified by the process can be seen, we can either use a string configuration to configuration information of the plurality Spring Bean, using a string array, may be used "resource files between a plurality of paths,; \ t \ n "and so isolated.

ClassPathResource res = new ClassPathResource(new String[]{"aa.xml","bbb.xml"});

Thus, SpringIOC container upon initialization Bean configuration package configuration information to the positioning Spring Resource

 

3, started

SpringIOC Bean container loaded on the allocation of resources is () function starts refresh, refresh () method is a template, the provisions of the IOC container to start the process, some logic to the subclass to achieve, its configuration of resources contained Bean ClassPathXmlApplicationContext boot loader into the container during the whole of the IOC Bean defined by parent class AbstractApplicationContext call refresh () method, the following logic:

@Override
	public void refresh() throws BeansException, IllegalStateException {
		synchronized (this.startupShutdownMonitor) {
			// Prepare this context for refreshing.
			//1、调用容器准备刷新的方法,获取容器的当时时间,同时给容器设置同步标识
			prepareRefresh();

			// Tell the subclass to refresh the internal bean factory.
			//2、告诉子类启动refreshBeanFactory()方法,Bean定义资源文件的载入从
			//子类的refreshBeanFactory()方法启动
			ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

			// Prepare the bean factory for use in this context.
			//3、为BeanFactory配置容器特性,例如类加载器、事件处理器等
			prepareBeanFactory(beanFactory);

			try {
				// Allows post-processing of the bean factory in context subclasses.
				//4、为容器的某些子类指定特殊的BeanPost事件处理器
				postProcessBeanFactory(beanFactory);

				// Invoke factory processors registered as beans in the context.
				//5、调用所有注册的BeanFactoryPostProcessor的Bean
				invokeBeanFactoryPostProcessors(beanFactory);

				// Register bean processors that intercept bean creation.
				//6、为BeanFactory注册BeanPost事件处理器.
				//BeanPostProcessor是Bean后置处理器,用于监听容器触发的事件
				registerBeanPostProcessors(beanFactory);

				// Initialize message source for this context.
				//7、初始化信息源,和国际化相关.
				initMessageSource();

				// Initialize event multicaster for this context.
				//8、初始化容器事件传播器.
				initApplicationEventMulticaster();

				// Initialize other special beans in specific context subclasses.
				//9、调用子类的某些特殊Bean初始化方法
				onRefresh();

				// Check for listener beans and register them.
				//10、为事件传播器注册事件监听器.
				registerListeners();

				// Instantiate all remaining (non-lazy-init) singletons.
				//11、初始化所有剩余的单例Bean
				finishBeanFactoryInitialization(beanFactory);

				// Last step: publish corresponding event.
				//12、初始化容器的生命周期事件处理器,并发布容器的生命周期事件
				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.
				//13、销毁已创建的Bean
				destroyBeans();

				// Reset 'active' flag.
				//14、取消refresh操作,重置容器的同步标识。
				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...
				//15、重设公共缓存
				resetCommonCaches();
			}
		}
	}

refresh () method IOC container Bean lifecycle management provides conditions for the primary, SpringIOC Bean container loading configuration information () method to start its subclasses refreshBeanFactory container, the entire refresh () in

ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

After these words of the code is the registration information source and lifecycle events vessel.

The main role refresh () method is: between the IOC to create a container, the container if there is already in existence, you need to make the existing container destruction and shut down to ensure that the use of after refresh is set up IOC container. It is similar to the restart of the IOC containers, container is initialized in the new-established container, Bean allocation of resources to be loaded.

 

4. Create a container

obtainFreshBeanFactory () method is called in the sub-container refreshBeanFactory () method, starting container loading process Bean configuration information as follows:

protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
		//这里使用了委派设计模式,父类定义了抽象的refreshBeanFactory()方法,具体实现调用子类容器的refreshBeanFactory()方法
		refreshBeanFactory();
		ConfigurableListableBeanFactory beanFactory = getBeanFactory();
		if (logger.isDebugEnabled()) {
			logger.debug("Bean factory for " + getDisplayName() + ": " + beanFactory);
		}
		return beanFactory;
	}

AbstractApplicationContext abstract class only defines refreshBeanFactory () method, the container is actually invoked its subclasses AbstractRefreshableApplicationContext implemented refreshBeanFactory () method as follows:

@Override
	protected final void refreshBeanFactory() throws BeansException {
		//如果已经有容器,销毁容器中的bean,关闭容器
		if (hasBeanFactory()) {
			destroyBeans();
			closeBeanFactory();
		}
		try {
			//创建IOC容器
			DefaultListableBeanFactory beanFactory = createBeanFactory();
			beanFactory.setSerializationId(getId());
			//对IOC容器进行定制化,如设置启动参数,开启注解的自动装配等
			customizeBeanFactory(beanFactory);
			//调用载入Bean定义的方法,主要这里又使用了一个委派模式,在当前类中只定义了抽象的loadBeanDefinitions方法,具体的实现调用子类容器
			loadBeanDefinitions(beanFactory);
			synchronized (this.beanFactoryMonitor) {
				this.beanFactory = beanFactory;
			}
		}
		catch (IOException ex) {
			throw new ApplicationContextException("I/O error parsing bean definition source for " + getDisplayName(), ex);
		}
	}

The process first determines whether there BeanFactory, if present in the bean container destroying the container, closing the container, and then create DefaultListableBeanFactory, and calls loadBeanDefinitions (beanFactory) loading bean definition.

 

5, loading configuration path

AbstractRefreshableApplicatioonContext only defines abstract loadBeanDefinitions method, the container is actually call the method implemented AbstractXmlApplicationContext subclass, the main source AbstractXmlApplicationContext follows:

loadBeanDefinition still abstract method needs to be achieved subclass,

public abstract class AbstractXmlApplicationContext extends AbstractRefreshableConfigApplicationContext {

	private boolean validating = true;


@Override
	protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) throws BeansException, IOException {
		// Create a new XmlBeanDefinitionReader for the given BeanFactory.
		//创建XmlBeanDefinitionReader,即创建Bean读取器,并通过回调设置到容器中去,容器使用该读取器读取Bean定义资源
		XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory);

		// Configure the bean definition reader with this context's
		// resource loading environment.
		//为Bean读取器设置Spring资源加载器,AbstractXmlApplicationContext的
		//祖先父类AbstractApplicationContext继承DefaultResourceLoader,因此,容器本身也是一个资源加载器
		beanDefinitionReader.setEnvironment(this.getEnvironment());
		beanDefinitionReader.setResourceLoader(this);
		//为Bean读取器设置SAX xml解析器
		beanDefinitionReader.setEntityResolver(new ResourceEntityResolver(this));

		// Allow a subclass to provide custom initialization of the reader,
		// then proceed with actually loading the bean definitions.
		//当Bean读取器读取Bean定义的Xml资源文件时,启用Xml的校验机制
		initBeanDefinitionReader(beanDefinitionReader);
		//Bean读取器真正实现加载的方法
		loadBeanDefinitions(beanDefinitionReader);
	}


protected void initBeanDefinitionReader(XmlBeanDefinitionReader reader) {
		reader.setValidating(this.validating);
	}


//Xml Bean读取器加载Bean定义资源
	protected void loadBeanDefinitions(XmlBeanDefinitionReader reader) throws BeansException, IOException {
		//获取Bean定义资源的定位
		Resource[] configResources = getConfigResources();
		if (configResources != null) {
			//Xml Bean读取器调用其父类AbstractBeanDefinitionReader读取定位
			//的Bean定义资源
			reader.loadBeanDefinitions(configResources);
		}
		//如果子类中获取的Bean定义资源定位为空,则获取FileSystemXmlApplicationContext构造方法中setConfigLocations方法设置的资源
		String[] configLocations = getConfigLocations();
		if (configLocations != null) {
			//Xml Bean读取器调用其父类AbstractBeanDefinitionReader读取定位
			//的Bean定义资源
			reader.loadBeanDefinitions(configLocations);
		}
	}


//这里又使用了一个委托模式,调用子类的获取Bean定义资源定位的方法
	//该方法在ClassPathXmlApplicationContext中进行实现,对于我们
	//举例分析源码的FileSystemXmlApplicationContext没有使用该方法
	@Nullable
	protected Resource[] getConfigResources() {
		return null;
	}



}

To XmlBean reader One strategy XmlBeanDefinitionReader example. XmlBeanDefinitionReader call reader.loadBeanDefinitions the parent AbstractBeanDefinitionReader () method reads Bean allocation of resources. Since we use as an example ClassPathXmlApplicationContext analysis, so the return value of getConfigResources null, so program execution reader.loadBeanDefinitions (configLocations) branch.

 

6, the path allocation processing policy

In the abstract parent class AbstractBeanDefinitionReader XmlBeanDefinitionReader defined in the loading process.

AbstractBeanDefinitionReader the loadBeanDefinitions () method is as follows:

//重载方法,调用下面的loadBeanDefinitions(String, Set<Resource>);方法
	@Override
	public int loadBeanDefinitions(String location) throws BeanDefinitionStoreException {
		return loadBeanDefinitions(location, null);
	}

public int loadBeanDefinitions(String location, @Nullable Set<Resource> actualResources) throws BeanDefinitionStoreException {
		//获取在IoC容器初始化过程中设置的资源加载器
		ResourceLoader resourceLoader = getResourceLoader();
		if (resourceLoader == null) {
			throw new BeanDefinitionStoreException(
					"Cannot import bean definitions from location [" + location + "]: no ResourceLoader available");
		}

		if (resourceLoader instanceof ResourcePatternResolver) {
			// Resource pattern matching available.
			try {
				//将指定位置的Bean定义资源文件解析为Spring IOC容器封装的资源
				//加载多个指定位置的Bean定义资源文件
				Resource[] resources = ((ResourcePatternResolver) resourceLoader).getResources(location);
				//委派调用其子类XmlBeanDefinitionReader的方法,实现加载功能
				int loadCount = loadBeanDefinitions(resources);
				if (actualResources != null) {
					for (Resource resource : resources) {
						actualResources.add(resource);
					}
				}
				if (logger.isDebugEnabled()) {
					logger.debug("Loaded " + loadCount + " bean definitions from location pattern [" + location + "]");
				}
				return loadCount;
			}
			catch (IOException ex) {
				throw new BeanDefinitionStoreException(
						"Could not resolve bean definition resource pattern [" + location + "]", ex);
			}
		}
		else {
			// Can only load single resources by absolute URL.
			//将指定位置的Bean定义资源文件解析为Spring IOC容器封装的资源
			//加载单个指定位置的Bean定义资源文件
			Resource resource = resourceLoader.getResource(location);
			//委派调用其子类XmlBeanDefinitionReader的方法,实现加载功能
			int loadCount = loadBeanDefinitions(resource);
			if (actualResources != null) {
				actualResources.add(resource);
			}
			if (logger.isDebugEnabled()) {
				logger.debug("Loaded " + loadCount + " bean definitions from location [" + location + "]");
			}
			return loadCount;
		}
	}

 

 

Run-time timing diagram Spring ioc

Annotation IOC whole initialization process

Bean positioning scan path ------------> read metadata ------------> Analytical -------------> Register bean

 

 

 

 

 

 

发布了35 篇原创文章 · 获赞 0 · 访问量 1万+

Guess you like

Origin blog.csdn.net/tealala/article/details/103660965