欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

使用Spring自定義命名空間

 更新時(shí)間:2021年09月26日 11:19:56   作者:liuhmmjj  
這篇文章主要介紹了使用Spring自定義命名空間方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教

Spring在解析xml文件中的標(biāo)簽的時(shí)候會(huì)區(qū)分當(dāng)前的標(biāo)簽是四種基本標(biāo)簽(import、alias、bean和beans)還是自定義標(biāo)簽,如果是自定義標(biāo)簽,則會(huì)按照自定義標(biāo)簽的邏輯解析當(dāng)前的標(biāo)簽。另外,即使是bean標(biāo)簽,其也可以使用自定義的屬性或者使用自定義的子標(biāo)簽。本文將對(duì)自定義標(biāo)簽和自定義屬性的使用方式進(jìn)行講解,并且會(huì)從源碼的角度對(duì)自定義標(biāo)簽和自定義屬性的實(shí)現(xiàn)方式進(jìn)行講解。

Spring框架從2.0版本開(kāi)始,提供了基于Schema風(fēng)格的Spring XML格式用來(lái)定義bean的擴(kuò)展機(jī)制。引入Schema-based XML是為了對(duì)Traditional的XML配置形式進(jìn)行簡(jiǎn)化。通過(guò)Schema的定義,把一些原本需要通過(guò)幾個(gè)bean的定義或者復(fù)雜的bean的組合定義的配置形式,用另外一種簡(jiǎn)單而可讀的配置形式呈現(xiàn)出來(lái)。

Schema-based XML由三部分構(gòu)成,我們由一幅圖說(shuō)明:

這里寫(xiě)圖片描述

  • namespace —— 擁有很明確的邏輯分類
  • element —— 擁有很明確的過(guò)程語(yǔ)義
  • attributes —— 擁有很簡(jiǎn)明的配置選項(xiàng)

例如,<mvc:annotation-driven />這段配置想要表達(dá)的意思,就是在mvc的空間內(nèi)實(shí)現(xiàn)Annotation驅(qū)動(dòng)的配置方式。其中,mvc表示配置的有效范圍,annotation-driven則表達(dá)了一個(gè)動(dòng)態(tài)的過(guò)程,實(shí)際的邏輯含義是:整個(gè)SpringMVC的實(shí)現(xiàn)是基于Annotation模式,請(qǐng)為我注冊(cè)相關(guān)的行為模式。

下面將闡述一下怎么寫(xiě)自定義XML的bean definition解析和集成這個(gè)解析到Spring IOC容器中。在后面的內(nèi)容中我們將會(huì)提到一個(gè)重要的概念那就是bean definition.其實(shí)Spring中有一個(gè)重要的概念那就是bean.而B(niǎo)eanDefinition這個(gè)對(duì)象就是對(duì)應(yīng)的標(biāo)簽解析后的對(duì)象。

利用下面幾個(gè)簡(jiǎn)答的步驟可以創(chuàng)建新的xml配置擴(kuò)展:

  • Authoring一個(gè)XML schema用來(lái)描述你的自定義element(s)
  • Coding一個(gè)自定義的NamespaceHandler實(shí)現(xiàn)(這是一個(gè)很簡(jiǎn)答的步驟,don't worry)
  • Coding一個(gè)或者多個(gè)BeanDefinitionParse實(shí)現(xiàn)(這是最主要的)
  • Registeringr把注冊(cè)上面的到Spring(這也是一個(gè)簡(jiǎn)答的步驟)

下面將會(huì)依次闡述上面的步驟。例如:我們需要?jiǎng)?chuàng)建一個(gè)XML擴(kuò)展(自定義xml element)允許我們可以用一種簡(jiǎn)單的方式來(lái)配置SimpleDateFormat對(duì)象(在java.text包中)。最后我們可以定義一個(gè)SimpleDateFormat類型的bean definition如下:

<myns:dateformat id="dateFormat"
    pattern="yyyy-MM-dd HH:mm"
    lenient="true"/>

1、Authoring the schema

創(chuàng)建一個(gè)Spring IOC容器的XML配置擴(kuò)展,我們需要編寫(xiě)一個(gè)XML Schema用來(lái)描述這個(gè)擴(kuò)展。下面的schema我們可以用來(lái)配置SimpleDateFormat對(duì)象

