Spring(二)之配置

本文涉及的产品
云数据库 RDS MySQL,集群系列 2核4GB
推荐场景:
搭建个人博客
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
云数据库 RDS MySQL,高可用系列 2核4GB
简介: 依赖配置详解直接变量基本类型Strings类型等idref元素引用其它的bean协作者内部bean集合重点注入值基本集合集合的合并XML配置文件的简写及其他基于XML配置元数据使用p名称空间配置属性depends-on依赖配置详解   bean的属性及构造器参数既可以引用容器中的其他bean,也可以是内联(inline)bean。

依赖配置详解

   bean的属性及构造器参数既可以引用容器中的其他bean,也可以是内联(inline)bean。在spring的XML配置中使用和元素定义。

直接变量(基本类型、Strings类型等。)

  <value/>元素通过人可以理解的字符串来指定属性或构造器参数的值。正如前面所提到的,JavaBean PropertyEditor将用于把字符串从java.lang.String类型转化为实际的属性或参数类型。

<bean id="myDataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">

  <property name="driverClassName">
    <value>com.mysql.jdbc.Driver</value>
  </property>
  <property name="url">
    <value>jdbc:mysql://localhost:3306/mydb</value>
  </property>
  <property name="username">
    <value>root</value>
  </property>
  <property name="password">
    <value>masterkaoli</value>
  </property>
</bean>

  <property/> 和<constructor-arg/> 元素中也可以使用’value’ 属性,这样会使我们的配置更简洁,比如下面的配置

<bean id="myDataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">

  <!-- results in a setDriverClassName(String) call -->
  <property name="driverClassName" value="com.mysql.jdbc.Driver"/>
  <property name="url" value="jdbc:mysql://localhost:3306/mydb"/>
  <property name="username" value="root"/>
  <property name="password" value="masterkaoli"/>
</bean>

   Spring团队更倾向采用属性方式(使用元素)来定义value值。当然我们也可以按照下面这种方式配置一个java.util.Properties实例

<bean id="mappings" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">

   <!-- typed as a java.util.Properties -->
   <property name="properties">
      <value>
         jdbc.driver.className=com.mysql.jdbc.Driver
         jdbc.url=jdbc:mysql://localhost:3306/mydb
      </value>
   </property>
</bean>

  如果采用上面的配置,Spring容器将使用JavaBean PropertyEditor把元素中的文本转换为一个java.util.Properties实例

idref元素

  idref元素用来将容器内其它bean的id传给 或 元素,同时提供错误验证功能。(如果使用元素指定拦截器名字,可以避免因一时疏忽导致的拦截器ID拼写错误。)

<bean id="theTargetBean" class="..."/>

<bean id="theClientBean" class="...">
    <property name="targetName">
        <idref bean="theTargetBean" />
    </property>
</bean>

  上述bean定义片段完全地等同于(在运行时)以下的片段:

<bean id="theTargetBean" class="..." />

<bean id="client" class="...">
    <property name="targetName" value="theTargetBean" />
</bean>

  第一种形式比第二种更可取的主要原因是,使用idref标记允许容器在部署时 验证所被引用的bean是否存在。而第二种方式中,传给client bean的targetName属性值并没有被验证。任何的输入错误仅在client bean实际实例化时才会被发现(可能伴随着致命的错误)。如果client bean 是prototype类型的bean,则此输入错误(及由此导致的异常)可能在容器部署很久以后才会被发现。

  此外,如果被引用的bean在同一XML文件内,且bean名字就是bean id,那么可以使用local属性,此属性允许XML解析器在解析XML文件时对引用的bean进行验证

<property name="targetName">
   <idref local="theTargetBean"/>
</property>

