spring 框架说明文档学习记录(3.3)

来源:互联网 发布:淘宝网店如何起步 编辑:程序博客网 时间:2024/06/06 00:40

三.三 依赖和配置详情

简单值

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

java.util.properties实例(spring通过PropertyEditor机制,将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>

idref元素

idref元素,只是简单的在将其他bean的id(string类型,不是引用)传给<constructor-arg/>或<property/>元素时进行错误验证。

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

等同于

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

第一种写法要优于第二种,第一种可以在部署时验证引用的bean实际存在


idref的通常使用场景为ProxyFactoryBean定义中的AOP 拦截器。使用idref防止拦截器id的拼写错误

注意:4.0的bean xsd中,不再支持idref的local属性,使用idref的bean属性替代

对其他beans的引用

<ref bean="someBean"/>

ref中parent属性,引用父级容器中的bean

<!-- in the parent context --><bean id="accountService" class="com.foo.SimpleAccountService"><!-- insert dependencies as required as here --></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>

注意:ref元素中的local属性在beans的xsd 4.0后不再支持,使用bean属性替代

内部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>
内部bean,不需要定义id或name,如果定义了,容器也不会作为id使用。同时容器忽略scope标记,内部bean是匿名的并随外部bean的创建而创建。

集合
我们在<list/>,<set/>,<map/>和<props/>元素中,设置java的集合类型参数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>

集合合并

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

注意merge="true"的使用,child中adminEmails的值为合并后的结果

administrator=administrator@example.comsales=sales@example.comsupport=support@example.co.uk

null和空字符串

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

使用p-命名空间简化xml

简单值

<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/beanshttp://www.springframework.org/schema/beans/spring-beans.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>
beans引用

<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/beanshttp://www.springframework.org/schema/beans/spring-beans.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>

使用c-命名空间简化xml

与p-命名空间对应<property>一样,c-命名空间对应<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/beanshttp://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进行编译),我们可以使用参数顺序赋值

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

混合属性名称
<bean id="foo" class="foo.Bar">  <property name="fred.bob.sammy" value="123" /></bean>
其中 bean foo有一个fred属性,fred有一个bob属性,bob有一个sammy属性,且sammy前各属性都不为空,否则抛出空指针异常

使用depends-on

depends-on属性,能够明确的强制一个或多个bean在当前bean之前进行初始化。

<bean id="beanOne" class="ExampleBean" depends-on="manager"/><bean id="manager" class="ManagerBean" />
依赖多个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" />
懒加载bean
ApplicationContext默认立即加载bean以便提早发现问题。我们可以通过定义bean为懒加载来组织使用预加载。

<bean id="lazy" class="com.foo.ExpensiveToCreateBean" lazy-init="true"/><bean name="not.lazy" class="com.foo.AnotherBean"/>
<beans default-lazy-init="true"><!-- no beans will be pre-instantiated... --></beans>

自动装配
自动装配功能有四个模式

no  :  不使用自动装配

byName  :  通过属性name绑定,spring寻找要自动装配的名称相同的bean,如果一个bean被设置为自动装配,它有一个master属性(和setMaster()方法),spring寻找一个名称为master的bean,并用它设置这个属性。

byType  :  如果容器中有该类型的bean,则将该属性自动装配,如果有多个该类型属性,会报错,如果没有可匹配bean,什么都不做。

constructor  :  与byType类似,在构造函数参数上使用。如果容器中没有构造函数参数类型的bean,会报致命错误。


避免bean使用自动装配

设置<bean/>的autowire-candidate属性为false


方法注入

在大部分应用场景中,容器中大部分都是单例的。当一个单例集成另一个单例或一个非单例集成另一个非单例时,我们一般将一个bean注册为另一个bean的属性。但是这会存在一个问题,假设单例A需要使用非单例B,某一个方法中调用。容器只能创建单例A一次,因此只能有一次设置其属性的机会。容器不能给单例A提供一个新的非单例B的实例。

一种解决方案是放弃部分控制反转,我们可以通过实现ApplicationContextAware创建一个与容器关联的bean A。

// a class that uses a stateful Command-style class to perform some processingpackage fiona.apple;// Spring-API importsimport org.springframework.beans.BeansException;import org.springframework.context.ApplicationContext;import org.springframework.context.ApplicationContextAware;public class CommandManager implements ApplicationContextAware {  private ApplicationContext applicationContext;  public Object process(Map commandState) {    // grab a new instance of the appropriate Command    Command command = createCommand();    // set the state on the (hopefully brand new) Command instance    command.setState(commandState);    return command.execute();  }  protected Command createCommand() {    // notice the Spring API dependency!    return this.applicationContext.getBean("command", Command.class);  }  public void setApplicationContext(    ApplicationContext applicationContext) throws BeansException {    this.applicationContext = applicationContext;  }}
查找方法注入
public abstract class CommandManager {  public Object process(Object commandState) {    // grab a new instance of the appropriate Command interface    Command command = createCommand();    // set the state on the (hopefully brand new) Command instance    command.setState(commandState);    return command.execute();  }  // okay... but where is the implementation of this method?  protected abstract Command createCommand();}
<!-- a stateful bean deployed as a prototype (non-singleton) --><bean id="command" class="fiona.apple.AsyncCommand" scope="prototype">  <!-- inject dependencies here as required --></bean><!-- commandProcessor uses statefulCommandHelper --><bean id="commandManager" class="fiona.apple.CommandManager">  <lookup-method name="createCommand" bean="command"/></bean>

当commandManager调用createCommand()时,会获得一个新的command实例

方法替换

public class MyValueCalculator {  public String computeValue(String input) {    // some real code...  }  // some other methods...}
/*** meant to be used to override the existing computeValue(String)* implementation in MyValueCalculator*/public class ReplacementComputeValue implements MethodReplacer {  public Object reimplement(Object o, Method m, Object[] args) throws Throwable {    // get the input value, work with it, and return a computed result    String input = (String) args[0];    ...    return ...;  }}
<bean id="myValueCalculator" class="x.y.z.MyValueCalculator">  <!-- arbitrary method replacement -->  <replaced-method name="computeValue" replacer="replacementComputeValue">    <arg-type>String</arg-type>  </replaced-method></bean><bean id="replacementComputeValue" class="a.b.c.ReplacementComputeValue"/>


















0 0
原创粉丝点击