`

注入的方式

    博客分类:
  • J2EE
 
阅读更多

 

一、依赖注入概述

 

Dependency injection (DI) is a process whereby objects define their dependencies, that is, the other 

objects they work with,The container then injects those dependencies when it creates the bean. This 

process is fundamentally the inverse, hence the name Inversion of Control (IoC).DI exists in two major variants, Constructor-based dependency injection and Setter-based dependency injection.

 

 

二、依赖注入分类

 

1.基于构造函数的注入

 

  1)自动依据类型的动态绑定注入

 

No potential ambiguity exists, assuming that Bar and Baz classes are not related by inheritance. Thus 

the following configuration works fine, and you do not need to specify the constructor argument indexes and/or types explicitly in the <constructor-arg/> element.

 

<beans>

  <bean id="foo" class="x.y.Foo">

      <constructor-arg ref="bar"/>

      <constructor-arg ref="baz"/>

  </bean>

 

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

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

 

</beans>

 

2)指定类型的动态绑定注入

 

In the preceding scenario, the container can use type matching with simple types if you explicitly 

specify the type of the constructor argument using the type attribute. For example:

 

<bean id="exampleBean" class="examples.ExampleBean">

<constructor-arg type="int" value="7500000"/>

<constructor-arg type="java.lang.String" value="42"/>

</bean>

 

3)指定位置的绑定注入

 

Use the index attribute to specify explicitly the index of constructor arguments. For example:

 

<bean id="exampleBean" class="examples.ExampleBean">

<constructor-arg index="0" value="7500000"/>

<constructor-arg index="1" value="42"/>

</bean>

In addition to resolving the ambiguity of multiple simple values, specifying an index resolves ambiguity 

 

where a constructor has two arguments of the same type. Note that the index is 0 based.

 

4)指定参数名称的绑定注入

 

As of Spring 3.0 you can also use the constructor parameter name for value disambiguation:

 

<bean id="exampleBean" class="examples.ExampleBean">

<constructor-arg name="years" value="7500000"/>

<constructor-arg name="ultimateanswer" value="42"/>

</bean>

 

2.依据setter方法的注入

 

The following example shows a class that can only be dependency-injected using pure setter injection. This class is conventional Java. It is a POJO that has no dependencies on container specific interfaces, base classes or annotations.

 

public class SimpleMovieLister {

 

  // the SimpleMovieLister has a dependency on the MovieFinder

  private MovieFinder movieFinder;

 

  // a setter method so that the Spring container can 'inject' a MovieFinder

  public void setMovieFinder(MovieFinder movieFinder) {

      this.movieFinder = movieFinder;

  }

 

  // business logic that actually 'uses' the injected MovieFinder is omitted...

}

 

POJO类里面,必须有set方法。

 

三、注入值时的一些方法

 

 

1.

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

 

2.

The following example uses the p-namespace for even more succinct XML configuration.

 

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

The preceding XML is more succinct; however, typos are discovered at runtime rather than design time, unless you use an IDE such as IntelliJ IDEA or the SpringSource Tool Suite (STS) that support automatic property completion when you create bean definitions. Such IDE assistance is highly recommended.

 

3.

The idref elementThe idref element is simply an error-proof way to pass the id (string value - not a reference) of another bean in the container to a <constructor-arg/> or <property/> element.

 

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

 

<bean id="theClientBean" class="...">

  <property name="targetName">

      <idref bean="theTargetBean" />

  </property>

</bean>

The above bean definition snippet is exactly equivalent (at runtime) to the following snippet:

 

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

 

<bean id="client" class="...">

  <property name="targetName" value="theTargetBean" />

</bean>

The first form is preferable to the second, because using the idref tag allows the container to validate 

at deployment time that the referenced, named bean actually exists. In the second variation, no 

validation is performed on the value that is passed to the targetName property of the client bean. 

Additionally, if the referenced bean is in the same XML unit, and the bean name is the bean id, you can use the local attribute, which allows the XML parser itself to validate the bean id earlier, at XML 

document parse time.

 

<property name="targetName">

 <!-- a bean with id 'theTargetBean' must exist; otherwise an exception will be thrown -->

 <idref local="theTargetBean"/>

</property>

</bean>

 

4.

 

Specifying the target bean through the parent attribute creates a reference to a bean that is in a 

parent container of the current container. The value of the parent attribute may be the same as either 

the id attribute of the target bean, or one of the values in the name attribute of the target bean, and 

the target bean must be in a parent container of the current one. You use this bean reference variant 

mainly when you have a hierarchy of containers and you want to wrap an existing bean in a parent 

container with a proxy that will have the same name as the 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>

 

5.

 

A <bean/> element inside the <property/> or <constructor-arg/> elements defines a so-called inner 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>

An inner bean definition does not require a defined id or name; the container ignores these values. It 

also ignores the scope flag. Inner beans are always anonymous and they are always scoped as prototypes. It is not possible to inject inner beans into collaborating beans other than into the enclosing bean.

 

6.集合注入

 

In the <list/>, <set/>, <map/>, and <props/> elements, you set the properties and arguments of the Java 

 

Collection types List, Set, Map, and Properties, respectively.

 

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

The value of a map key or value, or a set value, can also again be any of the following elements:Collection merging

As of Spring 2.0, the container supports the merging of collections. An application developer can define 

 

a parent-style <list/>, <map/>, <set/> or <props/> element, and have child-style <list/>, <map/>, <set/> or <props/> elements inherit and override values from the parent collection. That is, the child 

collection's values are the result of merging the elements of the parent and child collections, with the 

child's collection elements overriding values specified in the parent collection.This section on merging discusses the parent-child bean mechanism. Readers unfamiliar with parent and child bean definitions may wish to read the relevant section before continuing.

 

The following example demonstrates collection merging:

 

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

Notice the use of the merge=true attribute on the <props/> element of the adminEmails property of the child bean definition. When the child bean is resolved and instantiated by the container, the resulting instance has an adminEmails Properties collection that contains the result of the merging of the child's adminEmails collection with the parent's adminEmails collection.

 

administrator=administrator@example.com

sales=sales@example.com

support=support@example.co.uk

 

The child Properties collection's value set inherits all property elements from the parent <props/>, and 

the child's value for the support value overrides the value in the parent collection.

 

7.Null and empty string values

 

Spring treats empty arguments for properties and the like as empty Strings. The following XML-based 

configuration metadata snippet sets the email property to the empty String value ("")

 

<bean class="ExampleBean">

<property name="email" value=""/>

</bean>

The preceding example is equivalent to the following Java code: exampleBean.setEmail(""). The <null/> 

 

element handles null values. For example:

 

<bean class="ExampleBean">

<property name="email"><null/></property>

</bean>

The above configuration is equivalent to the following Java code: exampleBean.setEmail(null).

 

8.XML shortcut with the p-namespace

 

The p-namespace enables you to use the bean element's attributes, instead of nested <property/> 

elements, to describe your property values and/or collaborating beans.Spring 2.0 and later supports extensible configuration formats with namespaces, which are based on an XML Schema definition. The beans configuration format discussed in this chapter is defined in an XML Schema document. However, the p-namespace is not defined in an XSD file and exists only in the core of Spring.

 

The following example shows two XML snippets that resolve to the same result: The first uses standard 

 

XML format and the second uses the p-namespace.

 

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

The example shows an attribute in the p-namespace called email in the bean definition. This tells Spring to include a property declaration. As previously mentioned, the p-namespace does not have a schema definition, so you can set the name of the attribute to the property name.This next example includes two more bean definitions that both have a reference to another 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.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>

 

9.XML shortcut with the c-namespace

 

Similar to the Section 5.4.2.6, “XML shortcut with the p-namespace”, the c-namespace, newly introduced in Spring 3.1, allows usage of inlined attributes for configuring the constructor arguments rather then nested constructor-arg elements.Let's review the examples from Section 5.4.1.1, “Constructor-based dependency injection” with the c namespace:

 

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

For the rare cases where the constructor argument names are not available (usually if the bytecode was compiled without debugging information), one can use fallback to the argument indexes:

 

<-- 'c-namespace' index declaration -->

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

 

10.Using depends-on

 

If a bean is a dependency of another that usually means that one bean is set as a property of another. Typically you accomplish this with the <ref/> element in XML-based configuration metadata. However, sometimes dependencies between beans are less direct; for example, a static initializer in a class needs to be triggered, such as database driver registration. The depends-on attribute can explicitly force one or more beans to be initialized before the bean using this element is initialized. The following example uses the depends-on attribute to express a dependency on a single bean:

 

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

 

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

To express a dependency on multiple beans, supply a list of bean names as the value of the depends-on attribute, with commas, whitespace and semicolons, used as valid delimiters:

 

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

 

11.Lazy-initialized beans

 

By default, ApplicationContext implementations eagerly create and configure all singleton beans as part of the initialization process. Generally, this pre-instantiation is desirable, because errors in the 

configuration or surrounding environment are discovered immediately, as opposed to hours or even days later. When this behavior is not desirable, you can prevent pre-instantiation of a singleton bean by marking the bean definition as lazy-initialized. A lazy-initialized bean tells the IoC container to create a bean instance when it is first requested, rather than at startup.

In XML, this behavior is controlled by the lazy-init attribute on the <bean/> element; for example:

 

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

 

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

 

When the preceding configuration is consumed by an ApplicationContext, the bean named lazy is not 

eagerly pre-instantiated when the ApplicationContext is starting up, whereas the not.lazy bean is 

eagerly pre-instantiated.However, when a lazy-initialized bean is a dependency of a singleton bean that is not lazy-initialized, the ApplicationContext creates the lazy-initialized bean at startup, because it must satisfy the singleton's dependencies. The lazy-initialized bean is injected into a singleton bean elsewhere that is not lazy-initialized.You can also control lazy-initialization at the container level by using the default-lazy-init attribute on the <beans/> element; for example:

 

<beans default-lazy-init="true">

  <!-- no beans will be pre-instantiated... -->

</beans>

 

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics