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