<?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/java/</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/java/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><item><title>3.2 Bean Scopes</title><link>https://blog.terryx.com/posts/2016-01-21-32---bean-scopes/</link><pubDate>Wed, 28 Sep 2016 00:00:00 +0000</pubDate><guid>https://blog.terryx.com/posts/2016-01-21-32---bean-scopes/</guid><description><![CDATA[<h3 id="bean-scopes-singleton-and-prototype">Bean scopes: singleton and prototype</h3>
<h4 id="1-singleton">1. singleton</h4>
<p>Only one instance in Spring IoC container. Only return the same Bean.</p>
<blockquote>
<p>One instance of the bean is created for the entire application.</p>
</blockquote>
<p>Two ways to implement, we could learn how Spring work through the code bellow:</p>
<ul>
<li><strong>Define static attribute to hold the instance:</strong></li>
</ul>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-java" data-lang="java"><span class="line"><span class="cl"><span class="kn">package</span><span class="w"> </span><span class="nn">cn.javass.spring.chapter3.bean</span><span class="p">;</span><span class="w">  
</span></span></span><span class="line"><span class="cl"><span class="kd">public</span><span class="w"> </span><span class="kd">class</span> <span class="nc">Singleton</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">//1. Private constructor  </span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="kd">private</span><span class="w"> </span><span class="nf">Singleton</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></span><span class="line"><span class="cl"><span class="w">    </span><span class="kd">private</span><span class="w"> </span><span class="kd">static</span><span class="w"> </span><span class="kd">class</span> <span class="nc">InstanceHolder</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">private</span><span class="w"> </span><span class="kd">static</span><span class="w"> </span><span class="kd">final</span><span class="w"> </span><span class="n">Singleton</span><span class="w"> </span><span class="n">INSTANCE</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">Singleton</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="w">    </span><span class="c1">//3.Global accession  </span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="kd">public</span><span class="w"> </span><span class="kd">static</span><span class="w"> </span><span class="n">Singleton</span><span class="w"> </span><span class="nf">getInstance</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="k">return</span><span class="w"> </span><span class="n">InstanceHolder</span><span class="p">.</span><span class="na">INSTANCE</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><ul>
<li><strong>Via <em>SingletonBeanRegistry</em>:</strong></li>
</ul>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-java" data-lang="java"><span class="line"><span class="cl"><span class="kn">import</span><span class="w"> </span><span class="nn">java.util.HashMap</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="kn">import</span><span class="w"> </span><span class="nn">java.util.Map</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="kn">import</span><span class="w"> </span><span class="nn">org.springframework.beans.factory.config.SingletonBeanRegistry</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="kd">public</span><span class="w"> </span><span class="kd">class</span> <span class="nc">SingletonBeanRegister</span><span class="w"> </span><span class="kd">implements</span><span class="w"> </span><span class="n">SingletonBeanRegistry</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">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">BEANS</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">HashMap</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="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">public</span><span class="w"> </span><span class="kt">boolean</span><span class="w"> </span><span class="nf">containsSingleton</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="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">		</span><span class="k">return</span><span class="w"> </span><span class="n">BEANS</span><span class="p">.</span><span class="na">containsKey</span><span class="p">(</span><span class="n">beanName</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="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="kd">public</span><span class="w"> </span><span class="n">Object</span><span class="w"> </span><span class="nf">getSingleton</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="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">		</span><span class="k">return</span><span class="w"> </span><span class="n">BEANS</span><span class="p">.</span><span class="na">get</span><span class="p">(</span><span class="n">beanName</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="w">	</span><span class="nd">@Override</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="kd">public</span><span class="w"> </span><span class="kt">int</span><span class="w"> </span><span class="nf">getSingletonCount</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="k">return</span><span class="w"> </span><span class="n">BEANS</span><span class="p">.</span><span class="na">size</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="w">	</span><span class="nd">@Override</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="kd">public</span><span class="w"> </span><span class="n">String</span><span class="o">[]</span><span class="w"> </span><span class="nf">getSingletonNames</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="k">return</span><span class="w"> </span><span class="n">BEANS</span><span class="p">.</span><span class="na">keySet</span><span class="p">().</span><span class="na">toArray</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="n">0</span><span class="o">]</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="w">	</span><span class="nd">@Override</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="kd">public</span><span class="w"> </span><span class="kt">void</span><span class="w"> </span><span class="nf">registerSingleton</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">Object</span><span class="w"> </span><span class="n">bean</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="k">if</span><span class="w"> </span><span class="p">(</span><span class="n">BEANS</span><span class="p">.</span><span class="na">containsKey</span><span class="p">(</span><span class="n">beanName</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="k">throw</span><span class="w"> </span><span class="k">new</span><span class="w"> </span><span class="n">RuntimeException</span><span class="p">(</span><span class="s">&#34;[&#34;</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="n">beanName</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="s">&#34;] is exist&#34;</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="w">		</span><span class="n">BEANS</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">bean</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>JUnit Test:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-java" data-lang="java"><span class="line"><span class="cl"><span class="kn">import</span><span class="w"> </span><span class="nn">org.junit.Test</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="kd">public</span><span class="w"> </span><span class="kd">class</span> <span class="nc">SingletonTest</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="nd">@Test</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="kd">public</span><span class="w"> </span><span class="kt">void</span><span class="w"> </span><span class="nf">testRegister</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">SingletonBeanRegister</span><span class="w"> </span><span class="n">register</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">SingletonBeanRegister</span><span class="p">();</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">		</span><span class="n">register</span><span class="p">.</span><span class="na">registerSingleton</span><span class="p">(</span><span class="s">&#34;bean1&#34;</span><span class="p">,</span><span class="w"> </span><span class="k">new</span><span class="w"> </span><span class="n">HelloImpl2</span><span class="p">());</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">		</span><span class="n">HelloImpl2</span><span class="w"> </span><span class="n">bean1</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">(</span><span class="n">HelloImpl2</span><span class="p">)</span><span class="w"> </span><span class="n">register</span><span class="p">.</span><span class="na">getSingleton</span><span class="p">(</span><span class="s">&#34;bean1&#34;</span><span class="p">);</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">		</span><span class="n">bean1</span><span class="p">.</span><span class="na">sayHello</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="k">try</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">register</span><span class="p">.</span><span class="na">registerSingleton</span><span class="p">(</span><span class="s">&#34;bean1&#34;</span><span class="p">,</span><span class="w"> </span><span class="k">new</span><span class="w"> </span><span class="n">HelloImpl2</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="w">		</span><span class="k">catch</span><span class="w"> </span><span class="p">(</span><span class="n">Exception</span><span class="w"> </span><span class="n">e</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">System</span><span class="p">.</span><span class="na">out</span><span class="p">.</span><span class="na">println</span><span class="p">(</span><span class="n">e</span><span class="p">.</span><span class="na">getMessage</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="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><ul>
<li><strong>We could define <em>singleton</em> in xml:</strong></li>
</ul>
<p>In most time, <em>singleton</em> is default in Spring.</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-xml" data-lang="xml"><span class="line"><span class="cl"><span class="nt">&lt;bean</span>  <span class="na">class=</span><span class="s">&#34;cn.javass.spring.chapter3.bean.Printer&#34;</span> <span class="na">scope=</span><span class="s">&#34;singleton&#34;</span><span class="nt">/&gt;</span>
</span></span></code></pre></div><h4 id="2-prototype">2. prototype</h4>
<p>Return new Bean when container request a Bean. Contrast with <em>singleton</em>, <em>prototype</em> would not cache Bean.</p>
<blockquote>
<p>One instance of the bean is created every time the bean is injected
into or retrieved from the Spring application context.</p>
</blockquote>
<ul>
<li><strong>Here is the implement of <em>prototype</em> in Spring</strong>:</li>
</ul>
<p>Bean definition:</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">public</span><span class="w"> </span><span class="kd">class</span> <span class="nc">BeanDefinition</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">//singleton</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="kd">public</span><span class="w"> </span><span class="kd">static</span><span class="w"> </span><span class="kd">final</span><span class="w"> </span><span class="kt">int</span><span class="w"> </span><span class="n">SCOPE_SINGLETON</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">0</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="c1">//prototype</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="kd">public</span><span class="w"> </span><span class="kd">static</span><span class="w"> </span><span class="kd">final</span><span class="w"> </span><span class="kt">int</span><span class="w"> </span><span class="n">SCOPE_PROTOTYPE</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">1</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="c1">//identity</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="kd">private</span><span class="w"> </span><span class="n">String</span><span class="w"> </span><span class="n">id</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">private</span><span class="w"> </span><span class="n">String</span><span class="w"> </span><span class="n">clazz</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="c1">//Scope</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="kd">private</span><span class="w"> </span><span class="kt">int</span><span class="w"> </span><span class="n">scope</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">SCOPE_SINGLETON</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">public</span><span class="w"> </span><span class="kt">void</span><span class="w"> </span><span class="nf">setId</span><span class="p">(</span><span class="n">String</span><span class="w"> </span><span class="n">id</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="k">this</span><span class="p">.</span><span class="na">id</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">id</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="w">	</span><span class="kd">public</span><span class="w"> </span><span class="n">String</span><span class="w"> </span><span class="nf">getId</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="k">return</span><span class="w"> </span><span class="k">this</span><span class="p">.</span><span class="na">id</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="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="kd">public</span><span class="w"> </span><span class="kt">void</span><span class="w"> </span><span class="nf">setClazz</span><span class="p">(</span><span class="n">String</span><span class="w"> </span><span class="n">clazz</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="k">this</span><span class="p">.</span><span class="na">clazz</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">clazz</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="w">	</span><span class="kd">public</span><span class="w"> </span><span class="n">String</span><span class="w"> </span><span class="nf">getClazz</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="k">return</span><span class="w"> </span><span class="k">this</span><span class="p">.</span><span class="na">clazz</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="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="kd">public</span><span class="w"> </span><span class="kt">void</span><span class="w"> </span><span class="nf">setScope</span><span class="p">(</span><span class="kt">int</span><span class="w"> </span><span class="n">scope</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="k">this</span><span class="p">.</span><span class="na">scope</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">scope</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="w">	</span><span class="kd">public</span><span class="w"> </span><span class="kt">int</span><span class="w"> </span><span class="nf">getScope</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="k">return</span><span class="w"> </span><span class="k">this</span><span class="p">.</span><span class="na">scope</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>Bean registry, also use Map:</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">public</span><span class="w"> </span><span class="kd">class</span> <span class="nc">BeanDifinitionRegister</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">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">DEFINITIONS</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">HashMap</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="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="kd">public</span><span class="w"> </span><span class="kt">void</span><span class="w"> </span><span class="nf">registerBeanDefinition</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 class="n">BeanDefinition</span><span class="w"> </span><span class="n">bd</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="k">if</span><span class="w"> </span><span class="p">(</span><span class="n">DEFINITIONS</span><span class="p">.</span><span class="na">containsKey</span><span class="p">(</span><span class="n">bd</span><span class="p">.</span><span class="na">getId</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="k">throw</span><span class="w"> </span><span class="k">new</span><span class="w"> </span><span class="n">RuntimeException</span><span class="p">(</span><span class="s">&#34;Bean definition is exist!&#34;</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="w">		</span><span class="n">DEFINITIONS</span><span class="p">.</span><span class="na">put</span><span class="p">(</span><span class="n">bd</span><span class="p">.</span><span class="na">getId</span><span class="p">(),</span><span class="w"> </span><span class="n">bd</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="w">	</span><span class="kd">public</span><span class="w"> </span><span class="n">BeanDefinition</span><span class="w"> </span><span class="nf">getBeanDefinition</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="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">		</span><span class="k">return</span><span class="w"> </span><span class="n">DEFINITIONS</span><span class="p">.</span><span class="na">get</span><span class="p">(</span><span class="n">beanName</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="w">	</span><span class="kd">public</span><span class="w"> </span><span class="kt">boolean</span><span class="w"> </span><span class="nf">containsBeanDefinition</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="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">		</span><span class="k">return</span><span class="w"> </span><span class="n">DEFINITIONS</span><span class="p">.</span><span class="na">containsKey</span><span class="p">(</span><span class="n">beanName</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>Bean factory checks in the registry so that the Bean is new every time:</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">public</span><span class="w"> </span><span class="kd">class</span> <span class="nc">DefaultBeanFactory</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">//Bean registry</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="kd">private</span><span class="w"> </span><span class="n">BeanDifinitionRegister</span><span class="w"> </span><span class="n">DEFINITIONS</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">BeanDifinitionRegister</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">//singleton registry</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="kd">private</span><span class="w"> </span><span class="kd">final</span><span class="w"> </span><span class="n">SingletonBeanRegistry</span><span class="w"> </span><span class="n">SINGLETONS</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">SingletonBeanRegister</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">public</span><span class="w"> </span><span class="n">Object</span><span class="w"> </span><span class="nf">getBean</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="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">		</span><span class="c1">//is Bean definition exist?</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="o">!</span><span class="n">DEFINITIONS</span><span class="p">.</span><span class="na">containsBeanDefinition</span><span class="p">(</span><span class="n">beanName</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="k">throw</span><span class="w"> </span><span class="k">new</span><span class="w"> </span><span class="n">RuntimeException</span><span class="p">(</span><span class="s">&#34;Not exist[&#34;</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="n">beanName</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="s">&#34;]Bean difinition&#34;</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="w">		</span><span class="c1">//get Bean definition</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">		</span><span class="n">BeanDefinition</span><span class="w"> </span><span class="n">bd</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">DEFINITIONS</span><span class="p">.</span><span class="na">getBeanDefinition</span><span class="p">(</span><span class="n">beanName</span><span class="p">);</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">		</span><span class="c1">//is it singleton?</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">bd</span><span class="p">.</span><span class="na">getScope</span><span class="p">()</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="n">BeanDefinition</span><span class="p">.</span><span class="na">SCOPE_SINGLETON</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">//yes</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">SINGLETONS</span><span class="p">.</span><span class="na">containsSingleton</span><span class="p">(</span><span class="n">beanName</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="k">return</span><span class="w"> </span><span class="n">SINGLETONS</span><span class="p">.</span><span class="na">getSingleton</span><span class="p">(</span><span class="n">beanName</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="w">			</span><span class="c1">//no</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">			</span><span class="n">SINGLETONS</span><span class="p">.</span><span class="na">registerSingleton</span><span class="p">(</span><span class="n">beanName</span><span class="p">,</span><span class="w"> </span><span class="n">createBean</span><span class="p">(</span><span class="n">bd</span><span class="p">));</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">			</span><span class="k">return</span><span class="w"> </span><span class="n">SINGLETONS</span><span class="p">.</span><span class="na">getSingleton</span><span class="p">(</span><span class="n">beanName</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="w">		</span><span class="c1">//if it is prototype, construct new one every time.</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">bd</span><span class="p">.</span><span class="na">getScope</span><span class="p">()</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="n">BeanDefinition</span><span class="p">.</span><span class="na">SCOPE_PROTOTYPE</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="k">return</span><span class="w"> </span><span class="n">createBean</span><span class="p">(</span><span class="n">bd</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="w">		</span><span class="k">throw</span><span class="w"> </span><span class="k">new</span><span class="w"> </span><span class="n">RuntimeException</span><span class="p">(</span><span class="s">&#34;UNKNOWN Definition!&#34;</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="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="kd">public</span><span class="w"> </span><span class="kt">void</span><span class="w"> </span><span class="nf">registerBeanDefinition</span><span class="p">(</span><span class="n">BeanDefinition</span><span class="w"> </span><span class="n">bd</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">DEFINITIONS</span><span class="p">.</span><span class="na">registerBeanDefinition</span><span class="p">(</span><span class="n">bd</span><span class="p">.</span><span class="na">getId</span><span class="p">(),</span><span class="w"> </span><span class="n">bd</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="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="kd">private</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">BeanDefinition</span><span class="w"> </span><span class="n">bd</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">//new Bean</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">		</span><span class="k">try</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">Class</span><span class="w"> </span><span class="n">clazz</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">Class</span><span class="p">.</span><span class="na">forName</span><span class="p">(</span><span class="n">bd</span><span class="p">.</span><span class="na">getClazz</span><span class="p">());</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">			</span><span class="k">return</span><span class="w"> </span><span class="n">clazz</span><span class="p">.</span><span class="na">getConstructor</span><span class="p">().</span><span class="na">newInstance</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 class="k">catch</span><span class="w"> </span><span class="p">(</span><span class="n">ClassNotFoundException</span><span class="w"> </span><span class="n">e</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="k">throw</span><span class="w"> </span><span class="k">new</span><span class="w"> </span><span class="n">RuntimeException</span><span class="p">(</span><span class="s">&#34;Not found Bean[&#34;</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="n">bd</span><span class="p">.</span><span class="na">getId</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 class="k">catch</span><span class="w"> </span><span class="p">(</span><span class="n">Exception</span><span class="w"> </span><span class="n">e</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="k">throw</span><span class="w"> </span><span class="k">new</span><span class="w"> </span><span class="n">RuntimeException</span><span class="p">(</span><span class="s">&#34;New Bean[&#34;</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="n">bd</span><span class="p">.</span><span class="na">getId</span><span class="p">()</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="s">&#34;] failed&#34;</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="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>Junit test:</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">public</span><span class="w"> </span><span class="kd">class</span> <span class="nc">BeanFatoryTest</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="nd">@Test</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="kd">public</span><span class="w"> </span><span class="kt">void</span><span class="w"> </span><span class="nf">testPrototype</span><span class="p">()</span><span class="w"> </span><span class="kd">throws</span><span class="w"> </span><span class="n">Exception</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">//new Bean factory</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">		</span><span class="n">DefaultBeanFactory</span><span class="w"> </span><span class="n">bf</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">DefaultBeanFactory</span><span class="p">();</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">		</span><span class="c1">//new Bean definition</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">		</span><span class="n">BeanDefinition</span><span class="w"> </span><span class="n">bd</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">BeanDefinition</span><span class="p">();</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">		</span><span class="n">bd</span><span class="p">.</span><span class="na">setId</span><span class="p">(</span><span class="s">&#34;bean&#34;</span><span class="p">);</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">		</span><span class="n">bd</span><span class="p">.</span><span class="na">setScope</span><span class="p">(</span><span class="n">BeanDefinition</span><span class="p">.</span><span class="na">SCOPE_PROTOTYPE</span><span class="p">);</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">		</span><span class="n">bd</span><span class="p">.</span><span class="na">setClazz</span><span class="p">(</span><span class="n">HelloImpl2</span><span class="p">.</span><span class="na">class</span><span class="p">.</span><span class="na">getName</span><span class="p">());</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">		</span><span class="n">bf</span><span class="p">.</span><span class="na">registerBeanDefinition</span><span class="p">(</span><span class="n">bd</span><span class="p">);</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">		</span><span class="n">System</span><span class="p">.</span><span class="na">out</span><span class="p">.</span><span class="na">println</span><span class="p">(</span><span class="n">bf</span><span class="p">.</span><span class="na">getBean</span><span class="p">(</span><span class="s">&#34;bean&#34;</span><span class="p">)</span><span class="w"> </span><span class="o">!=</span><span class="w"> </span><span class="n">bf</span><span class="p">.</span><span class="na">getBean</span><span class="p">(</span><span class="s">&#34;bean&#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="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><ul>
<li><strong>We could define <em>prototype</em> in xml:</strong></li>
</ul>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-xml" data-lang="xml"><span class="line"><span class="cl"><span class="nt">&lt;bean</span>  <span class="na">class=</span><span class="s">&#34;cn.javass.spring.chapter3.bean.Printer&#34;</span> <span class="na">scope=</span><span class="s">&#34;prototypes&#34;</span><span class="nt">/&gt;</span>
</span></span></code></pre></div><h3 id="bean-scopes-in-web-application">Bean Scopes in Web application</h3>
<h4 id="1-request">1. request</h4>
<blockquote>
<p>In a web application, one instance of the bean is created for each
request.</p>
</blockquote>
<h4 id="2-session">2. session</h4>
<blockquote>
<p>In a web application, one instance of the bean is created for each session.</p>
</blockquote>
]]></description></item><item><title>4.1 Resource</title><link>https://blog.terryx.com/posts/2016-01-21-41-resource/</link><pubDate>Wed, 28 Sep 2016 00:00:00 +0000</pubDate><guid>https://blog.terryx.com/posts/2016-01-21-41-resource/</guid><description><![CDATA[<h3 id="resource">Resource</h3>
<h4 id="1-resource-api">1. Resource API</h4>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-java" data-lang="java"><span class="line"><span class="cl"><span class="kd">public</span><span class="w"> </span><span class="kd">interface</span> <span class="nc">InputStreamSource</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">InputStream</span><span class="w"> </span><span class="nf">getInputStream</span><span class="p">()</span><span class="w"> </span><span class="kd">throws</span><span class="w"> </span><span class="n">IOException</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><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-java" data-lang="java"><span class="line"><span class="cl"><span class="kd">public</span><span class="w"> </span><span class="kd">interface</span> <span class="nc">Resource</span><span class="w"> </span><span class="kd">extends</span><span class="w"> </span><span class="n">InputStreamSource</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="kt">boolean</span><span class="w"> </span><span class="nf">exists</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="nf">isReadable</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="nf">isOpen</span><span class="p">();</span><span class="w">  
</span></span></span><span class="line"><span class="cl"><span class="w">       </span><span class="n">URL</span><span class="w"> </span><span class="nf">getURL</span><span class="p">()</span><span class="w"> </span><span class="kd">throws</span><span class="w"> </span><span class="n">IOException</span><span class="p">;</span><span class="w">  
</span></span></span><span class="line"><span class="cl"><span class="w">       </span><span class="n">URI</span><span class="w"> </span><span class="nf">getURI</span><span class="p">()</span><span class="w"> </span><span class="kd">throws</span><span class="w"> </span><span class="n">IOException</span><span class="p">;</span><span class="w">  
</span></span></span><span class="line"><span class="cl"><span class="w">       </span><span class="n">File</span><span class="w"> </span><span class="nf">getFile</span><span class="p">()</span><span class="w"> </span><span class="kd">throws</span><span class="w"> </span><span class="n">IOException</span><span class="p">;</span><span class="w">  
</span></span></span><span class="line"><span class="cl"><span class="w">       </span><span class="kt">long</span><span class="w"> </span><span class="nf">contentLength</span><span class="p">()</span><span class="w"> </span><span class="kd">throws</span><span class="w"> </span><span class="n">IOException</span><span class="p">;</span><span class="w">  
</span></span></span><span class="line"><span class="cl"><span class="w">       </span><span class="kt">long</span><span class="w"> </span><span class="nf">lastModified</span><span class="p">()</span><span class="w"> </span><span class="kd">throws</span><span class="w"> </span><span class="n">IOException</span><span class="p">;</span><span class="w">  
</span></span></span><span class="line"><span class="cl"><span class="w">       </span><span class="n">Resource</span><span class="w"> </span><span class="nf">createRelative</span><span class="p">(</span><span class="n">String</span><span class="w"> </span><span class="n">relativePath</span><span class="p">)</span><span class="w"> </span><span class="kd">throws</span><span class="w"> </span><span class="n">IOException</span><span class="p">;</span><span class="w">  
</span></span></span><span class="line"><span class="cl"><span class="w">       </span><span class="n">String</span><span class="w"> </span><span class="nf">getFilename</span><span class="p">();</span><span class="w">  
</span></span></span><span class="line"><span class="cl"><span class="w">       </span><span class="n">String</span><span class="w"> </span><span class="nf">getDescription</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><ul>
<li>
<p><strong><em>InputStreamSource</em>:</strong></p>
</li>
<li>
<p><em><strong>getInputStream</strong></em>: Return new <em>java.io.InputStream</em> which needs close after used.</p>
</li>
<li>
<p><strong><em>Resource</em> extends <em>InputStreamSource</em>:</strong></p>
</li>
<li>
<p><em><strong>exists</strong></em>: Resource exists?</p>
</li>
<li>
<p><em><strong>isReadable</strong></em>: Resource readable?</p>
</li>
<li>
<p><em><strong>isOpen</strong></em>: Resource open?</p>
</li>
<li>
<p><em><strong>getURL</strong></em>: <em>java.util.URL</em>.</p>
</li>
<li>
<p><em><strong>getURI</strong></em>: <em>java.util.URI</em>.</p>
</li>
</ul>
<blockquote>
<p>URIs identify and URLs locate; however, locators are also identifiers, so every URL is also a URI, but there are URIs which are not URLs.</p>
</blockquote>
<ul>
<li><em><strong>getFile</strong></em>: <em>java.io.File</em>.</li>
<li><em><strong>contentLength</strong></em>: Resource length.</li>
<li><strong>lastModified_</strong>: Modified date.</li>
<li><em><strong>createRelateive</strong></em>: create file in Resource.</li>
<li><em><strong>getFilename</strong></em>: ONLY return <strong>file path</strong>.</li>
<li><em><strong>getDescription</strong></em> return <strong>full file path</strong>.</li>
</ul>
]]></description></item><item><title>4.2 Using Resource</title><link>https://blog.terryx.com/posts/2016-01-22-42--using-resource/</link><pubDate>Wed, 28 Sep 2016 00:00:00 +0000</pubDate><guid>https://blog.terryx.com/posts/2016-01-22-42--using-resource/</guid><description><![CDATA[<h3 id="using-resource">Using Resource</h3>
<h4 id="1-bytearrayresource">1. ByteArrayResource</h4>
<p>Junit test:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-java" data-lang="java"><span class="line"><span class="cl"><span class="kn">import</span><span class="w"> </span><span class="nn">org.junit.Test</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="kn">import</span><span class="w"> </span><span class="nn">org.springframework.core.io.ByteArrayResource</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="kn">import</span><span class="w"> </span><span class="nn">org.springframework.core.io.Resource</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="kd">public</span><span class="w"> </span><span class="kd">class</span> <span class="nc">ResourceTest</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="nd">@Test</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="kd">public</span><span class="w"> </span><span class="kt">void</span><span class="w"> </span><span class="nf">testByteArraryResorce</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">Resource</span><span class="w"> </span><span class="n">resource</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">ByteArrayResource</span><span class="p">(</span><span class="s">&#34;Hello World!&#34;</span><span class="p">.</span><span class="na">getBytes</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">resource</span><span class="p">.</span><span class="na">exists</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">dumpStream</span><span class="p">(</span><span class="n">resource</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="w">		</span><span class="n">Assert</span><span class="p">.</span><span class="na">assertEquals</span><span class="p">(</span><span class="kc">false</span><span class="p">,</span><span class="w"> </span><span class="n">resource</span><span class="p">.</span><span class="na">isOpen</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="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="kd">private</span><span class="w"> </span><span class="kt">void</span><span class="w"> </span><span class="nf">dumpStream</span><span class="p">(</span><span class="n">Resource</span><span class="w"> </span><span class="n">resource</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">InputStream</span><span class="w"> </span><span class="n">inputStream</span><span class="w"> </span><span class="o">=</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="w">		</span><span class="k">try</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">inputStream</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">resource</span><span class="p">.</span><span class="na">getInputStream</span><span class="p">();</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">			</span><span class="kt">byte</span><span class="w"> </span><span class="o">[]</span><span class="w"> </span><span class="n">descByte</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="k">new</span><span class="w"> </span><span class="kt">byte</span><span class="w"> </span><span class="o">[</span><span class="n">inputStream</span><span class="p">.</span><span class="na">available</span><span class="p">()</span><span class="o">]</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">			</span><span class="n">inputStream</span><span class="p">.</span><span class="na">read</span><span class="p">(</span><span class="n">descByte</span><span class="p">);</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">			</span><span class="n">System</span><span class="p">.</span><span class="na">out</span><span class="p">.</span><span class="na">println</span><span class="p">(</span><span class="k">new</span><span class="w"> </span><span class="n">String</span><span class="p">(</span><span class="n">descByte</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 class="k">catch</span><span class="w"> </span><span class="p">(</span><span class="n">IOException</span><span class="w"> </span><span class="n">e</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">e</span><span class="p">.</span><span class="na">printStackTrace</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 class="k">finally</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">try</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">inputStream</span><span class="p">.</span><span class="na">close</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 class="k">catch</span><span class="w"> </span><span class="p">(</span><span class="n">IOException</span><span class="w"> </span><span class="n">e</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">e</span><span class="p">.</span><span class="na">printStackTrace</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="w">		</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><strong>NOTE:</strong> <em><strong>ByteArrayResource</strong></em> can be used repeatedly, because <em><strong>isOpen()</strong></em> always returns <em>false</em>.</p>
<h4 id="2-inputstreamresource">2. InputStreamResource:</h4>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-java" data-lang="java"><span class="line"><span class="cl"><span class="nd">@Test</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">testInputStreamResource</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">ByteArrayInputStream</span><span class="w"> </span><span class="n">byteArrayInputStream</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">ByteArrayInputStream</span><span class="p">(</span><span class="s">&#34;Hello World!&#34;</span><span class="p">.</span><span class="na">getBytes</span><span class="p">());</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">		</span><span class="n">Resource</span><span class="w"> </span><span class="n">resource</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">InputStreamResource</span><span class="p">(</span><span class="n">byteArrayInputStream</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">resource</span><span class="p">.</span><span class="na">exists</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">dumpStream</span><span class="p">(</span><span class="n">resource</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="w">		</span><span class="n">Assert</span><span class="p">.</span><span class="na">assertEquals</span><span class="p">(</span><span class="kc">true</span><span class="p">,</span><span class="w"> </span><span class="n">resource</span><span class="p">.</span><span class="na">isOpen</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><strong>NOTE:</strong> <em><strong>InputStreamResource</strong></em> can be used only one time, because <em><strong>isOpen()</strong></em> always returns <em>true</em>.</p>
<h4 id="3-filesystemresource">3. FileSystemResource:</h4>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-java" data-lang="java"><span class="line"><span class="cl"><span class="nd">@Test</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">testFileResource</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">File</span><span class="w"> </span><span class="n">file</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">File</span><span class="p">(</span><span class="s">&#34;d:/test.txt&#34;</span><span class="p">);</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">		</span><span class="n">Resource</span><span class="w"> </span><span class="n">resource</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">FileSystemResource</span><span class="p">(</span><span class="n">file</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">resource</span><span class="p">.</span><span class="na">exists</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">dumpStream</span><span class="p">(</span><span class="n">resource</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="w">		</span><span class="n">Assert</span><span class="p">.</span><span class="na">assertEquals</span><span class="p">(</span><span class="kc">false</span><span class="p">,</span><span class="w"> </span><span class="n">resource</span><span class="p">.</span><span class="na">isOpen</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><strong>NOTE:</strong> <em><strong>FileSystemResource</strong></em> can be used repeatedly, because <em><strong>isOpen()</strong></em> always returns <em>false</em>.</p>
<h4 id="4-classpathresource">4. ClassPathResource:</h4>
<p><em><strong>ClassPathResource</strong></em> replaces <em><strong>Class</strong></em> and <em><strong>ClassLoader</strong></em> to give a uniform implement. The resource can be used repeatedly, because <em><strong>isOpen()</strong></em> always returns <em>false</em>.</p>
<p>Here are three constructors in <em><strong>ClassPathResource</strong></em>:</p>
<ul>
<li><em><strong>public ClassPathResource(String path)</strong></em>: using default <em><strong>ClassLoader</strong></em> to load resource.</li>
<li><em><strong>public ClassPathResource(String path, ClassLoader classLoader)</strong></em>: using specified <em><strong>ClassLoader</strong></em> to load path resource.</li>
<li><strong>_ public ClassPathResource(String path, Class<?> clazz)_</strong>: using <em>Class</em> path to load resource.</li>
</ul>
<blockquote>
<p>For example, if the Class path is “cn.javass.spring.ResourceTest”, the path is “cn/javass/spring/ResourceTest”.</p>
</blockquote>
<ol>
<li><em><strong>public ClassPathResource(String path)</strong></em>:</li>
</ol>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-java" data-lang="java"><span class="line"><span class="cl"><span class="nd">@Test</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">testClasspathResourceBydefaultClassLoader</span><span class="p">()</span><span class="w"> </span><span class="kd">throws</span><span class="w"> </span><span class="n">IOException</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">Resource</span><span class="w"> </span><span class="n">resource</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">ClassPathResource</span><span class="p">(</span><span class="s">&#34;cn/javass/spring/chapter4/test.properties&#34;</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">resource</span><span class="p">.</span><span class="na">exists</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">dumpStream</span><span class="p">(</span><span class="n">resource</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="w">		</span><span class="n">System</span><span class="p">.</span><span class="na">out</span><span class="p">.</span><span class="na">println</span><span class="p">(</span><span class="s">&#34;path:&#34;</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="n">resource</span><span class="p">.</span><span class="na">getFile</span><span class="p">().</span><span class="na">getAbsolutePath</span><span class="p">());</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">		</span><span class="n">Assert</span><span class="p">.</span><span class="na">assertEquals</span><span class="p">(</span><span class="kc">false</span><span class="p">,</span><span class="w"> </span><span class="n">resource</span><span class="p">.</span><span class="na">isOpen</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><ol>
<li><em><strong>public ClassPathResource(String path, ClassLoader classLoader)</strong></em>:</li>
</ol>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-java" data-lang="java"><span class="line"><span class="cl"><span class="nd">@Test</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">testClasspathResourceByClassLoader</span><span class="p">()</span><span class="w"> </span><span class="kd">throws</span><span class="w"> </span><span class="n">IOException</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">ClassLoader</span><span class="w"> </span><span class="n">classLoader</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="k">this</span><span class="p">.</span><span class="na">getClass</span><span class="p">().</span><span class="na">getClassLoader</span><span class="p">();</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">		</span><span class="n">Resource</span><span class="w"> </span><span class="n">resource</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">ClassPathResource</span><span class="p">(</span><span class="s">&#34;cn/javass/spring/chapter4/test.properties&#34;</span><span class="p">,</span><span class="w"> </span><span class="n">classLoader</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">resource</span><span class="p">.</span><span class="na">exists</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">dumpStream</span><span class="p">(</span><span class="n">resource</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="w">		</span><span class="n">System</span><span class="p">.</span><span class="na">out</span><span class="p">.</span><span class="na">println</span><span class="p">(</span><span class="s">&#34;path:&#34;</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="n">resource</span><span class="p">.</span><span class="na">getFile</span><span class="p">().</span><span class="na">getAbsolutePath</span><span class="p">());</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">		</span><span class="n">Assert</span><span class="p">.</span><span class="na">assertEquals</span><span class="p">(</span><span class="kc">false</span><span class="p">,</span><span class="w"> </span><span class="n">resource</span><span class="p">.</span><span class="na">isOpen</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><ol>
<li><strong>_ public ClassPathResource(String path, Class<?> clazz)_</strong>:</li>
</ol>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-java" data-lang="java"><span class="line"><span class="cl"><span class="nd">@Test</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">testClasspathResourceByClass</span><span class="p">()</span><span class="w"> </span><span class="kd">throws</span><span class="w"> </span><span class="n">IOException</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">Class</span><span class="w"> </span><span class="n">clazz</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="k">this</span><span class="p">.</span><span class="na">getClass</span><span class="p">();</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">		</span><span class="n">Resource</span><span class="w"> </span><span class="n">resource1</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">ClassPathResource</span><span class="p">(</span><span class="s">&#34;cn/javass/spring/chapter4/test.properties&#34;</span><span class="p">,</span><span class="w"> </span><span class="n">clazz</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">resource1</span><span class="p">.</span><span class="na">exists</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">dumpStream</span><span class="p">(</span><span class="n">resource1</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="w">		</span><span class="n">System</span><span class="p">.</span><span class="na">out</span><span class="p">.</span><span class="na">println</span><span class="p">(</span><span class="s">&#34;path:&#34;</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="n">resource1</span><span class="p">.</span><span class="na">getFile</span><span class="p">().</span><span class="na">getAbsolutePath</span><span class="p">());</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">		</span><span class="n">Assert</span><span class="p">.</span><span class="na">assertEquals</span><span class="p">(</span><span class="kc">false</span><span class="p">,</span><span class="w"> </span><span class="n">resource1</span><span class="p">.</span><span class="na">isOpen</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="n">Resource</span><span class="w"> </span><span class="n">resource2</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">ClassPathResource</span><span class="p">(</span><span class="s">&#34;cn/javass/spring/chapter4/test.properties&#34;</span><span class="p">,</span><span class="w"> </span><span class="k">this</span><span class="p">.</span><span class="na">getClass</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">resource2</span><span class="p">.</span><span class="na">exists</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">dumpStream</span><span class="p">(</span><span class="n">resource2</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="w">		</span><span class="n">System</span><span class="p">.</span><span class="na">out</span><span class="p">.</span><span class="na">println</span><span class="p">(</span><span class="s">&#34;path:&#34;</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="n">resource2</span><span class="p">.</span><span class="na">getFile</span><span class="p">().</span><span class="na">getAbsolutePath</span><span class="p">());</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">		</span><span class="n">Assert</span><span class="p">.</span><span class="na">assertEquals</span><span class="p">(</span><span class="kc">false</span><span class="p">,</span><span class="w"> </span><span class="n">resource1</span><span class="p">.</span><span class="na">isOpen</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>If not provide the full path, it will search in the <em><strong>resource</strong></em> folder. If not found in the <em><strong>resource</strong></em> folder, it will search in other package folders.</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">@Test</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">classpathResourceTestFromJar</span><span class="p">()</span><span class="w"> </span><span class="kd">throws</span><span class="w"> </span><span class="n">IOException</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">Resource</span><span class="w"> </span><span class="n">resource</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">ClassPathResource</span><span class="p">(</span><span class="s">&#34;overview.html&#34;</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">resource</span><span class="p">.</span><span class="na">exists</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">dumpStream</span><span class="p">(</span><span class="n">resource</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="w">		</span><span class="n">System</span><span class="p">.</span><span class="na">out</span><span class="p">.</span><span class="na">println</span><span class="p">(</span><span class="s">&#34;path:&#34;</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="n">resource</span><span class="p">.</span><span class="na">getURL</span><span class="p">().</span><span class="na">getPath</span><span class="p">());</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">		</span><span class="n">Assert</span><span class="p">.</span><span class="na">assertEquals</span><span class="p">(</span><span class="kc">false</span><span class="p">,</span><span class="w"> </span><span class="n">resource</span><span class="p">.</span><span class="na">isOpen</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><h3 id="5-urlresource">5. UrlResource:</h3>
<p><em><strong>isOpen()</strong></em> always return <em>false</em>. Supporting three ways to load resources:</p>
<ul>
<li><strong>http</strong></li>
<li><strong>ftp</strong></li>
<li><strong>file:</strong> For example, <strong>new <em>UrlResource</em>(“<em>file:d:/test.txt</em>“)</strong>.</li>
</ul>
<h3 id="6-servletcontextresource">6. ServletContextResource:</h3>
<p>To simplize the <em><strong>ServletContext</strong></em> of servlet.</p>
<h3 id="7-vfsresource">7. VfsResource:</h3>
<p>JBoss AS is now provide on <a href="http://wildfly.org/downloads/">http://wildfly.org/downloads/</a>.</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">@Test</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">testVfsResourceForRealFileSystem</span><span class="p">()</span><span class="w"> </span><span class="kd">throws</span><span class="w"> </span><span class="n">IOException</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">//New virtual path</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">		</span><span class="n">VirtualFile</span><span class="w"> </span><span class="n">home</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">VFS</span><span class="p">.</span><span class="na">getChild</span><span class="p">(</span><span class="s">&#34;/home&#34;</span><span class="p">);</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">		</span><span class="c1">//Mapping physical path</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">		</span><span class="n">VFS</span><span class="p">.</span><span class="na">mount</span><span class="p">(</span><span class="n">home</span><span class="p">,</span><span class="w"> </span><span class="k">new</span><span class="w"> </span><span class="n">RealFileSystem</span><span class="p">(</span><span class="k">new</span><span class="w"> </span><span class="n">File</span><span class="p">(</span><span class="s">&#34;d:&#34;</span><span class="p">)));</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">		</span><span class="c1">//Load resource from virtual path</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">		</span><span class="n">VirtualFile</span><span class="w"> </span><span class="n">virtualFile</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">home</span><span class="p">.</span><span class="na">getChild</span><span class="p">(</span><span class="s">&#34;test.txt&#34;</span><span class="p">);</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">		</span><span class="n">Resource</span><span class="w"> </span><span class="n">resource</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">VfsResource</span><span class="p">(</span><span class="n">virtualFile</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">resource</span><span class="p">.</span><span class="na">exists</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">dumpStream</span><span class="p">(</span><span class="n">resource</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="w">		</span><span class="n">System</span><span class="p">.</span><span class="na">out</span><span class="p">.</span><span class="na">println</span><span class="p">(</span><span class="n">resource</span><span class="p">.</span><span class="na">getFile</span><span class="p">().</span><span class="na">getAbsolutePath</span><span class="p">());</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">		</span><span class="n">Assert</span><span class="p">.</span><span class="na">assertEquals</span><span class="p">(</span><span class="kc">false</span><span class="p">,</span><span class="w"> </span><span class="n">resource</span><span class="p">.</span><span class="na">isOpen</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>]]></description></item><item><title>4.3 Access Resource</title><link>https://blog.terryx.com/posts/2016-01-22-43--access-resource/</link><pubDate>Wed, 28 Sep 2016 00:00:00 +0000</pubDate><guid>https://blog.terryx.com/posts/2016-01-22-43--access-resource/</guid><description><![CDATA[<h3 id="access-resource">Access Resource</h3>
<h4 id="1-resourceloader">1. ResourceLoader</h4>
<p>Spring has a <em><strong>DefaultResourceLoader</strong></em> which can return <em><strong>ClassPathResource</strong></em>, <em><strong>UrlResource</strong></em>, and <em><strong>ServletContextResourceLoader</strong></em> which extends all functions of <em><strong>DefaultResourceLoader</strong></em>.</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">@Test</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">testResourceLoad</span><span class="p">()</span><span class="w"> </span><span class="kd">throws</span><span class="w"> </span><span class="n">IOException</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">ResourceLoader</span><span class="w"> </span><span class="n">loader</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">DefaultResourceLoader</span><span class="p">();</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="n">Resource</span><span class="w"> </span><span class="n">resource</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">loader</span><span class="p">.</span><span class="na">getResource</span><span class="p">(</span><span class="s">&#34;classpath:cn/javass/spring/chapter4/test.txt&#34;</span><span class="p">);</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="n">Assert</span><span class="p">.</span><span class="na">assertEquals</span><span class="p">(</span><span class="n">ClassPathResource</span><span class="p">.</span><span class="na">class</span><span class="p">,</span><span class="w"> </span><span class="n">resource</span><span class="p">.</span><span class="na">getClass</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 <em><strong>ApplicationContext</strong></em> also can implement <em><strong>ResourceLoader</strong></em>:</p>
<ul>
<li><em><strong>ClassPathXmlApplicationContext</strong></em></li>
<li><em><strong>FileSystemXmlApplicationContext</strong></em></li>
<li><em><strong>WebApplicationContext</strong></em></li>
</ul>
<h4 id="2-resourceloaderaware">2. ResourceLoaderAware</h4>
<p>Injection via <em><strong>ApplicationContext</strong></em>:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-java" data-lang="java"><span class="line"><span class="cl"><span class="kn">import</span><span class="w"> </span><span class="nn">org.springframework.context.ResourceLoaderAware</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="kn">import</span><span class="w"> </span><span class="nn">org.springframework.core.io.ResourceLoader</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="kd">public</span><span class="w"> </span><span class="kd">class</span> <span class="nc">ResourceBean</span><span class="w"> </span><span class="kd">implements</span><span class="w"> </span><span class="n">ResourceLoaderAware</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">private</span><span class="w"> </span><span class="n">ResourceLoader</span><span class="w"> </span><span class="n">resourceLoader</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="nd">@Override</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="kd">public</span><span class="w"> </span><span class="kt">void</span><span class="w"> </span><span class="nf">setResourceLoader</span><span class="p">(</span><span class="n">ResourceLoader</span><span class="w"> </span><span class="n">resourceLoader</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="k">this</span><span class="p">.</span><span class="na">resourceLoader</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">resourceLoader</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="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="kd">public</span><span class="w"> </span><span class="n">ResourceLoader</span><span class="w"> </span><span class="nf">getResourceLoader</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="k">return</span><span class="w"> </span><span class="n">resourceLoader</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><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-xml" data-lang="xml"><span class="line"><span class="cl"><span class="nt">&lt;bean</span> <span class="na">class=</span><span class="s">&#34;cn.javass.spring.chapter4.ResourceBean&#34;</span> <span class="nt">/&gt;</span>
</span></span></code></pre></div><p>JUnit test:</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">@Test</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">test</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">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;chapter4/resourceLoaderAware.xml&#34;</span><span class="p">);</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">		</span><span class="n">ResourceBean</span><span class="w"> </span><span class="n">bean</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="n">ResourceBean</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 class="n">ResourceLoader</span><span class="w"> </span><span class="n">loader</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">bean</span><span class="p">.</span><span class="na">getResourceLoader</span><span class="p">();</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">		</span><span class="n">Assert</span><span class="p">.</span><span class="na">assertTrue</span><span class="p">(</span><span class="n">loader</span><span class="w"> </span><span class="k">instanceof</span><span class="w"> </span><span class="n">ApplicationContext</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><h4 id="3-resource-injection">3. Resource Injection</h4>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-java" data-lang="java"><span class="line"><span class="cl"><span class="kn">import</span><span class="w"> </span><span class="nn">org.springframework.core.io.Resource</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="kd">public</span><span class="w"> </span><span class="kd">class</span> <span class="nc">ResourceBean3</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">private</span><span class="w"> </span><span class="n">Resource</span><span class="w"> </span><span class="n">resource</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">public</span><span class="w"> </span><span class="n">Resource</span><span class="w"> </span><span class="nf">getResource</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="k">return</span><span class="w"> </span><span class="k">this</span><span class="p">.</span><span class="na">resource</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="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="kd">public</span><span class="w"> </span><span class="kt">void</span><span class="w"> </span><span class="nf">setResource</span><span class="p">(</span><span class="n">Resource</span><span class="w"> </span><span class="n">resource</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="k">this</span><span class="p">.</span><span class="na">resource</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">resource</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><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-xml" data-lang="xml"><span class="line"><span class="cl"><span class="nt">&lt;bean</span> <span class="na">id=</span><span class="s">&#34;resourceBean1&#34;</span> <span class="na">class=</span><span class="s">&#34;cn.javass.spring.chapter4.ResourceBean3&#34;</span><span class="nt">&gt;</span>
</span></span><span class="line"><span class="cl">	<span class="nt">&lt;property</span> <span class="na">name=</span><span class="s">&#34;resource&#34;</span> <span class="na">value=</span><span class="s">&#34;cn/javass/spring/chapter4/test.properties&#34;</span><span class="nt">/&gt;</span>
</span></span><span class="line"><span class="cl"><span class="nt">&lt;/bean&gt;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="nt">&lt;bean</span> <span class="na">id=</span><span class="s">&#34;resourceBean2&#34;</span> <span class="na">class=</span><span class="s">&#34;cn.javass.spring.chapter4.ResourceBean3&#34;</span><span class="nt">&gt;</span>
</span></span><span class="line"><span class="cl">	<span class="nt">&lt;property</span> <span class="na">name=</span><span class="s">&#34;resource&#34;</span> <span class="na">value=</span><span class="s">&#34;classpath:cn/javass/spring/chapter4/test.properties&#34;</span><span class="nt">/&gt;</span>
</span></span><span class="line"><span class="cl"><span class="nt">&lt;/bean&gt;</span>
</span></span></code></pre></div><p>JUnit test:</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">@Test</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">test</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">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;chapter4/resourceInject.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="w">		</span><span class="n">ResourceBean3</span><span class="w"> </span><span class="n">resourceBean1</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;resourceBean1&#34;</span><span class="p">,</span><span class="w"> </span><span class="n">ResourceBean3</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="w">		</span><span class="n">ResourceBean3</span><span class="w"> </span><span class="n">resourceBean2</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;resourceBean2&#34;</span><span class="p">,</span><span class="w"> </span><span class="n">ResourceBean3</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="w">		</span><span class="n">Assert</span><span class="p">.</span><span class="na">assertTrue</span><span class="p">(</span><span class="n">resourceBean1</span><span class="p">.</span><span class="na">getResource</span><span class="p">()</span><span class="w"> </span><span class="k">instanceof</span><span class="w"> </span><span class="n">ClassPathResource</span><span class="p">);</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">		</span><span class="n">Assert</span><span class="p">.</span><span class="na">assertTrue</span><span class="p">(</span><span class="n">resourceBean2</span><span class="p">.</span><span class="na">getResource</span><span class="p">()</span><span class="w"> </span><span class="k">instanceof</span><span class="w"> </span><span class="n">ClassPathResource</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>]]></description></item><item><title>Java Web 系统总结 (一)</title><link>https://blog.terryx.com/posts/2016-02-16-java-web-summary-1/</link><pubDate>Wed, 28 Sep 2016 00:00:00 +0000</pubDate><guid>https://blog.terryx.com/posts/2016-02-16-java-web-summary-1/</guid><description><![CDATA[<h3 id="一-jsp-总结">一. JSP 总结</h3>
<h4 id="9个隐含对象及其常用方法-虽然为-java-代码-但是使用-el-表达式完全可以进行调用相关-get-方法">9个隐含对象及其常用方法 (虽然为 Java 代码, 但是使用 <em>EL</em> 表达式完全可以进行调用相关 get 方法):</h4>
<p><strong>1. <em>Request (HttpServletRequest)</em></strong></p>
<ul>
<li><strong>Attribute</strong> 相关:</li>
</ul>
<p>可以理解在 <code>request</code> 作用域范围内的一个存储空间, 实现方法是将键值对放入一个 <code>HashMap</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="n">Object</span><span class="w"> </span><span class="nf">getAttribute</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="kt">void</span><span class="w"> </span><span class="nf">setAttribute</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 class="n">Object</span><span class="w"> </span><span class="n">o</span><span class="p">);</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="kt">void</span><span class="w"> </span><span class="nf">removeAttribute</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></code></pre></div><ul>
<li><strong>Paramater</strong> 相关:</li>
</ul>
<p>一般用于与 <code>html</code>, <code>jsp</code>页面 及 <code>url</code> 地址传递参数, 仅能传递字符串. 注意: 没有 <code>setParamater</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="n">String</span><span class="w"> </span><span class="nf">getParameter</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="n">String</span><span class="o">[]</span><span class="w"> </span><span class="nf">getParameterValues</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></code></pre></div><ul>
<li><strong>Cookie</strong> 相关:</li>
</ul>
<p>作为浏览器端持久化储存的一种实现方法, 由服务器加入 <code>response</code> 中, 并在 <code>request</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="n">Cookie</span><span class="o">[]</span><span class="w"> </span><span class="nf">getCookies</span><span class="p">();</span><span class="w">
</span></span></span></code></pre></div><ul>
<li><strong>Session</strong> 相关:</li>
</ul>
<p>作为服务器持久化储存的一种实现方法, 在浏览器第一次访问服务器资源时自动创建.</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">HttpSession</span><span class="w"> </span><span class="nf">getSession</span><span class="p">();</span><span class="w">
</span></span></span></code></pre></div><ul>
<li><strong>URI</strong> 路径:</li>
</ul>
<p><strong>应用名称 + 页面路径</strong></p>
<p>比如: <code>/day_15/bbs/bbs.jsp</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="n">String</span><span class="w"> </span><span class="nf">getRequestURI</span><span class="p">();</span><span class="w">
</span></span></span></code></pre></div><ul>
<li><strong>URL</strong> 路径:</li>
</ul>
<p><strong>站点地址 + URI路径</strong></p>
<p>比如: <code>http://localhost:8080/day_15/bbs/bbs.jsp</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="n">StringBuffer</span><span class="w"> </span><span class="nf">getRequestURL</span><span class="p">();</span><span class="w">
</span></span></span></code></pre></div><ul>
<li><strong>ServletPath</strong> 路径:</li>
</ul>
<p><strong>页面路径</strong></p>
<p>一般用于 <code>filter</code> 进行页面筛选. 比如: <code>/bbs/bbs.jsp</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="n">String</span><span class="w"> </span><span class="nf">getServletPath</span><span class="p">();</span><span class="w">
</span></span></span></code></pre></div><ul>
<li>转发地址:</li>
</ul>
<p>可以将 <code>request</code> 转发到另一页面或 <code>Servlet</code>. 注意: <code>path</code> 为 <code>Servlet context path</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="n">RequestDispatcher</span><span class="w"> </span><span class="nf">getRequestDispatcher</span><span class="p">(</span><span class="n">String</span><span class="w"> </span><span class="n">path</span><span class="p">);</span><span class="w">
</span></span></span></code></pre></div><ul>
<li>编码问题:</li>
</ul>
<p>对于携带中文作为 <code>Paramater</code> 的 <code>request</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="kt">void</span><span class="w"> </span><span class="nf">setCharacterEncoding</span><span class="p">(</span><span class="n">String</span><span class="w"> </span><span class="n">env</span><span class="p">);</span><span class="w">
</span></span></span></code></pre></div><p><strong>2. <em>Response (HttpServletResponse)</em></strong></p>
<ul>
<li><strong>Cookie</strong> 相关:</li>
</ul>
<p>作为浏览器端持久化储存的一种实现方法, 由服务器加入 <code>response</code> 中, 并在 <code>request</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="kt">void</span><span class="w"> </span><span class="nf">addCookie</span><span class="p">(</span><span class="n">Cookie</span><span class="w"> </span><span class="n">cookie</span><span class="p">)</span><span class="w">
</span></span></span></code></pre></div><ul>
<li>重定向地址</li>
</ul>
<p>可以跳转到另一页面, 但不转发 <code>request</code>. <code>location</code> 必须包含 <code>application context path</code> 或为 <code>URL</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="kt">void</span><span class="w"> </span><span class="nf">sendRedirect</span><span class="p">(</span><span class="n">String</span><span class="w"> </span><span class="n">location</span><span class="p">);</span><span class="w">
</span></span></span></code></pre></div><p><strong>3. <em>Session (HttpSession)</em></strong></p>
<ul>
<li><strong>Attribute</strong> 相关:</li>
</ul>
<p>和 <code>request</code> 类似, <code>session</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="n">Object</span><span class="w"> </span><span class="nf">getAttribute</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="kt">void</span><span class="w"> </span><span class="nf">setAttribute</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 class="n">Object</span><span class="w"> </span><span class="n">value</span><span class="p">);</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="kt">void</span><span class="w"> </span><span class="nf">removeAttribute</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></code></pre></div><ul>
<li>设置生命周期:</li>
</ul>
<p>从创建到销毁的时间.</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-java" data-lang="java"><span class="line"><span class="cl"><span class="kt">void</span><span class="w"> </span><span class="nf">setMaxInactiveInterval</span><span class="p">(</span><span class="kt">int</span><span class="w"> </span><span class="n">interval</span><span class="p">);</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="kt">int</span><span class="w"> </span><span class="nf">getMaxInactiveInterval</span><span class="p">();</span><span class="w">
</span></span></span></code></pre></div><p>立即销毁 <code>session</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="kt">void</span><span class="w"> </span><span class="nf">invalidate</span><span class="p">();</span><span class="w">
</span></span></span></code></pre></div><ul>
<li><strong>JSessionId</strong>:</li>
</ul>
<p>以 <code>JSessionId</code> 为名称存入 <code>Cookie</code> 中.</p>
<p>获取 <code>JSessionId</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="n">String</span><span class="w"> </span><span class="nf">getId</span><span class="p">();</span><span class="w">
</span></span></span></code></pre></div><ul>
<li>时间信息:</li>
</ul>
<p>获取创建与最近访问时间:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-java" data-lang="java"><span class="line"><span class="cl"><span class="kt">long</span><span class="w"> </span><span class="nf">getCreationTime</span><span class="p">();</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="kt">long</span><span class="w"> </span><span class="nf">getLastAccessedTime</span><span class="p">();</span><span class="w">
</span></span></span></code></pre></div><ul>
<li>获取 <strong>ServletContext</strong></li>
</ul>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-java" data-lang="java"><span class="line"><span class="cl"><span class="n">ServletContext</span><span class="w"> </span><span class="nf">getServletContext</span><span class="p">();</span><span class="w">
</span></span></span></code></pre></div><p>以上总结的三个隐含对象 <code>request</code> <code>response</code> <code>session</code>, 不只是对于 <code>JSP</code> , 而在整个 <code>Java Web</code> 技术中都极为重要, 对其常用的实现方法必须使用熟练.</p>
<p><strong>4. <em>Application (ServletContext)</em></strong></p>
<ul>
<li><strong>Attribute</strong> 相关:</li>
</ul>
<p>和 <code>request</code> <code>session</code> 类似, <code>Servlet</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="n">Object</span><span class="w"> </span><span class="nf">getAttribute</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="kt">void</span><span class="w"> </span><span class="nf">setAttribute</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 class="n">Object</span><span class="w"> </span><span class="n">value</span><span class="p">);</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="kt">void</span><span class="w"> </span><span class="nf">removeAttribute</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></code></pre></div><ul>
<li><strong>Paramater</strong> 相关:</li>
</ul>
<p>获取在 <code>web.xml</code> 中设置的 <code>Servlet</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="n">String</span><span class="w"> </span><span class="nf">getInitParameter</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></code></pre></div><ul>
<li><strong>Servlet Context Path</strong></li>
</ul>
<p>为服务器应用的路径名, 如: <code>/day_15</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="n">String</span><span class="w"> </span><span class="nf">getContextPath</span><span class="p">();</span><span class="w">
</span></span></span></code></pre></div><p>仅获取应用名称,  如: <code>day_15</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="n">String</span><span class="w"> </span><span class="nf">getServletContextName</span><span class="p">();</span><span class="w">
</span></span></span></code></pre></div><p><strong>5. <em>Config (ServletConfig)</em></strong></p>
<p><code>ServletContext</code> 可以覆盖其实现的所有功能.</p>
<ul>
<li><strong>Paramater</strong> 相关:</li>
</ul>
<p>获取在 <code>web.xml</code> 中设置的 <code>Servlet</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="n">String</span><span class="w"> </span><span class="nf">getInitParameter</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></code></pre></div><ul>
<li>获取 <strong>ServletContext</strong>:</li>
</ul>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-java" data-lang="java"><span class="line"><span class="cl"><span class="n">ServletContext</span><span class="w"> </span><span class="nf">getServletContext</span><span class="p">();</span><span class="w">
</span></span></span></code></pre></div><ul>
<li>获取应用名称:</li>
</ul>
<p>如: <code>day_15</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="n">String</span><span class="w"> </span><span class="nf">getServletContextName</span><span class="p">();</span><span class="w">
</span></span></span></code></pre></div><p><strong>6. <em>PageContext (PageContext)</em></strong></p>
<ul>
<li>可以获取其他所有隐藏对象 <strong>Request Response Session ServletContext ServletConfig Out Page Exception</strong>:</li>
</ul>
<p>直接调用 <code>get</code> 方法既可. 因为可以调用所有功能, 多用于 <code>EL</code> 表达式.</p>
<p><strong>7. 其余不常用的三个: Out Page Exception</strong>:</p>
<p>以上9个隐藏对象包含 <code>Java Web</code> 最重要的四个作用域:</p>
<ul>
<li><strong>Application</strong>: 作用于整个 Web 应用, 生命周期为 <strong>应用的添加到移除</strong>.</li>
<li><strong>Session</strong>: 作用于一次会话, 生命周期为 <strong>浏览器第一次访问生成到生命周期结束自动注销</strong>.</li>
<li><strong>Request</strong>: 作用于一次请求, 生命周期为 <strong>发送请求到请求处理结束</strong>.</li>
<li><strong>Page</strong>: 仅作用于本页面, 无生命周期.</li>
</ul>
]]></description></item><item><title>深入理解 HTTP Session</title><link>https://blog.terryx.com/posts/2016-02-17-http-session-summary/</link><pubDate>Wed, 28 Sep 2016 00:00:00 +0000</pubDate><guid>https://blog.terryx.com/posts/2016-02-17-http-session-summary/</guid><description><![CDATA[<blockquote>
<p>转载于 <a href="http://lavasoft.blog.51cto.com/62575/275589">深入理解 HTTP Session</a></p>
</blockquote>
<p>Session 在 web 开发中是一个非常重要的概念, 这个概念很抽象,很难定义,也是最让人迷惑的一个名词, 也是最多被滥用的名字之一, 在不同的场合,session一次的含义也很不相同. 这里只探讨 HTTP Session.</p>
<p>为了说明问题,这里基于 Java Servlet 理解 Session 的概念与原理,这里所说 Servlet 已经涵盖了 JSP 技术,因为 JSP 最终也会被编译为 Servlet,两者有着相同的本质.</p>
<p>在 Java 中, HTTP 的 Session 对象用 <code>javax.servlet.http.HttpSession</code> 来表示.</p>
<ol>
<li>概念: Session 代表服务器与浏览器的一次会话过程, 这个过程是连续的, 也可以时断时续的. 在 Servlet 中, session 指的是 HttpSession 类的对象, 这个概念到此结束了, 也许会很模糊, 但只有看完本文,才能真正有个深刻理解.</li>
<li>Session 创建的时间是:</li>
</ol>
<p>一个常见的误解是以为 session 在有客户端访问时就被创建, 然而事实是直到某 server 端程序调用 <code>HttpServletRequest.getSession(true)</code> 这样的语句时才被创建,注意如果JSP没有显示的使用 <code>&lt;% @page session=&quot;false&quot;%&gt;</code> 关闭 session, <strong>则 JSP 文件在编译成 Servlet 时将会自动加上这样一条语句 <code>HttpSession session = HttpServletRequest.getSession(true)</code>; 这也是JSP中隐含的 session对象的来历.</strong></p>
<p>由于 session 会消耗内存资源, 因此, 如果不打算使用 session, 应该在所有的 JSP 中关闭它.</p>
<p>引申:</p>
<ul>
<li>访问 <code>*.html</code> 的静态资源因为不会被编译为 Servlet, 也就不涉及 session 的问题.</li>
<li>当 JSP 页面没有显式禁止 session 的时候, 在打开浏览器第一次请求该 jsp 的时候, 服务器会自动为其创建一个 session, 并赋予其一个 sessionID, 发送给客户端的浏览器. 以后客户端接着请求本应用中其他资源的时候, 会自动在请求头上添加:
<code>Cookie:JSESSIONID</code> = 客户端第一次拿到的 session ID
这样, 服务器端在接到请求时候, 就会收到 session ID, 并根据 ID 在内存中找到之前创建的 session 对象, 提供给请求使用. 这也是 session 使用的基本原理 —- 搞不懂这个, 就永远不明白session的原理.</li>
</ul>
<ol start="3">
<li>Session删除的时间是:</li>
</ol>
<ul>
<li>Session 超时: 超时指的是连续一定时间服务器没有收到该 Session 所对应客户端的请求,并且这个时间超过了服务器设置的 Session 超时的最大时间.</li>
<li>程序调用 <code>HttpSession.invalidate()</code></li>
<li>服务器关闭或服务停止</li>
</ul>
<ol start="4">
<li>session 存放在哪里: 服务器端的内存中. 不过 session 可以通过特殊的方式做持久化管理.</li>
<li>session 的 id 是从哪里来的, sessionID 是如何使用的: 当客户端第一次请求 session 对象时候, 服务器会为客户端创建一个 session, 并将通过特殊算法算出一个 session 的 ID, 用来标识该session对象, 当浏览器下次 (session 继续有效时) 请求别的资源的时候, 浏览器会偷偷地将sessionID放置到请求头中, 服务器接收到请求后就得到该请求的 sessionID, 服务器找到该 id 的 session 返还给请求者 (Servlet) 使用. 一个会话只能有一个 session 对象, <strong>对 session 来说是只认 id 不认人</strong>.</li>
<li>session 会因为浏览器的关闭而删除吗？</li>
</ol>
<p>不会, session 只会通过上面提到的方式去关闭.
7. 同一客户端机器多次请求同一个资源, session 一样吗？</p>
<p>一般来说,每次请求都会新创建一个 session.</p>
<p>其实, 这个也不一定的, 总结下: <strong>对于多标签的浏览器 (比如 Chrome 浏览器) 来说, 在一个浏览器窗口中, 多个标签同时访问一个页面, session是一个. 对于多个浏览器窗口之间, 同时或者相隔很短时间访问一个页面, session是多个的, 和浏览器的进程有关. 对于一个同一个浏览器窗口, 直接录入url访问同一应用的不同资源, session是一样的.</strong>
8. session 是一个容器,可以存放会话过程中的任何对象.
9. session 因为请求 (request对象) 而产生, 同一个会话中多个 request 共享了一个 session 对象, 可以直接从请求中获取到 session 对象.
10. <strong>其实, session 的创建和使用总在服务端, 而浏览器从来都没得到过 session 对象.</strong> 但浏览器可以请求 Servlet (jsp 也是 Servlet) 来获取 session 的信息. 客户端浏览器真正紧紧拿到的是 session ID, 而这个对于浏览器操作的人来说, 是不可见的, 并且用户也无需关心自己处于哪个会话过程中.</p>
]]></description></item><item><title>用 Redis 实现分布式锁 与 实现任务队列</title><link>https://blog.terryx.com/posts/2016-04-27-redis/</link><pubDate>Wed, 28 Sep 2016 00:00:00 +0000</pubDate><guid>https://blog.terryx.com/posts/2016-04-27-redis/</guid><description><![CDATA[<blockquote>
<p>转载于 <a href="http://www.cnblogs.com/it-cen/p/4984272.html">用 Redis 实现分布式锁 与 实现任务队列</a></p>
</blockquote>
<p>这一次总结和分享用Redis实现分布式锁 与 实现任务队列 这两大强大的功能. 先扯点个人观点, 之前我看了一篇博文说博客园的文章大部分都是分享代码, 博文里强调说分享思路比分享代码更重要 (貌似大概是这个意思, 若有误请谅解) , 但我觉得, 分享思路固然重要, 但有了思路, 却没有实现的代码, 那会让人觉得很浮夸的, 在工作中的程序猿都知道, 你去实现一个功能模块, 一段代码, 虽然你有了思路, 但是实现的过程也是很耗时的, 特别是代码调试, 还有各种测试等等. 所以我认为, 思路+代码, 才是一篇好博文的主要核心.</p>
<p>直接进入主题.</p>
<h3 id="一前言">一、前言</h3>
<p>双十一刚过不久, 大家都知道在天猫、京东、苏宁等等电商网站上有很多秒杀活动, 例如在某一个时刻抢购一个原价1999现在秒杀价只要999的手机时, 会迎来一个用户请求的高峰期, 可能会有几十万几百万的并发量, 来抢这个手机, 在高并发的情形下会对数据库服务器或者是文件服务器应用服务器造成巨大的压力, 严重时说不定就宕机了, 另一个问题是, 秒杀的东西都是有量的, 例如一款手机只有10台的量秒杀, 那么, 在高并发的情况下, 成千上万条数据更新数据库 (例如10台的量被人抢一台就会在数据集某些记录下 减1) , 那次这个时候的先后顺序是很乱的, 很容易出现10台的量, 抢到的人就不止10个这种严重的问题. 那么, 以后所说的问题我们该如何去解决呢？ 接下来我所分享的技术就可以拿来处理以上的问题： 分布式锁 和 任务队列.</p>
<h3 id="二实现思路">二、实现思路</h3>
<h4 id="1redis-实现分布式锁思路">1.Redis 实现分布式锁思路</h4>
<p>思路很简单, 主要用到的 <code>redis</code> 函数是 <code>setnx()</code> , 这个应该是实现分布式锁最主要的函数. 首先是将某一任务标识名 (这里用 <code>Lock:order</code> 作为标识名的例子) 作为键存到 <code>redis</code> 里, 并为其设个过期时间, 如果是还有 <code>Lock:order</code> 请求过来, 先是通过 <code>setnx()</code> 看看是否能将 <code>Lock:order</code> 插入到 redis 里, 可以的话就返回 true, 不可以就返回 false. 当然, 在我的代码里会比这个思路复杂一些, 我会在分析代码时进一步说明.</p>
<h4 id="2redis-实现任务队列">2.Redis 实现任务队列</h4>
<p>这里的实现会用到上面的 <code>Redis</code> 分布式的锁机制, 主要是用到了<code>Redis</code> 里的有序集合这一数据结构. 例如入队时, 通过 <code>zset</code> 的 <code>add()</code> 函数进行入队, 而出对时, 可以用到 <code>zset</code> 的 <code>getScore()</code> 函数. 另外还可以弹出顶部的几个任务.</p>
<p>以上就是实现 分布式锁 和 任务队列 的简单思路, 如果你看完有点模棱两可, 那请看接下来的代码实现.</p>
<h3 id="三代码分析">三、代码分析</h3>
<h4 id="一-先来分析redis分布式锁的代码实现">(一) 先来分析Redis分布式锁的代码实现</h4>
<ul>
<li>(1) 为避免特殊原因导致锁无法释放, 在加锁成功后, 锁会被赋予一个生存时间 (通过 <code>lock</code>方法的参数设置或者使用默认值) , 超出生存时间锁会被自动释放锁的生存时间默认比较短 (秒级) , 因此, 若需要长时间加锁, 可以通过 <code>expire</code> 方法延长锁的生存时间为适当时间, 比如在循环内.</li>
<li>(2) 系统级的锁当进程无论何种原因时出现 crash 时, 操作系统会自己回收锁, 所以不会出现资源丢失, 但分布式锁不用, 若一次性设置很长时间, 一旦由于各种原因出现进程crash 或者其他异常导致unlock未被调用时, 则该锁在剩下的时间就会变成垃圾锁, 导致其他进程或者进程重启后无法进入加锁区域.</li>
</ul>
<p>先看加锁的实现代码：这里需要主要两个参数, 一个是 <code>$timeout</code>,这个是循环获取锁的等待时间, 在这个时间内会一直尝试获取锁知道超时, 如果为 0, 则表示获取锁失败后直接返回而不再等待；另一个重要参数的 <code>$expire</code>, 这个参数指当前锁的最大生存时间, 以秒为单位的, 它必须大于0, 如果超过生存时间锁仍未被释放, 则系统会自动强制释放. 这个参数的最要作用请看上面的 (1) 里的解释.</p>
<p>这里先取得当前时间, 然后再获取到锁失败时的等待超时的时刻 (是个时间戳), 再获取到锁的最大生存时刻是多少. 这里 redis 的 key 用这种格式：<code>Lock: 锁的标识名</code>, 这里就开始进入循环了, 先是插入数据到redis里, 使用 <code>setnx()</code> 函数, 这函数的意思是, 如果该键不存在则插入数据, 将最大生存时刻作为值存储, 假如插入成功, 则对该键进行失效时间的设置, 并将该键放在 <code>$lockedName</code> 数组里, 返回 true, 也就是上锁成功；如果该键存在, 则不会插入操作了, 这里有一步严谨的操作, 那就是取得当前键的剩余时间, 假如这个时间小于 0, 表示 key 上没有设置生存时间 (key是不会不存在的, 因为前面setnx会自动创建) 如果出现这种状况, 那就是进程的某个实例 setnx 成功后 crash 导致紧跟着的 expire 没有被调用, 这时可以直接设置expire并把锁纳为己用. 如果没设置锁失败的等待时间或者已超过最大等待时间了, 那就退出循环, 反之则隔 <code>$waitIntervalUs</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">     * 加锁
</span></span></span><span class="line"><span class="cl"><span class="cm">     * @param  [type]  $name           锁的标识名
</span></span></span><span class="line"><span class="cl"><span class="cm">     * @param  integer $timeout        循环获取锁的等待超时时间，在此时间内会一直尝试获取锁直到超时，为 0表示失败后直接返回不等待
</span></span></span><span class="line"><span class="cl"><span class="cm">     * @param  integer $expire         当前锁的最大生存时间(秒)，必须大于 0，如果超过生存时间锁仍未被释放，则系统会自动强制释放
</span></span></span><span class="line"><span class="cl"><span class="cm">     * @param  integer $waitIntervalUs 获取锁失败后挂起再试的时间间隔(微秒)
</span></span></span><span class="line"><span class="cl"><span class="cm">     * @return [type]                  [description]
</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="kd">public</span><span class="w"> </span><span class="n">function</span><span class="w"> </span><span class="nf">lock</span><span class="p">(</span><span class="n">$name</span><span class="p">,</span><span class="w"> </span><span class="n">$timeout</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">0</span><span class="p">,</span><span class="w"> </span><span class="n">$expire</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">15</span><span class="p">,</span><span class="w"> </span><span class="n">$waitIntervalUs</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">100000</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="k">if</span><span class="w"> </span><span class="p">(</span><span class="n">$name</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="kc">null</span><span class="p">)</span><span class="w"> </span><span class="k">return</span><span class="w"> </span><span class="kc">false</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">//取得当前时间</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="n">$now</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">time</span><span class="p">();</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="c1">//获取锁失败时的等待超时时刻</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="n">$timeoutAt</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">$now</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="n">$timeout</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="c1">//锁的最大生存时刻</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="n">$expireAt</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">$now</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="n">$expire</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="n">$redisKey</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="s">&#34;Lock:{$name}&#34;</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="k">while</span><span class="w"> </span><span class="p">(</span><span class="kc">true</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">//将rediskey的最大生存时刻存到redis里，过了这个时刻该锁会被自动释放</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="n">$result</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">$this</span><span class="o">-&gt;</span><span class="n">redisString</span><span class="o">-&gt;</span><span class="n">setnx</span><span class="p">(</span><span class="n">$redisKey</span><span class="p">,</span><span class="w"> </span><span class="n">$expireAt</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="k">if</span><span class="w"> </span><span class="p">(</span><span class="n">$result</span><span class="w"> </span><span class="o">!=</span><span class="w"> </span><span class="kc">false</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">//设置key的失效时间</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">                </span><span class="n">$this</span><span class="o">-&gt;</span><span class="n">redisString</span><span class="o">-&gt;</span><span class="n">expire</span><span class="p">(</span><span class="n">$redisKey</span><span class="p">,</span><span class="w"> </span><span class="n">$expireAt</span><span class="p">);</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">                </span><span class="c1">//将锁标志放到lockedNames数组里</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">                </span><span class="n">$this</span><span class="o">-&gt;</span><span class="n">lockedNames</span><span class="o">[</span><span class="n">$name</span><span class="o">]</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">$expireAt</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">                </span><span class="k">return</span><span class="w"> </span><span class="kc">true</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="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="c1">//以秒为单位，返回给定key的剩余生存时间</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="n">$ttl</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">$this</span><span class="o">-&gt;</span><span class="n">redisString</span><span class="o">-&gt;</span><span class="n">ttl</span><span class="p">(</span><span class="n">$redisKey</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">//ttl小于0 表示key上没有设置生存时间（key是不会不存在的，因为前面setnx会自动创建）</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="c1">//如果出现这种状况，那就是进程的某个实例setnx成功后 crash 导致紧跟着的expire没有被调用</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="c1">//这时可以直接设置expire并把锁纳为己用</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">$ttl</span><span class="w"> </span><span class="o">&lt;</span><span class="w"> </span><span class="n">0</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">$this</span><span class="o">-&gt;</span><span class="n">redisString</span><span class="o">-&gt;</span><span class="n">set</span><span class="p">(</span><span class="n">$redisKey</span><span class="p">,</span><span class="w"> </span><span class="n">$expireAt</span><span class="p">);</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">                </span><span class="n">$this</span><span class="o">-&gt;</span><span class="n">lockedNames</span><span class="o">[</span><span class="n">$name</span><span class="o">]</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">$expireAt</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">                </span><span class="k">return</span><span class="w"> </span><span class="kc">true</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="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="cm">/*****循环请求锁部分*****/</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="c1">//如果没设置锁失败的等待时间 或者 已超过最大等待时间了，那就退出</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">$timeout</span><span class="w"> </span><span class="o">&lt;=</span><span class="w"> </span><span class="n">0</span><span class="w"> </span><span class="o">||</span><span class="w"> </span><span class="n">$timeoutAt</span><span class="w"> </span><span class="o">&lt;</span><span class="w"> </span><span class="n">microtime</span><span class="p">(</span><span class="kc">true</span><span class="p">))</span><span class="w"> </span><span class="k">break</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">//隔 $waitIntervalUs 后继续 请求</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="n">usleep</span><span class="p">(</span><span class="n">$waitIntervalUs</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="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="k">return</span><span class="w"> </span><span class="kc">false</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></code></pre></div>]]></description></item></channel></rss>