<!-- myns.xsd (inside package org/springframework/samples/xml) --> 
<?xml version="1.0" encoding="UTF-8"?>
<xsd:schema xmlns="http://www.mycompany.com/schema/myns"
        xmlns:xsd="http://www.w3.org/2001/XMLSchema"
        xmlns:beans="http://www.springframework.org/schema/beans"
        targetNamespace="http://www.mycompany.com/schema/myns"
        elementFormDefault="qualified"
        attributeFormDefault="unqualified">
 
    <xsd:import namespace="http://www.springframework.org/schema/beans"/> 
    <xsd:element name="dateformat">
        <xsd:complexType>
            <xsd:complexContent>
                <xsd:extension base="beans:identifiedType">
                    <xsd:attribute name="lenient" type="xsd:boolean"/>
                    <xsd:attribute name="pattern" type="xsd:string" use="required"/>
                </xsd:extension>
            </xsd:complexContent>
        </xsd:complexType>
    </xsd:element>
</xsd:schema>

上面的schema將會(huì)用來(lái)配置SimpleDateFormat對(duì)象。直接在一個(gè)xml應(yīng)用context文件使用<myns:dateformat /> element.

<myns:dateformat id="dateFormat"
    pattern="yyyy-MM-dd HH:mm"
    lenient="true"/>

注意:上面的XML片段本質(zhì)上和下面的XML片段意義一樣。

<bean id="dateFormat" class="java.text.SimpleDateFormat">
    <constructor-arg value="yyyy-HH-dd HH:mm"/>
    <property name="lenient" value="true"/>
</bean>

2、Coding a NamespaceHandler

針對(duì)于上面的的schema,我們需要一個(gè)NamespaceHandler用來(lái)解析Spring遇到的所有這個(gè)特定的namespace配置文件中的所有elements.這個(gè)NamespaceHandler將會(huì)關(guān)心解析myns:dateformat元素。

這個(gè)NamespaceHandler接口相對(duì)簡(jiǎn)單,它包括三個(gè)重要的方法。

  • init().會(huì)在spring使用handler之前實(shí)例化NamespaceHandler
  • BeanDefinition parse(Element, ParseContext) - 當(dāng)Spring遇到上面定義的top-level元素(也就是myms)將會(huì)被調(diào)用,這個(gè)方法能夠注冊(cè)bean definitions并且可以返回一個(gè)bean definition.
  • BeanDefinitionHolder decorate(Node, BeanDefinitionHolder, ParserContext),當(dāng)spring遇到一個(gè)attribute或者嵌入到namespace中的元素中將會(huì)被調(diào)用。

在很多情況下在spring xml配置文件中每個(gè)top-level的xml元素代表一個(gè)single類型的bean definition(在我們的例子中,是一個(gè)single的<myns:dateformat>元素代表一個(gè)single的SimpleDateFormat bean definition).Spring提供了很多便利的類用來(lái)支持這種場(chǎng)景。在這個(gè)例子中,我們將使用NamespaceHandlerSupport。

package org.springframework.samples.xml; 
import org.springframework.beans.factory.xml.NamespaceHandlerSupport; 
public class MyNamespaceHandler extends NamespaceHandlerSupport { 
    public void init() {
        registerBeanDefinitionParser("dateformat", new SimpleDateFormatBeanDefinitionParser());
    } 
}

下面講一下為什么要繼承NamespaceHandlerSupport這個(gè)抽象類

先看一下Spring自定義命名空間加載過(guò)程:

XmlBeanDefinitionReader入口

DefaultDocumentLoader加載并解析一個(gè)XML文件成Document實(shí)例,從BeanDefinitionReader中獲取EntityResolver和ErrorHandler。

在XmlBeanDefinitionReader中創(chuàng)建BeanDefinitionDocumentReader,在這個(gè)BeanDefinitionDocumentReader中遍歷Document中的每個(gè)Element。

對(duì)每個(gè)Element,如果是默認(rèn)的URI(即beans命名空間內(nèi)的定義),調(diào)用parseDefaultElement()方法,否則調(diào)用BeanDefinitionParserDelegate中的parseCustomElement()方法。