引用其它的bean(协作者)

  在元素内部还可以使用ref元素。该元素用来将bean中指定属性的值设置为对容器中的另外一个bean的引用。如前所述,该引用bean将被作为依赖注入,而且在注入之前会被初始化(如果是singleton bean则已被容器初始化)。尽管都是对另外一个对象的引用,但是通过id/name指向另外一个对象却有三种不同的形式,不同的形式将决定如何处理作用域及验证。

  第一种形式也是最常见的形式是通过使用标记指定bean属性的目标bean,通过该标签可以引用同一容器或父容器内的任何bean(无论是否在同一XML文件中)。XML ‘bean’元素的值既可以是指定bean的id值也可以是其name值

  <ref bean=”someBean”/>
  第二种形式是使用ref的local属性指定目标bean,它可以利用XML解析器来验证所引用的bean是否存在同一文件中。local属性值必须是目标bean的id属性值。如果在同一配置文件中没有找到引用的bean,XML解析器将抛出一个例外。如果目标bean是在同一文件内,使用local方式就是最好的选择(为了尽早地发现错误)。

  <ref local=”someBean”/>
  第三种方式是通过使用ref的parent属性来引用当前容器的父容器中的bean。parent属性值既可以是目标bean的id值,也可以是name属性值。而且目标bean必须在当前容器的父容器中。使用parent属性的主要用途是为了用某个与父容器中的bean同名的代理来包装父容器中的一个bean(例如,子上下文中的一个bean定义覆盖了他的父bean)。

<!-- in the parent context -->

    <bean id="accountService" class="com.foo.SimpleAccountService">
    </bean>
<!-- in the child (descendant) context -->

<bean id="accountService" class="org.springframework.aop.framework.ProxyFactoryBean">
      <property name="target">
          <ref parent="accountService"/>
      </property>
</bean>

内部bean

  所谓的内部bean(inner bean)是指在一个bean的或 元素中使用元素定义的bean。内部bean定义不需要有id或name属性,即使指定id 或 name属性值也将会被容器忽略。

    <bean id="outer" class="...">
        <property name="target">
            <bean class="com.example.Person"> 
                 <property name="name" value="Fiona Apple"/>
                <property name="age" value="25"/>
         </bean>
        </property>
    </bean>

  注意:内部bean中的scope标记及id或name属性将被忽略。内部bean总是匿名的且它们总是prototype模式的。同时将内部bean注入到包含该内部bean之外的bean是不可能的。

集合(重点)

  通过<list/>、<set/>、<map/><props/>元素可以定义和设置与Java Collection类型对应List、Set、MapProperties的值。

<bean id="moreComplexObject" class="example.ComplexObject">
  <!-- results in a setAdminEmails(java.util.Properties) call -->
  <property name="adminEmails">
    <props>
        <prop key="administrator">administrator@example.org</prop>
        <prop key="support">support@example.org</prop>
        <prop key="development">development@example.org</prop>
    </props>
  </property>

  <!-- results in a setSomeList(java.util.List) call -->
  <property name="someList">
    <list>
        <value>a list element followed by a reference</value>
        <ref bean="myDataSource" />
    </list>
  </property>

  <!-- results in a setSomeMap(java.util.Map) call -->
  <property name="someMap">
    <map>
        <entry>
            <key>
                <value>an entry</value>
            </key>
            <value>just some string</value>
        </entry>
        <entry>
            <key>
                <value>a ref</value>
            </key>
            <ref bean="myDataSource" />
        </entry>
    </map>
  </property>

  <!-- results in a setSomeSet(java.util.Set) call -->
  <property name="someSet">
    <set>
        <value>just some string</value>
        <ref bean="myDataSource" />
    </set>
  </property>
</bean>

map的key或value值,或set的value值还可以是以下元素:

bean | ref | idref | list | set | map | props | value | null

注入值(基本、集合)

  注入基本类型的值、注入集合类型的值

    <bean id="eb" class="basic.ExampleBean">
        <property name="name" value="C罗"/>
        <property name="age" value="22"/>
        <property name="cities">
            <list>
                <value>北京</value>
                <value>岳阳</value>
                <value>长沙</value>
                <!-- 允许重复元素 -->
                <value>长沙</value>
            </list>
        </property>
        <property name="interest">
            <set>
                <value>钓鱼</value>
                <value>做饭</value>
                <value>编程</value>
                <!-- 不允许重复元素 -->
                <value>编程</value>
            </set>
        </property>
        <property name="score">
            <map>
                <entry key="english" value="59.5"/>
                <entry key="math" value="69.5"/>
            </map>
        </property>
        <property name="db">
            <props>
                <prop key="username">Tom</prop>
                <prop key="password">1234</prop>
            </props>
        </property>
    </bean>

  将集合类型的值当做一个bean来配置。命名空间(namespace):为了区分同名元素而在

     <util:list id="citiesBean">
        <value>北京</value>
        <value>武汉</value>
        <value>济南</value>
     </util:list>
     <util:set id="interestBean">
        <value>台球</value>
        <value>钓鱼</value>
        <value>做饭</value>
     </util:set>
     <util:map id="scoreBean">
        <entry key="english" value="80"/>
        <entry key="math" value="90"/>
     </util:map>
     <util:properties id="dbBean">
        <prop key="username">Tom</prop>
        <prop key="password">1234</prop>
     </util:properties>
     <bean id="eb2" class="basic.ExampleBean">
        <property name="cities" ref="citiesBean"/>
        <property name="interest" ref="interestBean"/>
        <property name="score" ref="scoreBean"/>
        <property name="db" ref="dbBean"/>
     </bean>

     <!-- 
        读取location指定位置的文件的内容。
        classpath:是spring框架内部的约定。
      -->
     <util:properties id="config" 
     location="classpath:config.properties"/>

