<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>欲說還休</title><link>https://blog.terryx.com/tags/spring-4/</link><description>TerryX's Blog</description><generator>Hugo 0.161.1</generator><language>zh-cn</language><managingEditor>TerryX</managingEditor><lastBuildDate>Wed, 21 Mar 2018 00:00:00 +0000</lastBuildDate><atom:link href="https://blog.terryx.com/tags/spring-4/index.xml" rel="self" type="application/rss+xml"/><item><title>Spring IoC Container Part 3</title><link>https://blog.terryx.com/posts/spring4-3/</link><pubDate>Mon, 24 Oct 2016 00:00:00 +0000</pubDate><guid>https://blog.terryx.com/posts/spring4-3/</guid><description><![CDATA[<h2 id="defaultsingletonbeanregistry">DefaultSingletonBeanRegistry</h2>
<p>Last time we find that in the <code>DefaultListableBeanFactory</code> it provides map to save bean definitions. But when getting bean instance, we need to step into <code>DefaultSingletonBeanRegistry</code>. First let’s see the document:</p>
<blockquote>
<p>Generic registry for shared bean instances, implementing the <code>SingletonBeanRegistry</code>. <strong>Allows for registering singleton instances that should be shared for all callers of the registry, to be obtained via bean name</strong>.</p>
</blockquote>
<blockquote>
<p>Also supports registration of <code>DisposableBean</code> instances, (which might or might not correspond to registered singletons), to be destroyed on shutdown of the registry. Dependencies between beans can be registered to enforce an appropriate shutdown order.</p>
</blockquote>
<blockquote>
<p>This class mainly serves as base class for <code>BeanFactory</code> implementations, factoring out the common management of singleton bean instances. Note that the <code>ConfigurableBeanFactory</code> interface extends the <code>SingletonBeanRegistry</code> interface.</p>
</blockquote>
<blockquote>
<p>Note that this class assumes neither a bean definition concept nor a specific creation process for bean instances, in contrast to <code>AbstractBeanFactory</code> and <code>DefaultListableBeanFactory</code> (which inherit from it). Can alternatively also be used as a nested helper to delegate to.</p>
</blockquote>
<p>In the class, it has private variable to cache the bean instance:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-java" data-lang="java"><span class="line"><span class="cl"><span class="cm">/** Cache of singleton objects: bean name --&gt; bean instance */</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="kd">private</span><span class="w"> </span><span class="kd">final</span><span class="w"> </span><span class="n">Map</span><span class="o">&lt;</span><span class="n">String</span><span class="p">,</span><span class="w"> </span><span class="n">Object</span><span class="o">&gt;</span><span class="w"> </span><span class="n">singletonObjects</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="k">new</span><span class="w"> </span><span class="n">ConcurrentHashMap</span><span class="o">&lt;</span><span class="n">String</span><span class="p">,</span><span class="w"> </span><span class="n">Object</span><span class="o">&gt;</span><span class="p">(</span><span class="n">256</span><span class="p">);</span><span class="w">
</span></span></span></code></pre></div><h2 id="abstractbeanfactory">AbstractBeanFactory</h2>
<p>Again <code>AbstractBeanFactory</code> is very important <code>BeanFactory</code> implementation to get beans, and it is also a <code>SingletonBeanRegistry</code> interface implementation to save beans.</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-java" data-lang="java"><span class="line"><span class="cl"><span class="kd">protected</span><span class="w"> </span><span class="o">&lt;</span><span class="n">T</span><span class="o">&gt;</span><span class="w"> </span><span class="n">T</span><span class="w"> </span><span class="nf">doGetBean</span><span class="p">(</span><span class="n">String</span><span class="w"> </span><span class="n">name</span><span class="p">,</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">                          </span><span class="n">Class</span><span class="o">&lt;</span><span class="n">T</span><span class="o">&gt;</span><span class="w"> </span><span class="n">requiredType</span><span class="p">,</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">                          </span><span class="n">Object</span><span class="o">[]</span><span class="w"> </span><span class="n">args</span><span class="p">,</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">                          </span><span class="kt">boolean</span><span class="w"> </span><span class="n">typeCheckOnly</span><span class="p">)</span><span class="w">
</span></span></span></code></pre></div><p>When <code>ApplicationContext</code> calls <code>doGetBean(...)</code>, it will call <code>getSingleton(...)</code> which is declared in <code>SingletonBeanRegistry</code> interface and implements in <code>DefaultSingletonBeanRegistry</code>.</p>
<blockquote>
<p>Return the (raw) singleton object registered under the given name.
Only checks already instantiated singletons; does not return an Object for singleton bean definitions which have not been instantiated yet.</p>
</blockquote>
<blockquote>
<p>The main purpose of this method is to access manually registered singletons (see <code>registerSingleton(java.lang.String, java.lang.Object)</code>). Can also be used to access a singleton defined by a bean definition that already been created, in a raw fashion.</p>
</blockquote>
<blockquote>
<p>NOTE: This lookup method is not aware of FactoryBean prefixes or aliases. You need to resolve the canonical bean name first before obtaining the singleton instance.</p>
</blockquote>
<p>In this method, if the bean exists in concurrent map <code>singletonObjects&lt;String, Object&gt;</code> of <code>DefaultSingletonBeanRegistry</code>, it will call <code>getSingleton(...)</code> and return the bean object; Else the bean isn’t defined, the method will also call  <code>getSingleton(...)</code>, if the singleton bean is null then it will generate the object of bean.</p>
<h2 id="create-object-of-bean">Create Object of Bean</h2>
<p>How does spring create object from bean definition file? In <code>AbstractBeanFactory</code>, it provide an abstract bean creation method:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-java" data-lang="java"><span class="line"><span class="cl"><span class="kd">protected</span><span class="w"> </span><span class="kd">abstract</span><span class="w"> </span><span class="n">Object</span><span class="w"> </span><span class="nf">createBean</span><span class="p">(</span><span class="n">String</span><span class="w"> </span><span class="n">beanName</span><span class="p">,</span><span class="w"> </span><span class="n">RootBeanDefinition</span><span class="w"> </span><span class="n">mbd</span><span class="p">,</span><span class="w"> </span><span class="n">Object</span><span class="o">[]</span><span class="w"> </span><span class="n">args</span><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">			</span><span class="kd">throws</span><span class="w"> </span><span class="n">BeanCreationException</span><span class="p">;</span><span class="w">
</span></span></span></code></pre></div><p>Also see the document:</p>
<blockquote>
<p><strong>Create a bean instance for the given merged bean definition (and arguments).</strong> The bean definition will already have been merged with the parent definition in case of a child definition.</p>
</blockquote>
<blockquote>
<p>All bean retrieval methods delegate to this method for actual bean creation.</p>
</blockquote>
<p>This method is implemented in <code>AbstractAutowireCapableBeanFactory</code>:</p>
<blockquote>
<p>Abstract bean factory superclass that implements default bean creation, with the full capabilities specified by the <code>RootBeanDefinition</code> class. Implements the <code>AutowireCapableBeanFactory</code> interface <strong>in addition to AbstractBeanFactory’s <code>createBean(java.lang.Class&lt;T&gt;)</code> method.</strong></p>
</blockquote>
<blockquote>
<p>Provides bean creation (with constructor resolution), property population, wiring (including autowiring), and initialization. Handles runtime bean references, resolves managed collections, calls initialization methods, etc. Supports autowiring constructors, properties by name, and properties by type.</p>
</blockquote>
<blockquote>
<p>The main template method to be implemented by subclasses is <code>AutowireCapableBeanFactory.resolveDependency(DependencyDescriptor, String, Set, TypeConverter)</code>, used for autowiring by type. In case of a factory which is capable of searching its bean definitions, matching beans will typically be implemented through such a search. For other factory styles, simplified matching algorithms can be implemented.</p>
</blockquote>
<blockquote>
<p>Note that this class does not assume or implement bean definition registry capabilities. See <code>DefaultListableBeanFactory</code> for an implementation of the <code>ListableBeanFactory</code> and <code>BeanDefinitionRegistry</code> interfaces, which represent the API and SPI view of such a factory, respectively.</p>
</blockquote>
<p>Now we just move to <code>createBean(...)</code> method and its main method is <code>doCreateBean(...)</code>:</p>
<blockquote>
<p>Actually create the specified bean. Pre-creation processing has already happened at this point, <em>e.g. checking</em> <code>postProcessBeforeInstantiation</code> <em>callbacks</em>.</p>
</blockquote>
<blockquote>
<p>Differentiates between default bean instantiation, use of a factory method, and autowiring a constructor.</p>
</blockquote>
<p>So we can know from the document that the method just create the specified bean which means it should get class reference in the definition file.</p>
<p>In this method, we find <code>BeanWrapper</code> class which is the central interface of Spring’s low-level JavaBeans infrastructure. The wrapper  is initialized with <code>createBeanInstance(...)</code> method which can create a new instance for the specified bean, using an appropriate instantiation strategy: factory method, constructor autowiring, or simple instantiation. Then it call the core instantiation method <code>instantiateBean(...)</code> and it will step into <code>InstantiationStrategy</code> interface.</p>
<h2 id="instantiationstrategy">InstantiationStrategy</h2>
<blockquote>
<p>Interface responsible for creating instances corresponding to a root bean definition.</p>
</blockquote>
<blockquote>
<p>This is pulled out into a strategy as various approaches are possible, including using CGLIB to create subclasses on the fly to support Method Injection.</p>
</blockquote>
<p>Here we just talk about its <code>SimpleInstantiationStrategy</code> implement class. it has <code>instantiate(...)</code> which can return an instance of the bean with the given name in this factory. First it get the <code>Class&lt;?&gt; clazz</code> of the bean, and call <code>clazz.getDeclaredConstructor(...)</code> to get the <code>Constructor&lt;?&gt;</code> of the bean, then step into <code>BeanUtils</code> class and call <code>instantiateClass(...)</code> method which can call <code>constructor.newInstance(args)</code> and return a new object created by calling the constructor this object represents.</p>
<p>Finally, the object will be saved in the <code>singletonObjects&lt;String, Object&gt;</code> for <code>getBean(...)</code> method to get the object.</p>
<h2 id="whats-next">What’s Next?</h2>
<p>After reading the source code of Spring’s IoC, I find some TODO list.</p>
<ul>
<li><code>ThreadLocal&lt;?&gt;</code>, <code>ConcurrentMap&lt;K, V&gt;</code> and <em>volatile</em> are often appeared in the source, so I need to deal with something about Java Threads;</li>
<li><a href="http://docs.spring.io/spring/docs/current/spring-framework-reference/html/">Spring Reference</a> is very useful document to read thus I need to focus more with it.</li>
</ul>
]]></description></item><item><title>Spring IoC Container Part 2</title><link>https://blog.terryx.com/posts/spring4-2/</link><pubDate>Fri, 21 Oct 2016 00:00:00 +0000</pubDate><guid>https://blog.terryx.com/posts/spring4-2/</guid><description><![CDATA[<h2 id="log4j">Log4J</h2>
<p>When using Spring framework, we must use <a href="https://commons.apache.org/proper/commons-logging/">Apache Common Logging</a> to print log in console or binary files. As we known, Spring log configuration can change in the <code>web.xml</code> when it works on server. But in these series of articles, we try to analyze the Spring core techniques without works on server. So there should have another way to configure log without <code>web.xml</code> because we want to see the debug informations.</p>
<p>Spring gives <code>Log4jConfigurer.initLogging()</code> method (has been deprecated in Spring 4.2.1) to  initialize log4j from the given file location. Note that we always use Maven to build project, but maven might mash <code>src</code> and <code>resources</code> folders to one. Thus we should use <code>classpath:</code> ,<strong>without slash</strong>, to represent <code>resources</code> folder in the project.</p>
<p>Now Apache Commons Logging (JCL) provides thin-wrapper Log implementations for other logging tools, including Log4J. But <code>Log4jConfigurer.initLogging()</code> calls methods from log4j 1.x. It means that we should add log4j 1.x dependency to make sure that our log configuration file works smoothly.</p>
<p>Here is the configure file <code>log4j.properties</code>, and just opening debug function in <code>org.springframework.beans</code> because we want to know the IOC process:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-plain" data-lang="plain"><span class="line"><span class="cl">log4j.rootCategory=INFO, stdout
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">log4j.appender.stdout=org.apache.log4j.ConsoleAppender
</span></span><span class="line"><span class="cl">log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
</span></span><span class="line"><span class="cl">log4j.appender.stdout.layout.ConversionPattern=%d{ABSOLUTE} %5p %t %c:%L - %m%n
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">log4j.category.org.springframework.beans=DEBUG
</span></span></code></pre></div><p>As last article, we run the same code but add our log configuration before:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-java" data-lang="java"><span class="line"><span class="cl"><span class="n">Log4jConfigurer</span><span class="p">.</span><span class="na">initLogging</span><span class="p">(</span><span class="s">&#34;classpath:log4j.properties&#34;</span><span class="p">);</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="n">ApplicationContext</span><span class="w"> </span><span class="n">context</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="k">new</span><span class="w"> </span><span class="n">ClassPathXmlApplicationContext</span><span class="p">(</span><span class="s">&#34;services.xml&#34;</span><span class="p">);</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="n">PetStoreServiceImpl</span><span class="w"> </span><span class="n">petStoreService</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">context</span><span class="p">.</span><span class="na">getBean</span><span class="p">(</span><span class="s">&#34;petStore&#34;</span><span class="p">,</span><span class="w"> </span><span class="n">PetStoreServiceImpl</span><span class="p">.</span><span class="na">class</span><span class="p">);</span><span class="w">
</span></span></span></code></pre></div><p>Now we can follow the log information to know the IOC clearly.</p>
<h2 id="classpathxmlapplicationcontext">ClassPathXmlApplicationContext</h2>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-plain" data-lang="plain"><span class="line"><span class="cl">17:23:15,265  INFO main ClassPathXmlApplicationContext org.springframework.context.support.AbstractApplicationContext.prepareRefresh:581 - Refreshing org.springframework.context.support.ClassPathXmlApplicationContext@42dafa95: startup date [Fri Oct 21 17:23:15 EDT 2016]; root of context hierarchy
</span></span></code></pre></div><p>First we step into <code>ClassPathXmlApplicationContext</code> constructor and it calls <code>refresh()</code>. This method is declared in the interface <code>ConfigurableApplicationContext</code>, implements in <code>AbstractApplicationContext</code>, finally called in <code>ClassPathXmlApplicationContext</code> which is a subclass of <code>AbstractApplicationContext</code>.</p>
<blockquote>
<p>This method can load or refresh the <strong>persistent representation</strong> of the configuration, which might an XML file, properties file, or relational database schema. As this is a startup method, it should destroy already created singletons if it fails, to avoid dangling resources. In other words, after invocation  of that method, either all or no singletons at all should be instantiated.</p>
</blockquote>
<p>As we see in the document, <code>refresh()</code> is used to load and refresh persistent representation configuration. It should be done first of all.</p>
<h2 id="xmlbeandefinitionreader">XmlBeanDefinitionReader</h2>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-plain" data-lang="plain"><span class="line"><span class="cl">17:23:15,555  INFO main XmlBeanDefinitionReader org.springframework.beans.factory.xml.XmlBeanDefinitionReader.loadBeanDefinitions:317 - Loading XML bean definitions from class path resource [services.xml]
</span></span></code></pre></div><p>The <code>refresh()</code> method calls <code>obtainFreshBeanFactory()</code> in  which can tell the subclass to refresh the internal bean factory. So how to let a class to call the method (in this case it is <code>refreshBeanFactory()</code>) in its subclass? It is a very classical design pattern.</p>
<p>First, the <code>AbstractApplicationContext</code> declares:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-java" data-lang="java"><span class="line"><span class="cl"><span class="kd">protected</span><span class="w"> </span><span class="kd">abstract</span><span class="w"> </span><span class="kt">void</span><span class="w"> </span><span class="nf">refreshBeanFactory</span><span class="p">()</span><span class="w">
</span></span></span></code></pre></div><p>This method is implemented in <code>AbstractRefreshableApplicationContext</code> which is a subclass of <code>AbstractApplicationContext</code>:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-java" data-lang="java"><span class="line"><span class="cl"><span class="nd">@Override</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="kd">protected</span><span class="w"> </span><span class="kd">final</span><span class="w"> </span><span class="kt">void</span><span class="w"> </span><span class="nf">refreshBeanFactory</span><span class="p">()</span><span class="w">
</span></span></span></code></pre></div><p>Therefore the father class can call the method which implemented in its subclass.</p>
<p>Here is <code>XmlBeanDefinitionReader</code>:</p>
<blockquote>
<p>Bean definition reader for XML bean definitions. Delegates the actual XML document reading to an implementation of the <code>BeanDefinitionDocumentReader</code> interface. Typically applied to a
<code>DefaultListableBeanFactory</code> or a <code>GenericApplicationContext</code>.</p>
</blockquote>
<blockquote>
<p>This class loads a DOM document and applies the <code>BeanDefinitionDocumentReader</code> to it.</p>
</blockquote>
<blockquote>
<p>The document reader will register each bean definition with the given bean factory, talking to the latter’s implementation of the <code>BeanDefinitionRegistry</code> interface.</p>
</blockquote>
<p><code>loadBeanDefinition()</code> method is used to load bean definitions from the specified XML file.</p>
<h2 id="defaultdocumentloader">DefaultDocumentLoader</h2>
<p><code>XmlBeanDefinitionReader</code> calls <code>doLoadDocument()</code> and it has local variable <code>DocumentLoader</code> documentLoader which calls <code>loadDocument()</code>.</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-plain" data-lang="plain"><span class="line"><span class="cl">19:38:23,603 DEBUG main DefaultDocumentLoader org.springframework.beans.factory.xml.DefaultDocumentLoader.loadDocument:73 - Using JAXP provider [com.sun.org.apache.xerces.internal.jaxp.DocumentBuilderFactoryImpl]
</span></span></code></pre></div><p>Here is <code>DefaultDocumentLoader</code>:</p>
<blockquote>
<p>Spring’s default {@link DocumentLoader} implementation. Simply loads <code>Document</code> documents using the standard JAXP-configured XML parser. If you want to change the <code>DocumentBuilder</code> that is used to load documents, then one strategy is to define a corresponding Java system property when starting your JVM. For example, to use the Oracle <code>DocumentBuilder</code>, might start your application like as follows:</p>
<p><code>java -Djavax.xml.parsers.DocumentBuilderFactory=oracle.xml.jaxp.JXDocumentBuilderFactory MyMainClass</code></p>
</blockquote>
<h2 id="defaultbeandefinitiondocumentreader">DefaultBeanDefinitionDocumentReader</h2>
<p>Here is <code>DefaultBeanDefinitionDocumentReader</code> which is used to read bean definitions:</p>
<blockquote>
<p>Default implementation of the <code>BeanDefinitionDocumentReader</code> interface that reads bean definitions according to the “spring-beans” DTD and XSD format (Spring’s default XML bean definition format).</p>
</blockquote>
<blockquote>
<p>The structure, elements, and attribute names of the required XML document are hard-coded in this class. (Of course a transform could be run if necessary to produce this format). <code>&lt;beans&gt;</code> does not need to be the root element of the XML document: this class will parse all bean definition elements in the XML file, regardless of the actual root element.</p>
</blockquote>
<p>And <code>registerBeanDefinitions(doc, readerContext)</code>:</p>
<blockquote>
<p>Read bean definitions from the given DOM document and register them with the registry in the given reader context.</p>
</blockquote>
<blockquote>
<p><code>doc</code> the DOM document <code>readerContext</code> the current context of the reader (includes the target registry and the resource being parsed)</p>
</blockquote>
<h2 id="defaultlistablebeanfactory">DefaultListableBeanFactory</h2>
<blockquote>
<p>Default implementation of the <code>ListableBeanFactory</code> and <code>BeanDefinitionRegistry</code> interfaces: a full-fledged bean factory based on bean definition objects.
<strong>Typical usage is registering all bean definitions first (possibly read from a bean definition file), before accessing beans</strong>. Bean definition lookup is therefore an inexpensive operation in a local bean definition table, operating on pre-built bean definition metadata objects.</p>
</blockquote>
<blockquote>
<p>Can be used as a standalone bean factory, or as a superclass for custom bean factories. Note that readers for specific bean definition formats are typically implemented separately rather than as bean factory subclasses: see for example <code>PropertiesBeanDefinitionReader</code> and <code>XmlBeanDefinitionReader</code>.</p>
</blockquote>
<blockquote>
<p>For an alternative implementation of the <code>ListableBeanFactory</code> interface, have a look at <code>StaticListableBeanFactory</code>, which manages existing bean instances rather than creating new ones based on bean definitions.</p>
</blockquote>
<p>It implements the bean register method <code>registerBeanDefinition()</code> which is declared in interface <code>BeanDefinitionRegistry</code>.</p>
<blockquote>
<p>Register a new bean definition with this registry. Must support <code>RootBeanDefinition</code> and <code>ChildBeanDefinition</code>.</p>
</blockquote>
<p>Now we look at <code>DefaultListableBeanFactory</code> and find that it has some private variables.</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-java" data-lang="java"><span class="line"><span class="cl"><span class="cm">/** Map of bean definition objects, keyed by bean name */</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="kd">private</span><span class="w"> </span><span class="kd">final</span><span class="w"> </span><span class="n">Map</span><span class="o">&lt;</span><span class="n">String</span><span class="p">,</span><span class="w"> </span><span class="n">BeanDefinition</span><span class="o">&gt;</span><span class="w"> </span><span class="n">beanDefinitionMap</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="k">new</span><span class="w"> </span><span class="n">ConcurrentHashMap</span><span class="o">&lt;</span><span class="n">String</span><span class="p">,</span><span class="w"> </span><span class="n">BeanDefinition</span><span class="o">&gt;</span><span class="p">(</span><span class="n">256</span><span class="p">);</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="cm">/** List of bean definition names, in registration order */</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="kd">private</span><span class="w"> </span><span class="kd">volatile</span><span class="w"> </span><span class="n">List</span><span class="o">&lt;</span><span class="n">String</span><span class="o">&gt;</span><span class="w"> </span><span class="n">beanDefinitionNames</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="k">new</span><span class="w"> </span><span class="n">ArrayList</span><span class="o">&lt;</span><span class="n">String</span><span class="o">&gt;</span><span class="p">(</span><span class="n">256</span><span class="p">);</span><span class="w">
</span></span></span></code></pre></div><p>Note that <code>beanDefinitionMap</code> is a <code>java.util.concurrent.ConcurrentHashMap</code> and <code>beanDefinitionNames</code> is a volatile variable.</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-java" data-lang="java"><span class="line"><span class="cl"><span class="k">this</span><span class="p">.</span><span class="na">beanDefinitionMap</span><span class="p">.</span><span class="na">put</span><span class="p">(</span><span class="n">beanName</span><span class="p">,</span><span class="w"> </span><span class="n">beanDefinition</span><span class="p">);</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="k">this</span><span class="p">.</span><span class="na">beanDefinitionNames</span><span class="p">.</span><span class="na">add</span><span class="p">(</span><span class="n">beanName</span><span class="p">);</span><span class="w">
</span></span></span></code></pre></div><p>TODO: <code>java.util.concurrent.ConcurrentHashMap</code> and volatile variable.</p>
]]></description></item><item><title>Spring IoC Container Part 1</title><link>https://blog.terryx.com/posts/spring4-1/</link><pubDate>Mon, 10 Oct 2016 00:00:00 +0000</pubDate><guid>https://blog.terryx.com/posts/spring4-1/</guid><description><![CDATA[<p>Let’s look a simple code within Spring below:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-java" data-lang="java"><span class="line"><span class="cl"><span class="w"> </span><span class="c1">// create and configure beans</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="n">ApplicationContext</span><span class="w"> </span><span class="n">context</span><span class="w"> </span><span class="o">=</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="k">new</span><span class="w"> </span><span class="n">ClassPathXmlApplicationContext</span><span class="p">(</span><span class="k">new</span><span class="w"> </span><span class="n">String</span><span class="o">[]</span><span class="w"> </span><span class="p">{</span><span class="s">&#34;services.xml&#34;</span><span class="p">,</span><span class="w"> </span><span class="s">&#34;daos.xml&#34;</span><span class="p">});</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="c1">// retrieve configured instance</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="n">PetStoreService</span><span class="w"> </span><span class="n">service</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">context</span><span class="p">.</span><span class="na">getBean</span><span class="p">(</span><span class="s">&#34;petStore&#34;</span><span class="p">,</span><span class="w"> </span><span class="n">PetStoreService</span><span class="p">.</span><span class="na">class</span><span class="p">);</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="c1">// use configured instance</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="n">List</span><span class="o">&lt;</span><span class="n">String</span><span class="o">&gt;</span><span class="w"> </span><span class="n">userList</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">service</span><span class="p">.</span><span class="na">getUsernameList</span><span class="p">();</span><span class="w">
</span></span></span></code></pre></div><p>First of all, we should know the class hierarchy in <code>org.springframework.context.support</code>:</p>
<p><img src="http://www.plantuml.com/plantuml/svg/fP7D2i8m3CVFxYbwd8Xx1zdLW-X540zPpMQnQqiIFs3uxcwh5qLbmq03JVx9Bqq3w1DKg3nL6GSohYe9QhnwEcNQEy6RP7mEmPCqIQ9QCssGIj2eSkzAKvq92ekB4ApH8CQxF9QfffTtDhjuSr249I4VqsaVl_SU2XO2BKfRO5QBv_L3DrC7YpKwuN-v8y7DWB9rH7mPg3te3hyW8nbn0GD8F-UAqCby8zstx_PAzssNFgeufcUCahycqZVXaCLkQpjktczlR9B9anG1UUTN8CTXXC-gs3IvFm00" alt=""  loading="lazy">
</p>
<p><code>ClassPathXmlApplicationContext</code> implements <code>ApplicationContext</code> and calls its constructor as below:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-java" data-lang="java"><span class="line"><span class="cl"><span class="w"> </span><span class="cm">/**
</span></span></span><span class="line"><span class="cl"><span class="cm"> * Create a new ClassPathXmlApplicationContext, loading the definitions
</span></span></span><span class="line"><span class="cl"><span class="cm"> * from the given XML file and automatically refreshing the context.
</span></span></span><span class="line"><span class="cl"><span class="cm"> * @param configLocation resource location
</span></span></span><span class="line"><span class="cl"><span class="cm"> * @throws BeansException if context creation failed
</span></span></span><span class="line"><span class="cl"><span class="cm"> **/</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="kd">public</span><span class="w"> </span><span class="nf">ClassPathXmlApplicationContext</span><span class="p">(</span><span class="n">String</span><span class="w"> </span><span class="n">configLocation</span><span class="p">)</span><span class="w"> </span><span class="kd">throws</span><span class="w"> </span><span class="n">BeansException</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="k">this</span><span class="p">(</span><span class="k">new</span><span class="w"> </span><span class="n">String</span><span class="o">[]</span><span class="w"> </span><span class="p">{</span><span class="n">configLocation</span><span class="p">},</span><span class="w"> </span><span class="kc">true</span><span class="p">,</span><span class="w"> </span><span class="kc">null</span><span class="p">);</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="p">}</span><span class="w">
</span></span></span></code></pre></div><p>Step into <code>ClassPathXmlApplicationContext(String[], boolean, ApplicationContext)</code>：</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-java" data-lang="java"><span class="line"><span class="cl"><span class="cm">/**
</span></span></span><span class="line"><span class="cl"><span class="cm"> * Create a new ClassPathXmlApplicationContext with the given parent,
</span></span></span><span class="line"><span class="cl"><span class="cm"> * loading the definitions from the given XML files.
</span></span></span><span class="line"><span class="cl"><span class="cm"> * @param configLocations array of resource locations
</span></span></span><span class="line"><span class="cl"><span class="cm"> * @param refresh whether to automatically refresh the context,
</span></span></span><span class="line"><span class="cl"><span class="cm"> * loading all bean definitions and creating all singletons.
</span></span></span><span class="line"><span class="cl"><span class="cm"> * Alternatively, call refresh manually after further configuring the context.
</span></span></span><span class="line"><span class="cl"><span class="cm"> * @param parent the parent context
</span></span></span><span class="line"><span class="cl"><span class="cm"> * @throws BeansException if context creation failed
</span></span></span><span class="line"><span class="cl"><span class="cm"> * @see #refresh()
</span></span></span><span class="line"><span class="cl"><span class="cm"> **/</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="kd">public</span><span class="w"> </span><span class="nf">ClassPathXmlApplicationContext</span><span class="p">(</span><span class="n">String</span><span class="o">[]</span><span class="w"> </span><span class="n">configLocations</span><span class="p">,</span><span class="w"> </span><span class="err">￼</span><span class="kt">boolean</span><span class="w"> </span><span class="n">refresh</span><span class="p">,</span><span class="w"> </span><span class="n">ApplicationContext</span><span class="w"> </span><span class="n">parent</span><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">		</span><span class="kd">throws</span><span class="w"> </span><span class="n">BeansException</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="kd">super</span><span class="p">(</span><span class="n">parent</span><span class="p">);</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="n">setConfigLocations</span><span class="p">(</span><span class="n">configLocations</span><span class="p">);</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="n">refresh</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">		</span><span class="n">refresh</span><span class="p">();</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="p">}</span><span class="w">
</span></span></span></code></pre></div><p>In this method, it first call <code>super(parent)</code>, which is <code>AbstractXmlApplicationContext(parent)</code> –&gt; <code>AbstractRefreshableConfigApplicationContext(parent)</code> –&gt; <code>AbstractRefreshableApplicationContext(parent)</code> –&gt; <code>AbstractApplicationContext(parent)</code>.</p>
<p>Then, for the <code>setConfigLocations(configLocations)</code>, we need move to <code>AbstractRefreshableConfigApplicationContext</code>, the superclass of <code>ClassPathXmlApplicationContext</code>. It has <code>setConfigLocations(configLocations)</code> that deals with the locations String and save to its private value <code>String[] configLocations</code>.</p>
<p>Now, we get to the <code>refresh()</code> method belong to <code>AbstractApplicationContext</code> that implements the method in the interface <code>ConfigurableApplicationContext</code></p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-java" data-lang="java"><span class="line"><span class="cl"><span class="cm">/**
</span></span></span><span class="line"><span class="cl"><span class="cm"> * Load or refresh the persistent representation of the configuration,
</span></span></span><span class="line"><span class="cl"><span class="cm"> * which might an XML file, properties file, or relational database schema.
</span></span></span><span class="line"><span class="cl"><span class="cm"> * &lt;p&gt;As this is a startup method, it should destroy already created singletons
</span></span></span><span class="line"><span class="cl"><span class="cm"> * if it fails, to avoid dangling resources. In other words, after invocation
</span></span></span><span class="line"><span class="cl"><span class="cm"> * of that method, either all or no singletons at all should be instantiated.
</span></span></span><span class="line"><span class="cl"><span class="cm"> * @throws BeansException if the bean factory could not be initialized
</span></span></span><span class="line"><span class="cl"><span class="cm"> * @throws IllegalStateException if already initialized and multiple refresh
</span></span></span><span class="line"><span class="cl"><span class="cm"> * attempts are not supported
</span></span></span><span class="line"><span class="cl"><span class="cm"> */</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nd">@Override</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="kd">public</span><span class="w"> </span><span class="kt">void</span><span class="w"> </span><span class="nf">refresh</span><span class="p">()</span><span class="w"> </span><span class="kd">throws</span><span class="w"> </span><span class="n">BeansException</span><span class="p">,</span><span class="w"> </span><span class="n">IllegalStateException</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">		</span><span class="kd">synchronized</span><span class="w"> </span><span class="p">(</span><span class="k">this</span><span class="p">.</span><span class="na">startupShutdownMonitor</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">		</span><span class="c1">// Prepare this context for refreshing.</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">		</span><span class="n">prepareRefresh</span><span class="p">();</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">		</span><span class="c1">// Tell the subclass to refresh the internal bean factory.</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">		</span><span class="n">ConfigurableListableBeanFactory</span><span class="w"> </span><span class="n">beanFactory</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">obtainFreshBeanFactory</span><span class="p">();</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">		</span><span class="c1">// Prepare the bean factory for use in this context.</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">		</span><span class="n">prepareBeanFactory</span><span class="p">(</span><span class="n">beanFactory</span><span class="p">);</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">		</span><span class="c1">// remainder...</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">		</span><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="p">}</span><span class="w">
</span></span></span></code></pre></div><p>For this line call <code>obtainFreshBeanFactory()</code> that then calls <code>refreshBeanFactory()</code>, subclass <code>AbstractXmlApplicationContext</code> to refresh bean factory and load bean definitions by calling <code>loadBeanDefinitions(beanFactory)</code>, and then it calls <code>loadBeanDefinitions(reader)</code>, in which reader is <code>XmlBeanDefinitionReader</code> implements <code>BeanDefinitionReader</code>. This class loads a DOM document and applies the reader to it. The document reader will register each bean definition with the given bean factory, talking to the latter’s implementation of the <code>BeanDefinitionRegistry</code> interface.</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-java" data-lang="java"><span class="line"><span class="cl"><span class="c1">// Tell the subclass to refresh the internal bean factory.</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="n">ConfigurableListableBeanFactory</span><span class="w"> </span><span class="n">beanFactory</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">obtainFreshBeanFactory</span><span class="p">();</span><span class="w">
</span></span></span></code></pre></div><p>The reader has the <code>loadBeanDefinitions(configLocations)</code> method and the inner method of <code>XmlBeanDefinitionReader</code> provides a <code>loadBeanDefinitions(encodedResource)</code> where <code>EncodedResource</code> is the resource descriptor for the XML file, allowing to specify an encoding to use for parsing the file.</p>
<p>Method <code>doLoadDocument(inputSource, resource)</code> actually load bean definitions from the specified XML file. <code>DefaultDocumentLoader</code> that implements <code>DocumentLoader</code> loads a <code>Document</code> document from the supplied <code>InputSource</code> source by calling method <code>loadDocument(InputSource, EntityResolver, ...)</code> (that is a classical design pattern).</p>
<p>Further topics: <code>InputSource</code> of Spring Resource,<code>ThreadLocal</code> of Java SE concurrency, <code>context.getBean(...)</code> of how to get instantialization of service.</p>
]]></description></item></channel></rss>