在parseCustomElement()方法中,它找到當(dāng)前Element的namespaceURI,然后從NamespaceHandlerResolver中獲取自定義的NamespaceHandler,使用該NamespaceHandler來(lái)解析這個(gè)Element,由于我們已經(jīng)在init()方法中注冊(cè)了不同的element name對(duì)應(yīng)的BeanDefinitionParser,因而可以使用這個(gè)自定義的BeanDefinitionParser來(lái)解析自定義的Element。

其中默認(rèn)的NamespaceHandlerResolver(DefaultNamespaceHandlerResolver)會(huì)找到當(dāng)前classpath下的所有META-INF/spring.handlers文件,加載進(jìn)來(lái),讀取里面的內(nèi)容成namespaceURI到NamespaceHandler的map,并初始化所有的NamespaceHandler。

看一下BeanDefinitionParserDelegate中的parseCustomElement()方法:

public BeanDefinition parseCustomElement(Element ele) {
        return this.parseCustomElement(ele, (BeanDefinition)null);
}
 
public BeanDefinition parseCustomElement(Element ele, BeanDefinition containingBd){
        String namespaceUri = this.getNamespaceURI(ele);
        NamespaceHandler handler = this.readerContext.getNamespaceHandlerResolver().resolve(namespaceUri);
        if (handler == null) {
            this.error("Unable to locate Spring NamespaceHandler for XML schema namespace [" + namespaceUri + "]", ele);
            return null;
        } else {
            return handler.parse(ele, new ParserContext(this.readerContext, this, containingBd));
        }
}

其中parse方法為抽象類NamespaceHandlerSupport中的方法:

public BeanDefinition parse(Element element, ParserContext parserContext) {
        return this.findParserForElement(element, parserContext).parse(element, parserContext);
}
 
private BeanDefinitionParser findParserForElement(Element element, ParserContext parserContext) {
        String localName = parserContext.getDelegate().getLocalName(element);
        BeanDefinitionParser parser = (BeanDefinitionParser)this.parsers.get(localName);
        if (parser == null) {
            parserContext.getReaderContext().fatal("Cannot locate BeanDefinitionParser for element [" + localName + "]", element);
        } 
        return parser;
}

而其中的

BeanDefinitionParser parser = (BeanDefinitionParser)this.parsers.get(localName);這句中的parsers是一個(gè)HashMap 在繼承NamespaceHandlerSupport這個(gè)抽象類中的重寫(xiě)了init()方法:

public void init() {
        registerBeanDefinitionParser("dateformat", new SimpleDateFormatBeanDefinitionParser());
    }

NamespaceHandlerSupport這個(gè)類的registerBeanDefinitionParser方法:

private final Map<String, BeanDefinitionParser> parsers = new HashMap(); 
protected final void registerBeanDefinitionParser(String elementName, BeanDefinitionParser parser) {
        this.parsers.put(elementName, parser);
    }

return this.findParserForElement(element, parserContext).parse(element, parserContext);中的parse方法為抽象類AbstractBeanDefinitionParser中的方法:

public final BeanDefinition parse(Element element, ParserContext parserContext) {
        AbstractBeanDefinition definition = this.parseInternal(element, parserContext);
        if (definition != null && !parserContext.isNested()) {
            try {
                String id = this.resolveId(element, definition, parserContext);
                if (!StringUtils.hasText(id)) {
                    parserContext.getReaderContext().error("Id is required for element '" + parserContext.getDelegate().getLocalName(element) + "' when used as a top-level tag", element);
                }
 
                String[] aliases = null;
                if (this.shouldParseNameAsAliases()) {
                    String name = element.getAttribute("name");
                    if (StringUtils.hasLength(name)) {
                        aliases = StringUtils.trimArrayElements(StringUtils.commaDelimitedListToStringArray(name));
                    }
                }
 
                BeanDefinitionHolder holder = new BeanDefinitionHolder(definition, id, aliases);
                this.registerBeanDefinition(holder, parserContext.getRegistry());
                if (this.shouldFireEvents()) {
                    BeanComponentDefinition componentDefinition = new BeanComponentDefinition(holder);
                    this.postProcessComponentDefinition(componentDefinition);
                    parserContext.registerComponent(componentDefinition);
                }
            } catch (BeanDefinitionStoreException var8) {
                parserContext.getReaderContext().error(var8.getMessage(), element);
                return null;
            }
        } 
        return definition;
    }