集合的合并

  Spring IoC容器支持集合的合并。这样我们可以定义parent-stylechild-style的、、或元素,子集合的值从其父集合继承和覆盖而来;也就是说,*父子集合元素合并*后的值就是子集合中的最终结果,而且子集合中的元素值将覆盖父集全中对应的值

  注意,关于合并的这部分利用了parent-child bean机制

<beans>
<bean id="parent" abstract="true" class="example.ComplexObject">
    <property name="adminEmails">
        <props>
            <prop key="administrator">administrator@example.com</prop>
            <prop key="support">support@example.com</prop>
        </props>
    </property>
</bean>
<bean id="child" parent="parent">
    <property name="adminEmails">
        <!-- the merge is specified on the *child* collection definition -->
        <props merge="true">
            <prop key="sales">sales@example.com</prop>
            <prop key="support">support@example.co.uk</prop>
        </props>
    </property>
</bean>
<beans>

在上面的例子中,childbean的adminEmails属性的元素上使用了merge=true属性。当child bean被容器实际解析及实例化时,其 adminEmails将与父集合的adminEmails属性进行合并。

administrator=administrator@example.com
sales=sales@example.com
support=support@example.co.uk

  子bean的Properties集合将从父继承所有属性元素。同时子bean的support值将覆盖父集合的相应值。不同的集合类型是不能合并(如map和 list是不能合并的),否则将会抛出相应的Exception。

XML配置文件的简写及其他

  配置元数据冗长不是什么好事情,因此我们将通过下面的方式来对配置进行“减肥”,第一种做法就是通过使用<property/>来定义值和对其他bean的引用,另一个做法就是采用不同的属性定义格式

基于XML配置元数据

  <property/>、<constructor-arg/>及<entry/>元素都支持value属性(attribute),它可以用来替代内嵌的<value/>元素。

<property name="myProperty">
  <value>hello</value>
</property>
<constructor-arg>
  <value>hello</value>
</constructor-arg>
<entry key="myKey">
  <value>hello</value>
</entry>

等同于:

<property name="myProperty" value="hello"/>
<constructor-arg value="hello"/>
<entry key="myKey" value="hello"/>

<property/>和<constructor-arg/>支持类似ref的简写属性,它可用来替代整个内嵌的<ref/>元素。因而,以下的代码:

<property name="myProperty">
  <ref bean="myBean">
</property>
<constructor-arg>
  <ref bean="myBean">
</constructor-arg>

等同于:

<property name="myProperty" ref="myBean"/>
<constructor-arg ref="myBean"/>

注意,尽管存在等同于<ref bean=”xxx”> 元素的简写形式,但并没有<ref local=”xxx”>的简写形式,为了对当前xml中bean的引用,你只能使用完整的形式。

最后,map中entry元素的简写形式为key/key-refvalue /value-ref属性,因而,以下的代码:

<entry>
  <key>
    <ref bean="myKeyBean" />
  </key>
  <ref bean="myValueBean" />
</entry>

等同于:

<entry key-ref="myKeyBean" value-ref="myValueBean"/>

使用p名称空间配置属性

  事实上,我们所看到的所有bean的配置格式都是基于一个 XML Schema文档。
  特定的名称空间并不需要定义在一个XSD文件中,它只在Spring内核中存在。我们所说的p名称空间就是这样,它不需要一个schema定义,与我们前面采用元素定义bean的属性不同的是,当我们采用了p名称空间,我们就可以**在bean元素中使用属性(attribute)来描述**bean的property值。

  下面的两段XML配置文件中都是用来定义同一个bean:一个采用的是标准的XML格式,一个是采用p名称空间。

