spring学习(三)——官方文档阅读(5.0.7)——bean属性的配置方法

bean属性(即类属性)的配置方法

<constructor-arg/>与<property/>中可配置的属性和标签如下:

name、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>

name指定类属性,value为类属性的值,注意到value的值是字符串,spring通过conversion service API完成类型转换

也可以使用p-namespace,需要在xml中添加xmlns:p="http://www.springframework.org/schema/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.xsd">

    <bean id="myDataSource" class="org.apache.commons.dbcp.BasicDataSource"
        destroy-method="close"
        p:driverClassName="com.mysql.jdbc.Driver"
        p:url="jdbc:mysql://localhost:3306/mydb"
        p:username="root"
        p:password="masterkaoli"/>

</beans>

如果需要引用其他类,可以加上ref后缀,例如:p:password—ref

 

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>

通过javaBeans的PropertyEditor机制将value的值转换为java.util.Properties实例

 

<idref/>:

idref允许在容器创建时就就验证依赖bean是否存在,不必等到创建bean的时候在验证

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

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

使用<idref/>可以防止我们拼错单词,idref与ref不同,ref会注入实例化的bean,而idref注入的是字符串,例如上例,targetName的值将为theTargetBean,idref的值必须是一个bean的id或是name,如果id或是name为theTargetBean的bean不存在,那么会抛出异常,不必等到该bean实例化(对于懒加载的bean将十分有用)

 

<ref/>

当依赖是其他bean时,可以使用ref标签引用,ref有bean、parent两种

<ref bean="someBean"/>
  • bean属性表示依赖可以是父容器也可以是本容器的bean(不管是不是在同一个xml文件中),
<bean id="accountService" class="com.foo.SimpleAccountService">
    <!-- insert dependencies as required as here -->
</bean>

  • parent属性表示依赖是父容器的bean
<!-- in the child (descendant) context -->
<bean id="accountService" <!-- bean name is the same as the parent bean -->
    class="org.springframework.aop.framework.ProxyFactoryBean">
    <property name="target">
        <ref parent="accountService"/> <!-- notice how we refer to the parent bean -->
    </property>
    <!-- insert other configuration and dependencies as required here -->
</bean>

 

 

inner beans

在<property/>或是<constructor-arg/>内使用<bean/>标签配置的类

<bean id="outer" class="...">
    <!-- instead of using a reference to a target bean, simply define the target bean inline -->
    <property name="target">
        <bean class="com.example.Person"> <!-- this is the inner bean -->
            <property name="name" value="Fiona Apple"/>
            <property name="age" value="25"/>
        </bean>
    </property>
</bean>

inner bean不要求id和name,这也意味着inner bean只能注入outer bean(本例中为id为outer的bean),inner bean会忽略scope标志的设置(scope和outer bean是一致的)

 

注册collection

使用<list/>、<set/>、<map/> <props>标签注册collection包中的list、set、map、properties

<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="an entry" value="just some string"/>
            <entry key ="a ref" value-ref="myDataSource"/>
        </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

集合合并

一个集合可以指定自己的父集合是谁,子集合可以覆盖父集合的值,拿property来说,如下:

<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>

注意id为child的bean,用parent指定了父集合的id,将merge属性置为true,同时覆盖了父集合中的support属性的值,最终child的属性如下:

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

<list/>、<map/>、<set/>使用方式类似,对于<list/>来说,父链的值先于子链,set、map、properties不存在这种现象(因为内部使用的数据结构不是链表,所以可能会重新排列)

 

集合合并的限制

不同类型的集合不能合并(例如Map和List),merge属性只对子集合有效

 

强类型集合

集合支持泛型编程,我们可以指定集合的关键字、键值的类型,此时spring的类型转换器会将配置中bean的属性值转换为对应的类型

,例如:

public class Foo {

    private Map<String, Float> accounts;

    public void setAccounts(Map<String, Float> accounts) {
        this.accounts = accounts;
    }
}
<beans>
    <bean id="foo" class="x.y.Foo">
        <property name="accounts">
            <map>
                <entry key="one" value="9.99"/>
                <entry key="two" value="2.75"/>
                <entry key="six" value="3.99"/>
            </map>
        </property>
    </bean>
</beans>

spring会将one、two、six转换为string类型,9.99、2.75、3.99转换为float类型,当实例化foo时,spring会反射生成map<string,float>

 

空字符串值

在spring中间属性值设置为null的方法:

<bean class="ExampleBean">
    <property name="email">
        <null/>
    </property>
</bean>

c—namespace

c-namespace等效于<constructor-arg/>,如下:

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

    <bean id="bar" class="x.y.Bar"/>
    <bean id="baz" class="x.y.Baz"/>

    <!-- traditional declaration -->
    <bean id="foo" class="x.y.Foo">
        <constructor-arg ref="bar"/>
        <constructor-arg ref="baz"/>
        <constructor-arg value="foo@bar.com"/>
    </bean>

    <!-- c-namespace declaration -->
    <bean id="foo" class="x.y.Foo" c:bar-ref="bar" c:baz-ref="baz" c:email="foo@bar.com"/>

</beans>

如果遇到构造函数参数名字不可用的情况(极少数情况,字节码没有debug信息),可以使用构造函数参数的index指定:

<!-- c-namespace index declaration -->
<bean id="foo" class="x.y.Foo" c:_0-ref="bar" c:_1-ref="baz"/>

由于xml语法的要求,索引表示法要用“_”作为前导

 

复合属性名

在设置bean属性时,可以使用复合属性或嵌套属性名,只要路径的所有组件(最终属性名除外)都不是空的。

<bean id="foo" class="foo.Bar">
    <property name="fred.bob.sammy" value="123" />
</bean>

如上所示,fred和bob均不能为空,否则会抛出NullPointerException异常,这种方式优先于setter方法注入,顺序为——初始化bean实例(调用默认构造函数或是有参构造函数),接着设置复合属性名的值,最后运行setter方法,如果我们使用setter方法注入,将会抛出NullPointerException异常(由于复合属性先于setter方法执行,此时setter方法set的属性的值为空)

 

使用depends-on

当bean初始化到一半,发现某个依赖还未初始化,就会去初始化依赖,使用depends-on,可以控制bean的依赖先于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" />

对于上面的例子,spring可以保证当beanOne初始化时,manager、accountDao已经完成初始化,depends-on也可以控制bean销毁的顺序,以上面的例子为例,beanOne会先被销毁,接着manager、accountDao被销毁

 

懒加载

 

一般情况下,容器初始化时会先初始化单例bean,我们可以指定lazy-initialized属性来延迟初始化单例bean,在第一次请求(例如作为某个bean的依赖)的时候才初始化该单例bean,如下:

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

上述例子中,由于lazy bean的lazy-init值为true,所以lazy bean将会延迟初始化

我们也可以将需要延迟初始化的bean一次性配置好:

<beans default-lazy-init="true">
    <!-- no beans will be pre-instantiated... -->
</beans>
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值