this.registerBeanDefinition(holder, parserContext.getRegistry());最終會(huì)調(diào)用BeanDefinitionReaderUtils的registerBeanDefinition方法向IoC容器注冊(cè)解析的Bean,BeanDefinitionReaderUtils的注冊(cè)的源碼如下:

//將解析的BeanDefinitionHold注冊(cè)到容器中 
public static void registerBeanDefinition(BeanDefinitionHolder definitionHolder, BeanDefinitionRegistry registry)  
    throws BeanDefinitionStoreException {  
        //獲取解析的BeanDefinition的名稱
         String beanName = definitionHolder.getBeanName();  
        //向IoC容器注冊(cè)BeanDefinition 
        registry.registerBeanDefinition(beanName, definitionHolder.getBeanDefinition());  
        //如果解析的BeanDefinition有別名,向容器為其注冊(cè)別名  
         String[] aliases = definitionHolder.getAliases();  
        if (aliases != null) {  
            for (String aliase : aliases) {  
                registry.registerAlias(beanName, aliase);  
            }  
        }  
}

當(dāng)調(diào)用BeanDefinitionReaderUtils向IoC容器注冊(cè)解析的BeanDefinition時(shí),真正完成注冊(cè)功能的是DefaultListableBeanFactory。

DefaultListableBeanFactory向IoC容器注冊(cè)解析后的BeanDefinition:

DefaultListableBeanFactory中使用一個(gè)HashMap的集合對(duì)象存放IoC容器中注冊(cè)解析的BeanDefinition,向IoC容器注冊(cè)的主要源碼如下:

//存儲(chǔ)注冊(cè)的俄BeanDefinition  
private final Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<String, BeanDefinition>();  
   //向IoC容器注冊(cè)解析的BeanDefiniton  
public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition)  
         throws BeanDefinitionStoreException {  
     Assert.hasText(beanName, "Bean name must not be empty");  
     Assert.notNull(beanDefinition, "BeanDefinition must not be null");  
     //校驗(yàn)解析的BeanDefiniton  
      if (beanDefinition instanceof AbstractBeanDefinition) {  
           try {  
               ((AbstractBeanDefinition) beanDefinition).validate();  
          }  
          catch (BeanDefinitionValidationException ex) {  
              throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName,  
                      "Validation of bean definition failed", ex);  
          }  
      }  
      //注冊(cè)的過(guò)程中需要線程同步,以保證數(shù)據(jù)的一致性  
      synchronized (this.beanDefinitionMap) {  
          Object oldBeanDefinition = this.beanDefinitionMap.get(beanName);  
          //檢查是否有同名的BeanDefinition已經(jīng)在IoC容器中注冊(cè),如果已經(jīng)注冊(cè),  
          //并且不允許覆蓋已注冊(cè)的Bean,則拋出注冊(cè)失敗異常  
          if (oldBeanDefinition != null) {  
              if (!this.allowBeanDefinitionOverriding) {  
                  throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName,  
                           "Cannot register bean definition [" + beanDefinition + "] for bean '" + beanName +  
                          "': There is already [" + oldBeanDefinition + "] bound.");  
              }  
              else {//如果允許覆蓋,則同名的Bean,后注冊(cè)的覆蓋先注冊(cè)的  
                  if (this.logger.isInfoEnabled()) {  
                      this.logger.info("Overriding bean definition for bean '" + beanName +  
                              "': replacing [" + oldBeanDefinition + "] with [" + beanDefinition + "]");  
                  }  
              }  
          }  
          //IoC容器中沒(méi)有已經(jīng)注冊(cè)同名的Bean,按正常注冊(cè)流程注冊(cè)  
          else {  
              this.beanDefinitionNames.add(beanName);  
              this.frozenBeanDefinitionNames = null;  
          }  
          this.beanDefinitionMap.put(beanName, beanDefinition);  
          //重置所有已經(jīng)注冊(cè)過(guò)的BeanDefinition的緩存  
          resetBeanDefinition(beanName);  
      }  
} 