<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:p="http://www.springframework.org/schema/p"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">

    <bean name="classic" class="com.example.ExampleBean">
        <property name="email" value="foo@bar.com/>
    </bean>

    <bean name="p-namespace" class="com.example.ExampleBean"
          p:email="foo@bar.com"/>
</beans>

  从上面的bean定义中,我们采用p名称空间的方式包含了一个叫email的属性,而Spring会知道我们的bean包含了一个属性(property)定义。我们前面说了,p名称空间是不需要schema定义的,因此属性(attribute)的名字就是你bean的property的名字。

  下面的例子包含了两个bean定义,它们都引用了另一个bean

<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:p="http://www.springframework.org/schema/p"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">

    <bean name="john-classic" class="com.example.Person">
        <property name="name" value="John Doe"/>
        <property name="spouse" ref="jane"/>
    </bean>

    <bean name="john-modern" 
        class="com.example.Person"
        p:name="John Doe"
        p:spouse-ref="jane"/>

    <bean name="jane" class="com.example.Person">
        <property name="name" value="Jane Doe"/>
    </bean>
</beans>

  上面的例子不仅使用p名称空间包含了一个属性(property)值,而且使用了一个特殊的格式声明了一个属性引用。在第一个bean定义中使用了<property name=”spouse” ref=”jane”/>来建立beanjohn到beanjane的引用,而第二个bean定义则采用p:spouse-ref=”jane“属性(attribute)的方式达到了同样的目的。在这个例子中,”spouse”是属性(property)名,而”-ref“则用来说明该属性不是一个具体的值而是对另外一个bean的引用。

depends-on

  depends-on属性可以用于当前bean初始化之前显式地强制一个或多个bean被初始化。下面的例子中使用了depends-on属性来指定一个bean的依赖。

<bean id="beanOne" class="ExampleBean" depends-on="manager"/>

<bean id="manager" class="ManagerBean" />

  若需要表达对多个bean的依赖,可以在’depends-on’中将指定的多个bean名字用分隔符进行分隔,分隔符可以是逗号、空格及分号等。下面的例子中使用了’depends-on’来表达对多个bean的依赖。

<bean id="beanOne" class="ExampleBean" depends-on="manager,accountDao">
  <property name="manager" ref="manager" />
</bean>

<bean id="manager" class="ManagerBean" />
<bean id="accountDao" class="x.y.jdbc.JdbcAccountDao" />

  注意
  “depends-on”属性不仅用来指定初始化时的依赖,同时也用来指定相应的销毁时的依赖(该依赖只针对singletonbean)。depends-on属性中指定的依赖bean会在相关bean销毁之前被销毁,从而可以让用户控制销毁顺序。
## 延迟初始化bean ##
**  默认情况下,容器启动之后,会将所用作用域为
   singleton的bean创建好。
   可以设置lazy-init属性为true,表示延迟加载**
  ApplicationContext实现的默认行为就是在启动时将所有singleton bean提前进行实例化。提前实例化意味着作为初始化过程的一部分,ApplicationContext实例会创建并配置所有的singleton bean。通常情况下这是件好事,因为这样在配置中的任何错误就会即刻被发现(否则的话可能要花几个小时甚至几天)。

  有时候这种默认处理可能并不是你想要的。如果你不想让一个singleton bean在ApplicationContext初始化时被提前实例化,那么可以将bean设置为延迟实例化。一个延迟初始化bean将告诉IoC 容器是在启动时还是在第一次被用到时实例化。

  在XML配置文件中,延迟初始化将通过元素中的lazy-init属性来进行控制。例如:

<bean id="lazy" class="com.foo.ExpensiveToCreateBean" lazy-init="true"/>

