Spring Dependencies Injection

Spring Dependencies Injection

一、construtor argsInjection

    1.1 ref注入

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

package x.y;
public class Foo {
    public Foo(Bar bar, Baz baz) {
    // ...
    }
}

此時會根據類型匹配相應的構造器參數,進行注入java

    1.2 指定type類型 注入


public class ExampleBean {
    // Number of years to calculate the Ultimate Answer
    private int years;
    // The Answer to Life, the Universe, and Everything
    private String ultimateAnswer;
    public ExampleBean(int years, String ultimateAnswer) {
    this.years = years;
    this.ultimateAnswer = ultimateAnswer;
    }
}


<bean id="exampleBean" class="examples.ExampleBean">
    <constructor-arg type="int" value="7500000"/>
    <constructor-arg type="java.lang.String" value="42"/>
</bean>


    1.3 指定index注入

<bean id="exampleBean" class="examples.ExampleBean">
    <constructor-arg index="0" value="7500000"/>
    <constructor-arg index="1" value="42"/>
</bean>


    1.4 使用註解注入

package examples;
public class ExampleBean {
    // Fields omitted
    @ConstructorProperties({"years", "ultimateAnswer"})
    public ExampleBean(int years, String ultimateAnswer) {
        this.years = years;
        this.ultimateAnswer = ultimateAnswer;
    }
}

二、Setter-based dependency injection

    是時候用構造器注入,啥時候用setter哪,一個經驗說:必須的參數須要構造器注入,其餘的能夠用setter,可是,也能夠用@Required annotation去顯示指定必須的參數spring

    2.1 簡單的set注入

        

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

<bean id="simpleMovieLister" class = "...">
    <property name = "movieFinder" ref = "movieFinder"></property>
</bean>

    大量的setter注入須要灰常多的的非空判斷,因此spring的官方推薦是用constructor的注入,若是須要傳入的參數過多,建議使用工廠方法,哦耶!express

三、依賴解析流程

    第一步:

            ApplicationContext建立,使用經過xml,java code ,annotation配置的元數據進行初始化beandefinition,ide

            (The ApplicationContext is created and initialized with configuration metadata that describes all
the beans. Configuration metadata can be specified via XML, Java code, or annotations.)函數

    第二步:

            獲取到每一個經過構造函數,setter,property,工廠方法注入的屬性(ref,基本數據類型),在這個bena被建立的時候賦值給他
學習

            (For each bean, its dependencies are expressed in the form of properties, constructor arguments, or
arguments to the static-factory method if you are using that instead of a normal constructor. These
dependencies are provided to the bean, when the bean is actually created.)ui

    第三步:

            

    每一個屬性或構造函數參數的定義的參數都是一個集合,或者基本數據類型,或者容器中另一個bean的引用。this

    (Each property or constructor argument is an actual definition of the value to set, or a reference to
another bean in the container)
spa

    

    第四步:

    每一個構造器參數或者屬性都是被轉化爲實際的類型,默認的spring會轉化value爲任何一個基本類型int,long,boolean,String等
code

   ( Each property or constructor argument which is a value is converted from its specified format to the
actual type of that property or constructor argument. By default Spring can convert a value supplied
in string format to all built-in types, such as int, long, String, boolean, etc.)


循環依賴(Circular dependencies)注入

    加入你頂一個class A,他的構造器裏面須要參數爲Class B,同時,class B的構造器須要一個Class A這時候Spring注入會陷入循環當中,拋出一個BeanCurrentlyInCreationException的異常

咋辦,雖然推薦用構造器注入好,可是這種狀況下,你要變通下,用setter注入不就行了嗎,ok!

這是一個經典的哲學問題,先有雞仍是先有蛋(a classic chicken/egg scenario)

雖Spring會有問題,可是一般狀況下你要相信Spring的解決能力,當在load的時候他不會影響整個系統的由於單個bean的注入問題,只有在整個bean被建立的時候纔會報錯,值得學習的思想



屬性 idref

    idef能夠在容器初始化以前經行驗證,制定的id的ref對象是否存在

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


屬性ref

<bean id="theTargetBean" class="..."/>
<bean id="theClientBean" class="...">
<property name="targetName">
<ref id="theTargetBean" />
</property>
</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>


內部類


    這個內部類顯示去配置聲明一個bean元素時候不須要指定id 或者name,容器不會去須要這個,並且scope也不須要

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



集合Collections

      

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


自動合併父級集合屬性,merge
<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>



depends-on


ref有時候不太強大,當你須要初始化你的類以前,須要確保你的引用類必定被先初始化,這時候該標籤有了一個強大力量

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

The depends-on attribute in the bean definition can specify both an initialization time dependencyand, in the case of singleton beans only, a corresponding destroy time dependency. Dependentbeans that define a depends-on relationship with a given bean are destroyed first, prior to thegiven bean itself being destroyed. Thus depends-on can also control shutdown order.

相關文章
相關標籤/搜索