3、BeanDefinitionParser

BeanDefinitionParser的責(zé)任是解析定義schema在top-level的XML元素.在解析過(guò)程中,我們必須訪問(wèn)XML元素,因此我們可以解析我們自定義的XML內(nèi)容,例如下面的例子:

package org.springframework.samples.xml; 
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.xml.AbstractSingleBeanDefinitionParser;
import org.springframework.util.StringUtils;
import org.w3c.dom.Element; 
import java.text.SimpleDateFormat;
 
public class SimpleDateFormatBeanDefinitionParser extends AbstractSingleBeanDefinitionParser { 1 
    protected Class getBeanClass(Element element) {
        return SimpleDateFormat.class; 2
    }
 
    protected void doParse(Element element, BeanDefinitionBuilder bean) {
        // this will never be null since the schema explicitly requires that a value be supplied
        String pattern = element.getAttribute("pattern");
        bean.addConstructorArg(pattern);
 
        // this however is an optional property
        String lenient = element.getAttribute("lenient");
        if (StringUtils.hasText(lenient)) {
            bean.addPropertyValue("lenient", Boolean.valueOf(lenient));
        }
    } 
}

注意:

  • 我們使用Spring提供的AbstractSingleBeanDefinitionParser 來(lái)處理創(chuàng)建一個(gè)single的BeanDefinition的一些基本的工作。
  • 我們重寫(xiě)了AbstractSingleBeanDefinitionParser父類的doParse方法來(lái)實(shí)現(xiàn)我們自己創(chuàng)建single類型的BeanDefinition的邏輯。

4、Registering the handler and the schema

編碼工作完成了.下面是事情就是在Spring XML解析的邏輯能夠織入我們定義的element;我們需要在兩個(gè)特定的目標(biāo)properties文件中注冊(cè)我們自定義的namespaceHandler和自定義的XSD文件。這些properties文件都需要被放置在你項(xiàng)目中的'META-INF'應(yīng)用下。

1) META-INF/spring.handlers

這個(gè)properties文件叫做'spring.handlers',包含XML Schema URIS與namespace處理類的映射。在我們的例子中,我們需要像下面:

http\://www.mycompany.com/schema/myns=org.springframework.samples.xml.MyNamespaceHandler

鍵值對(duì)的第一個(gè)部分(key)是關(guān)聯(lián)你自定義namespace擴(kuò)展的URI,并且需要匹配你自定義XSD Schema中的'targetNamespace'屬性。

NamespaceHandlerResolver(DefaultNamespaceHandlerResolver)會(huì)找到當(dāng)前classpath下的所有META-INF/spring.handlers文件,加載進(jìn)來(lái),讀取里面的內(nèi)容成namespaceURI到NamespaceHandler的map,并初始化所有的NamespaceHandler。

DefaultNamespaceHandlerResolver的resolve方法:

    public NamespaceHandler resolve(String namespaceUri) {
        Map<String, Object> handlerMappings = this.getHandlerMappings();
        Object handlerOrClassName = handlerMappings.get(namespaceUri);
        if (handlerOrClassName == null) {
            return null;
        } else if (handlerOrClassName instanceof NamespaceHandler) {
            return (NamespaceHandler)handlerOrClassName;
        } else {
            String className = (String)handlerOrClassName;
 
            try {
                Class<?> handlerClass = ClassUtils.forName(className, this.classLoader);
                if (!NamespaceHandler.class.isAssignableFrom(handlerClass)) {
                    throw new FatalBeanException("Class [" + className + "] for namespace [" + namespaceUri + "] does not implement the [" + NamespaceHandler.class.getName() + "] interface");
                } else {
                    NamespaceHandler namespaceHandler = (NamespaceHandler)BeanUtils.instantiateClass(handlerClass);
                    namespaceHandler.init();
                    handlerMappings.put(namespaceUri, namespaceHandler);
                    return namespaceHandler;
                }
            } catch (ClassNotFoundException var7) {
                throw new FatalBeanException("NamespaceHandler class [" + className + "] for namespace [" + namespaceUri + "] not found", var7);
            } catch (LinkageError var8) {
                throw new FatalBeanException("Invalid NamespaceHandler class [" + className + "] for namespace [" + namespaceUri + "]: problem with handler class file or dependent class", var8);
            }
        }
    }
 
    private Map<String, Object> getHandlerMappings() {
        if (this.handlerMappings == null) {
            synchronized(this) {
                if (this.handlerMappings == null) {
                    try {
                        Properties mappings = PropertiesLoaderUtils.loadAllProperties(this.handlerMappingsLocation, this.classLoader);
                        if (this.logger.isDebugEnabled()) {
                            this.logger.debug("Loaded NamespaceHandler mappings: " + mappings);
                        }
 
                        Map<String, Object> handlerMappings = new ConcurrentHashMap(mappings.size());
                        CollectionUtils.mergePropertiesIntoMap(mappings, handlerMappings);
                        this.handlerMappings = handlerMappings;
                    } catch (IOException var5) {
                        throw new IllegalStateException("Unable to load NamespaceHandler mappings from location [" + this.handlerMappingsLocation + "]", var5);
                    }
                }
            }
        } 
        return this.handlerMappings;
    }