<bean name="not.lazy" class="com.foo.AnotherBean"/>

  当ApplicationContext实现加载上述配置时,设置为lazy的bean将不会在ApplicationContext启动时提前被实例化,而not.lazy却会被提前实例化。

  需要说明的是,如果一个bean被设置为延迟初始化,而另一个非延迟初始化的singleton bean**依赖于它**,那么当ApplicationContext提前实例化singleton bean时,它必须也确保所有上述singleton 依赖bean也被预先初始化,当然也包括设置为延迟实例化的bean。因此,如果Ioc容器在启动的时候创建了那些设置为延迟实例化的bean的实例,你也不要觉得奇怪,因为那些延迟初始化的bean可能在配置的某个地方被注入到了一个非延迟初始化singleton bean里面。

  在容器层次上通过在元素上使用’default-lazy-init’属性来控制延迟初始化也是可能的。如下面的配置:

<beans default-lazy-init="true">
    <!-- no beans will be pre-instantiated... -->
</beans>
相关实践学习
如何在云端创建MySQL数据库
开始实验后,系统会自动创建一台自建MySQL的 源数据库 ECS 实例和一台 目标数据库 RDS。
全面了解阿里云能为你做什么
阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助 &nbsp; &nbsp; 相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
相关文章
|
12天前
|
Java 开发者 微服务
手写模拟Spring Boot自动配置功能
【11月更文挑战第19天】随着微服务架构的兴起,Spring Boot作为一种快速开发框架,因其简化了Spring应用的初始搭建和开发过程,受到了广大开发者的青睐。自动配置作为Spring Boot的核心特性之一,大大减少了手动配置的工作量,提高了开发效率。
31 0
|
1月前
|
Java API 数据库
构建RESTful API已经成为现代Web开发的标准做法之一。Spring Boot框架因其简洁的配置、快速的启动特性及丰富的功能集而备受开发者青睐。
【10月更文挑战第11天】本文介绍如何使用Spring Boot构建在线图书管理系统的RESTful API。通过创建Spring Boot项目,定义`Book`实体类、`BookRepository`接口和`BookService`服务类,最后实现`BookController`控制器来处理HTTP请求,展示了从基础环境搭建到API测试的完整过程。
48 4
|
1月前
|
Java API 数据库
Spring Boot框架因其简洁的配置、快速的启动特性及丰富的功能集而备受开发者青睐
本文通过在线图书管理系统案例,详细介绍如何使用Spring Boot构建RESTful API。从项目基础环境搭建、实体类与数据访问层定义,到业务逻辑实现和控制器编写,逐步展示了Spring Boot的简洁配置和强大功能。最后,通过Postman测试API,并介绍了如何添加安全性和异常处理,确保API的稳定性和安全性。
38 0
|
30天前
|
Java API Spring
在 Spring 配置文件中配置 Filter 的步骤
【10月更文挑战第21天】在 Spring 配置文件中配置 Filter 是实现请求过滤的重要手段。通过合理的配置,可以灵活地对请求进行处理,满足各种应用需求。还可以根据具体的项目要求和实际情况,进一步深入研究和优化 Filter 的配置,以提高应用的性能和安全性。
|
22天前
|
Java Spring
[Spring]aop的配置与使用
本文介绍了AOP(面向切面编程)的基本概念和核心思想。AOP是Spring框架的核心功能之一,通过动态代理在不修改原代码的情况下注入新功能。文章详细解释了连接点、切入点、通知、切面等关键概念,并列举了前置通知、后置通知、最终通知、异常通知和环绕通知五种通知类型。
30 1
|
1月前
|
Java BI 调度
Java Spring的定时任务的配置和使用
遵循上述步骤,你就可以在Spring应用中轻松地配置和使用定时任务,满足各种定时处理需求。
139 1
|
2月前
|
XML Java 数据格式
Spring IOC—基于XML配置Bean的更多内容和细节(通俗易懂)
Spring 第二节内容补充 关于Bean配置的更多内容和细节 万字详解!
225 18
Spring IOC—基于XML配置Bean的更多内容和细节(通俗易懂)
|
2月前
|
前端开发 Java Spring
关于spring mvc 的 addPathPatterns 拦截配置常见问题
关于spring mvc 的 addPathPatterns 拦截配置常见问题
233 1
|
1月前
|
XML Java 数据格式
手动开发-简单的Spring基于注解配置的程序--源码解析
手动开发-简单的Spring基于注解配置的程序--源码解析
47 0
|
1月前
|
XML Java 数据格式
手动开发-简单的Spring基于XML配置的程序--源码解析
手动开发-简单的Spring基于XML配置的程序--源码解析
82 0
下一篇
无影云桌面