Network Security Internet Technology Development Database Servers Mobile Phone Android Software Apple Software Computer Software News IT Information

In addition to Weibo, there is also WeChat

Please pay attention

WeChat public account

Shulou

What is the core process of Spring IOC

2025-04-12 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Development >

Share

Shulou(Shulou.com)06/02 Report--

This article mainly explains "what is the core process of Spring IOC". Interested friends may wish to have a look at it. The method introduced in this paper is simple, fast and practical. Let's let the editor take you to learn "what is the core process of Spring IOC"?

1. Initialization

Roughly step by step, we follow the initialization process of Spring IOC. The whole context is very large. The initialization process is mainly to read XML resources, parse them, and finally register them in Bean Factory:

After completing the initialization process, the Bean waits for the call in BeanFactory. Let's learn the initialization process in detail through a specific example, such as when the following bean is loaded:

When loading, you need to read, parse, and register bean. The specific call stack for this process is as follows:

The key code for each step is analyzed in detail below:

Prepare for

Save the configuration location and refresh

After calling ClassPathXmlApplicationContext, the configuration location information is saved to configLocations for later parsing, and then the refresh method of AbstractApplicationContext is called to refresh:

Public ClassPathXmlApplicationContext (String [] configLocations, boolean refresh, ApplicationContext parent) throws BeansException {super (parent); / / Save location information, such as `com/springstudy/talentshow/talent- show.xml` setConfigLocations (configLocations); if (refresh) {/ / 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) {/ / Destroy already created singletons to avoid dangling resources. DestroyBeans (); / / Reset 'active' flag. CancelRefresh (ex); / / Propagate exception to caller. Throw ex;}

Create and load BeanFactory

Protected final void refreshBeanFactory () throws BeansException {/ /.... DefaultListableBeanFactory beanFactory = createBeanFactory (); / /. LoadBeanDefinitions (beanFactory); / /.}

Create XMLBeanDefinitionReader

Protected void loadBeanDefinitions (DefaultListableBeanFactory beanFactory) throws BeansException, IOException {/ / Create a new XmlBeanDefinitionReader for the given BeanFactory. XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader (beanFactory); / /... / / Allow a subclass to provide custom initialization of the reader, / / then proceed with actually loading the bean definitions. InitBeanDefinitionReader (beanDefinitionReader); loadBeanDefinitions (beanDefinitionReader); read

Create and process each resource

Public int loadBeanDefinitions (String location, Set actualResources) throws BeanDefinitionStoreException {/ /... / read Resource Resource [] resources = ((ResourcePatternResolver) resourceLoader) .getResources (location) through Location; int loadCount = loadBeanDefinitions (resources); / /...} public int loadBeanDefinitions (Resource...) Resources) throws BeanDefinitionStoreException {Assert.notNull (resources, "Resource array must not be null"); int counter = 0; for (Resource resource: resources) {/ / load every resource counter + = loadBeanDefinitions (resource);} return counter;}

Process each element of XML

Protected void parseBeanDefinitions (Element root, BeanDefinitionParserDelegate delegate) {/ /. NodeList nl = root.getChildNodes (); for (int I = 0; I

< nl.getLength(); i++) { Node node = nl.item(i); if (node instanceof Element) { Element ele = (Element) node; if (delegate.isDefaultNamespace(ele)) { // 处理每个xml中的元素,可能是import、alias、bean parseDefaultElement(ele, delegate); } else { delegate.parseCustomElement(ele); } } } // ... ...} 解析和注册bean protected void processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate) { // 解析 BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele); if (bdHolder != null) { bdHolder = delegate.decorateBeanDefinitionIfRequired(ele, bdHolder); try { // 注册 // Register the final decorated instance. BeanDefinitionReaderUtils.registerBeanDefinition( bdHolder, getReaderContext().getRegistry()); } catch (BeanDefinitionStoreException ex) { getReaderContext().error("Failed to register bean definition with name '" + bdHolder.getBeanName() + "'", ele, ex); } // Send registration event. getReaderContext().fireComponentRegistered(new BeanComponentDefinition(bdHolder)); }} 本步骤中,通过parseBeanDefinitionElement将XML的元素解析为BeanDefinition,然后存在BeanDefinitionHolder中,然后再利用BeanDefinitionHolder将BeanDefinition注册,实质就是把BeanDefinition的实例put进BeanFactory中,和后面将详细的介绍解析和注册过程。 解析 处理每个Bean的元素 public AbstractBeanDefinition parseBeanDefinitionElement( Element ele, String beanName, BeanDefinition containingBean) { // ... ... // 创建beandefinition AbstractBeanDefinition bd = createBeanDefinition(className, parent); parseBeanDefinitionAttributes(ele, beanName, containingBean, bd); bd.setDescription(DomUtils.getChildElementValueByTagName(ele, DESCRIPTION_ELEMENT)); parseMetaElements(ele, bd); parseLookupOverrideSubElements(ele, bd.getMethodOverrides()); parseReplacedMethodSubElements(ele, bd.getMethodOverrides()); // 处理"Constructor" parseConstructorArgElements(ele, bd); // 处理"Preperty" parsePropertyElements(ele, bd); parseQualifierElements(ele, bd); // ... ...} 处理属性的值 public Object parsePropertyValue(Element ele, BeanDefinition bd, String propertyName) { String elementName = (propertyName != null) ? " element for property '" + propertyName + "'" : " element"; // ... ... if (hasRefAttribute) { // 处理引用 String refName = ele.getAttribute(REF_ATTRIBUTE); if (!StringUtils.hasText(refName)) { error(elementName + " contains empty 'ref' attribute", ele); } RuntimeBeanReference ref = new RuntimeBeanReference(refName); ref.setSource(extractSource(ele)); return ref; } else if (hasValueAttribute) { // 处理值 TypedStringValue valueHolder = new TypedStringValue(ele.getAttribute(VALUE_ATTRIBUTE)); valueHolder.setSource(extractSource(ele)); return valueHolder; } else if (subElement != null) { // 处理子类型(比如list、map等) return parsePropertySubElement(subElement, bd); } // ... ...} 1.4 注册 public static void registerBeanDefinition( BeanDefinitionHolder definitionHolder, BeanDefinitionRegistry registry) throws BeanDefinitionStoreException { // Register bean definition under primary name. String beanName = definitionHolder.getBeanName(); registry.registerBeanDefinition(beanName, definitionHolder.getBeanDefinition()); // Register aliases for bean name, if any. String[] aliases = definitionHolder.getAliases(); if (aliases != null) { for (String alias : aliases) { registry.registerAlias(beanName, alias); } }}public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition) throws BeanDefinitionStoreException { // ...... // 将beanDefinition注册 this.beanDefinitionMap.put(beanName, beanDefinition); // ......} 注册过程中,最核心的一句就是:this.beanDefinitionMap.put(beanName, beanDefinition),也就是说注册的实质就是以beanName为key,以beanDefinition为value,将其put到HashMap中。 注册 public static void registerBeanDefinition( BeanDefinitionHolder definitionHolder, BeanDefinitionRegistry registry) throws BeanDefinitionStoreException { // Register bean definition under primary name. String beanName = definitionHolder.getBeanName(); registry.registerBeanDefinition(beanName, definitionHolder.getBeanDefinition()); // Register aliases for bean name, if any. String[] aliases = definitionHolder.getAliases(); if (aliases != null) { for (String alias : aliases) { registry.registerAlias(beanName, alias); } }}public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition) throws BeanDefinitionStoreException { // ...... // 将beanDefinition注册 this.beanDefinitionMap.put(beanName, beanDefinition); // ...... 理解了以上两个过程,我们就可以自己实现一个简单的Spring框架了。于是,我根据自己的理解实现了一个简单的IOC框架Simple Spring,有兴趣可以看看。 注册过程中,最核心的一句就是:this.beanDefinitionMap.put(beanName, beanDefinition),也就是说注册的实质就是以beanName为key,以beanDefinition为value,将其put到HashMap中。 注入依赖 当完成初始化IOC容器后,如果bean没有设置lazy-init(延迟加载)属性,那么bean的实例就会在初始化IOC完成之后,及时地进行初始化。初始化时会先建立实例,然后根据配置利用反射对实例进行进一步操作,具体流程如下所示:

Create an instance of bean

The procedure function call stack for creating an instance of bean is as follows:

Properties of injected bean

The property procedure function call stack that is injected into bean is as follows:

When creating attributes of bean and injecting bean, it is done in the doCreateBean function. Let's focus on:

Protected Object doCreateBean (final String beanName, final RootBeanDefinition mbd, final Object [] args) {/ / Instantiate the bean. BeanWrapper instanceWrapper = null; if (mbd.isSingleton ()) {instanceWrapper = this.factoryBeanInstanceCache.remove (beanName);} if (instanceWrapper = = null) {/ / create an instance of bean instanceWrapper = createBeanInstance (beanName, mbd, args);} /. / / Initialize the bean instance. Object exposedObject = bean; try {/ / initialize the instance of bean, such as injection properties populateBean (beanName, mbd, instanceWrapper); if (exposedObject! = null) {exposedObject = initializeBean (beanName, exposedObject, mbd) }} / /.} at this point, I believe you have a deeper understanding of "what is the core process of Spring IOC". You might as well do it in practice. Here is the website, more related content can enter the relevant channels to inquire, follow us, continue to learn!

Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.

Views: 238

*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.

Share To

Development

Wechat

© 2024 shulou.com SLNews company. All rights reserved.

12
Report