PropertiesLoaderUtils中的loadAllProperties方法:

public static Properties loadAllProperties(String resourceName, ClassLoader classLoader) throws IOException {
        Assert.notNull(resourceName, "Resource name must not be null");
        ClassLoader classLoaderToUse = classLoader;
        if (classLoader == null) {
            classLoaderToUse = ClassUtils.getDefaultClassLoader();
        }
 
        Enumeration<URL> urls = classLoaderToUse != null ? classLoaderToUse.getResources(resourceName) : ClassLoader.getSystemResources(resourceName);
        Properties props = new Properties();
 
        while(urls.hasMoreElements()) {
            URL url = (URL)urls.nextElement();
            URLConnection con = url.openConnection();
            ResourceUtils.useCachesIfNecessary(con);
            InputStream is = con.getInputStream();
 
            try {
                if (resourceName.endsWith(".xml")) {
                    props.loadFromXML(is);
                } else {
                    props.load(is);
                }
            } finally {
                is.close();
            }
        } 
        return props;
    }

2) META-INF/spring.schemas

這個(gè)properties文件叫做'spring.schemas',包含XML Schema在classpath中的位置。這個(gè)文件主要是防止spring在網(wǎng)絡(luò)上加載這個(gè)schema文件。如果你指定這個(gè)properties文件影射,Spring將會(huì)在classpath中查找這個(gè)schema(在這種情況下會(huì)在'org.springframework.samples.xml'包下面的'myns.xsd')

http\://www.mycompany.com/schema/myns/myns.xsd=org/springframework/samples/xml/myns.xsd

你最好部署你的XSD文件在你的NamespaceHandler和BeanDefinition類的classpath中。

5、最終效果演示

如果你已經(jīng)完成了以上步驟,那么你就成功的定義了你自己的BeanDefinition在Spring IOC容器中。我們可以Spring IOC容器獲取到并使用這個(gè)Bean對(duì)象。

1)配置文件

schema-beans.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:myns="http://www.mycompany.com/schema/myns"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
       http://www.springframework.org/schema/beans/spring-beans.xsd
       http://www.mycompany.com/schema/myns http://www.mycompany.com/schema/myns/myns.xsd">
 
    <myns:dateformat id="dateFormat"
                     pattern="yyyy-MM-dd HH:mm"
                     lenient="true"/> 
</beans>

2)測(cè)試類

SchemaBeanDefinitionTest.java

package org.springframework.samples.xml; 
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext; 
import java.text.SimpleDateFormat;
 
public class SchemaBeanDefinitionTest { 
    public static void main(String[] args) {
        ApplicationContext context = new ClassPathXmlApplicationContext("schema-beans.xml");
        SimpleDateFormat dateFormat = context.getBean("dateFormat", SimpleDateFormat.class);
                System.out.println("-------------------gain object--------------------");
        System.out.println(dateFormat);
    } 
}

3)項(xiàng)目結(jié)構(gòu):

這里寫(xiě)圖片描述

注意:在idea靜態(tài)資源必須放在resources下面,不然會(huì)報(bào)錯(cuò)。

4)運(yùn)行結(jié)果

這里寫(xiě)圖片描述

以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。

