<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
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>
<bean id="exampleBean" class="examples.ExampleBean"> <constructor-arg index="0" value="7500000"/> <constructor-arg index="1" value="42"/> </bean>
package examples; public class ExampleBean { // Fields omitted @ConstructorProperties({"years", "ultimateAnswer"}) public ExampleBean(int years, String ultimateAnswer) { this.years = years; this.ultimateAnswer = ultimateAnswer; } }
是時候用構造器注入,啥時候用setter哪,一個經驗說:必須的參數須要構造器注入,其餘的能夠用setter,可是,也能夠用@Required annotation去顯示指定必須的參數spring
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.)
加入你頂一個class A,他的構造器裏面須要參數爲Class B,同時,class B的構造器須要一個Class A這時候Spring注入會陷入循環當中,拋出一個BeanCurrentlyInCreationException的異常
咋辦,雖然推薦用構造器注入好,可是這種狀況下,你要變通下,用setter注入不就行了嗎,ok!
這是一個經典的哲學問題,先有雞仍是先有蛋(a classic chicken/egg scenario)
雖Spring會有問題,可是一般狀況下你要相信Spring的解決能力,當在load的時候他不會影響整個系統的由於單個bean的注入問題,只有在整個bean被建立的時候纔會報錯,值得學習的思想
idef能夠在容器初始化以前經行驗證,制定的id的ref對象是否存在
<bean id="theTargetBean" class="..."/> <bean id="theClientBean" class="..."> <property name="targetName"> <idref bean="theTargetBean" /> </property> </bean>
<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>
<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>
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.