相關(guān)文章

  • Java正則表達(dá)式Pattern和Matcher原理詳解

    Java正則表達(dá)式Pattern和Matcher原理詳解

    這篇文章主要介紹了Java正則表達(dá)式Pattern和Matcher原理詳解,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2020-02-02
  • Java模擬實(shí)現(xiàn)QQ三方登錄(單點(diǎn)登錄2.0)

    Java模擬實(shí)現(xiàn)QQ三方登錄(單點(diǎn)登錄2.0)

    這篇文章主要為大家詳細(xì)介紹了Java模擬實(shí)現(xiàn)QQ三方登錄,單點(diǎn)登錄2.0,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2020-06-06
  • mybatis時(shí)間范圍查詢代碼示例

    mybatis時(shí)間范圍查詢代碼示例

    這篇文章主要給大家介紹了關(guān)于mybatis時(shí)間范圍查詢的相關(guān)資料,在項(xiàng)?中避免不了要?到時(shí)間范圍查詢,文中通過(guò)代碼示例介紹的非常詳細(xì),需要的朋友可以參考下
    2023-08-08
  • SpringBoot基于Disruptor實(shí)現(xiàn)高效的消息隊(duì)列?

    SpringBoot基于Disruptor實(shí)現(xiàn)高效的消息隊(duì)列?

    Disruptor是一個(gè)開(kāi)源的Java框架,它被設(shè)計(jì)用于在生產(chǎn)者-消費(fèi)者問(wèn)題上獲得盡量高的吞吐量和盡量低的延遲,本文主要介紹了SpringBoot基于Disruptor實(shí)現(xiàn)高效的消息隊(duì)列?,具有一定的參考價(jià)值,感興趣的可以了解一下
    2024-02-02
  • JPA框架實(shí)現(xiàn)分頁(yè)查詢和條件查詢功能詳解

    JPA框架實(shí)現(xiàn)分頁(yè)查詢和條件查詢功能詳解

    這篇文章主要介紹了JPA框架實(shí)現(xiàn)分頁(yè)查詢和條件查詢功能,JPA是Java Persistence API的簡(jiǎn)稱,在過(guò)去很多數(shù)據(jù)庫(kù)的增刪查改操作都是用這個(gè)框架操作的,感興趣想要詳細(xì)了解可以參考下文
    2023-05-05
  • Elasticsearch Join字段類型簡(jiǎn)單快速上手教程

    Elasticsearch Join字段類型簡(jiǎn)單快速上手教程

    這篇文章主要為大家介紹了Elasticsearch Join字段類型簡(jiǎn)單快速上手教程詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-09-09
  • Go反射底層原理及數(shù)據(jù)結(jié)構(gòu)解析

    Go反射底層原理及數(shù)據(jù)結(jié)構(gòu)解析

    這篇文章主要介紹了Go反射底層原理及數(shù)據(jù)結(jié)構(gòu)解析,反射的實(shí)現(xiàn)和interface的組成很相似,都是由“類型”和“數(shù)據(jù)值”構(gòu)成,下面小編分享更多相關(guān)內(nèi)容需要的小伙伴可以參考一下
    2022-06-06
  • java中BigDecimal用法詳解

    java中BigDecimal用法詳解

    本文詳細(xì)講解了java中BigDecimal的用法,文中通過(guò)示例代碼介紹的非常詳細(xì)。對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2021-12-12
  • Spring如何使用@Indexed加快啟動(dòng)速度

    Spring如何使用@Indexed加快啟動(dòng)速度

    這篇文章主要介紹了Spring如何使用@Indexed加快啟動(dòng)速度,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2021-11-11
  • 圖解Java經(jīng)典算法插入排序的原理與實(shí)現(xiàn)

    圖解Java經(jīng)典算法插入排序的原理與實(shí)現(xiàn)

    插入排序的算法描述是一種簡(jiǎn)單直觀的排序算法。其原理是通過(guò)構(gòu)建有序序列,對(duì)于未排序數(shù)據(jù),在已排序序列中從后向前掃描,找到相應(yīng)位置并插入。本文將用Java語(yǔ)言實(shí)現(xiàn)插入排序算法并進(jìn)行可視化,感興趣的可以了解一下
    2022-09-09

最新評(píng)論