Beans, Bean Factory FlApplicationContext 表3.1.Bean定义的解释 特性 详细说明 c⊥ass 第3.2.3节“bean的类” id和name 第3.2.4节“Bean的标志符(id与name)” singleton或 prototype 第3.2.5节“ Singleton的使用与否” 构造函数参数 第3.3.1节“设置bean的属性和合作者” bean的属性 第3.3.1节“设置bean的属性和合作者” 自动装配模式 第3.3.5节“自动装配协作对象” 依赖检查模式 第3.3.6节“依赖检查” 初始化模式 第3.4.1节“生命周期接口” 析构方法 第3.4.1节“生命周期接口” 注意bean定义可以表示为真正的接口org. springframework. beans. factory. config. Bean Definition以及它的各种 子接口和实现。然而,绝大多数的用户代码不需要与 BeanDefination直接接触。 3.2.3.bean的类 clas属性通常是强制性的(参考第3.2.3.3节“通过实例工厂方法创建bean”和第3.5节“子 bean定义”),有两种用法。在绝大多数情况下, BeanFactory直接调用bean的构造函数来"new"一个 bean(相当于调用new的Java代码), class属性指定了需要创建的bean的类。在比较少的情况下, BeanFactory调用某个类的静态的工厂方法来创建bean, class属性指定了实际包含静态工厂方法的那 个类。(至于静态工厂方法返回的bean的类型是同一个类还是完全不同的另一个类,这并不重要 3.2.3.1.通过构造函数创建bean 当使用构造函数创建bean时,所有普通的类都可以被 Spring使用并且和 Spring兼容。这就是说,被创 建的类不需要实现任何特定的接口或者按照特定的样式进行编写。仅仅指定bean的类就足够了。然而 ,根据bean使用的IoC类型,你可能需要一个默认的(空的)构造函数。 另外, BeanFactory并不局限于管理真正的 JavaBean,它也能管理任何你想让它管理的类。虽然很多 使用 Spring的人喜欢在 BeanFactory中用真正的 JavaBean(仅包含一个默认的(无参数的)构造函数 ,在属性后面定义相对应的 setter和 getter方法),但是在你的 BeanFactory中也可以使用特殊的非 bean样式的类。举例来说,如果你需要使用一个遗留下来的完全没有遵守 JavaBean规范的连接池 不要担心, Spring同样能够管理它。 使用 XmlBeanFactory你可以像下面这样定义你的 bean class: <bean id="exampleBean <bean name= another Example class="examples. ExampleBeanTwo Version 1.1
ň " #$%&ab:nȻ eH ɷɸǙÿ *1%'' ȝ "" ǥ à9$%&:;á 2@.&%B$ ȝ "< ǥ à#$%&:=>? 2@A&%B$á '2&E1$+&ů0,++-0$ ȝ "C ǥ àD2&E1$+&: AFá VWXYZY ȝ "" ǥ àST9$%&:GH.JKLá 9$%&:GH ȝ "" ǥ àST9$%&:GH.JKLá MNOPĭÜ ȝ ""C ǥ àMNOP]K^_á QRĭÜ ȝ ""` ǥ àQRá ȄȅĨĭÜ ȝ "< ǥ àghijklá łV[\ ȝ "< ǥ àghijklá Ƽ9$%&abäÁňǢɲȾ:kl,E'0,2&E5,%B$,9$%&'5%*+,-*&52E#$%&4$52&2+2&ÁÂ|:ȀĂ pkl.ÓÔƘȩyIdžȏƫY:ŭ®¯ząØA#$%&4$52&%+2&ȍkkɻƘ ¦¦ 9° *1%''GHÖĘ{ȡH:òZ¡ȝ """ ǥ àÖŪÓð[\«¬9$%&á.ȝ "C ǥ àp 9$%&abáôIœɀĂ\ƘdžȏƫYȋȌŗI#$%&)%*+,-ȍk¤9$%&:VWXY¨Ȳ&$Ȳwx 9$%&òǸȆŌ¤&$:Ù%%®¯ôI*1%''GHljamਫ¬:9$%&:;Ƙ ǬɼĔ:ȋȌŗI #$%&)%*+,-¤ɥx;:ɳŦ:[\¨«¬9$%&I *1%''GHljamÓǀƂǞɳŦ[\:ƞ x;Ƙ òǏŌɳŦ[\¥¦:9$%&:;Æ{ʼnwx;ă{ſȐzʼn:āwx;IŷǟzƗØôƘ ¦¦ ±²³´µ¶·s Ȇ VWXY«¬9$%&ŹIŖœőÖ:;ɓäÁßD0,2&E ǟǵ.D0,2&EǼijƘ ŷƠ{ǙIß« ¬:;ząØÓÔƃĥea:klůLɽɾea:Ȓܼ³ɿƘdzdzlja9$%&:;ƠʀȕmƘ ȩy Iƿ¶9$%& :;ÆIĄäąØwxʁų:òʂ:ôVWXYƘ āʃI#$%&)%*+,-ǟzʄɴŌú¾ɲȾ:Ù%%#$%&I|Ɣú¾ƃĥĄʅơ|ú¾:;Ƙ ɢȩǠƫ D0,2&E:ɑɟɠ#$%&)%*+,-ɲȾ:Ù%%#$%& òdzƂǞwxʁų:òŤZY:ôVWXY IGHȼÌabǸ^ª:'$++$,.E$++$,[\ôIɤ{Ą:#$%&)%*+,-ƔäÁ eʆ:ñ 9$%&ȒÜ:;Ƙ ĵð¨ǙIĤƙĄąØ wxʇʈŗ¨:ſȐDžœʉʊÙ%%#$%&ȗǁ:ĦkèI zØʋĜID0,2&EʼnȒȕú¾|Ƙ śB1#$%&)%*+,-ĄäÁȑŗÌŷȒabĄ:9$%& *1%''Ë ɭ9$%& 2@ɦȲ$3%B01$#$%&Ȳ *1%''ɦȲ$3%B01$'3%B01$#$%&Ȳɮ ɭ9$%& &%B$ɦȲ%&+$,3%B01$Ȳ *1%''ɦȲ$3%B01$'3%B01$#$%&ÝȲɮ #$%&'( #$%&)%*+,-./0012*%+2&&+$3+ £$,'2&
Beans, Bean Factory FlApplicationContext 至于为构造函数提供(可选的)参数,以及对象实例创建后设置实例属性,将会在后面叙述 3.2.3.2.通过静态工厂方法创建Bean 当你定义一个使用静态工厂方法创建的bean,同时使用 class属性指定包含静态工厂方法的类,这个时 候需要 factory- ethod属性来指定工厂方法名。 Spring调用这个方法(包含一组可选的参数)并返回一个 有效的对象,之后这个对象就完全和构造方法创建的对象一样。用户可以使用这样的bean定义在遗留 代码中调用静态工厂。 下面是一个bean定义的例子,声明这个bean要通过 factory- method指定的方法创建。注意这个bean定 义并没有指定返回对象的类型,只指定包含工厂方法的类。在这个例子中, createInstance必须是 static方法 <bean id= examplebe class="examples. ExampleBean2 factory-method="createInstance/> 至于为工厂方法提供(可选的)参数,以及对象实例被工厂方法创建后设置实例属性,将会在后面叙 述 3.2.3.3.通过实例工厂方法创建bean 使用一个实例工厂方法(非静态的)创建bean和使用静态工厂方法非常类似,调用一个已存在的bean (这个bean应该是工厂类型)的工厂方法来创建新的bean。 使用这种机制, class属性必须为空,而且 factory-bean属性必须指定一个bean的名字,这个bean一定要在 当前的bean工厂或者父bean工厂中,并包含工厂方法。而工厂方法本身仍然要通过 factory- method属性 设置。 下面是一个例子 <!- The factory bean, which contains a me thod called <bean id= my Factory Bear </bean> <I-- The bean to be created via the factory bean -- <bean id="exampleBean factory-bean" my Factory Bean factory-method="createInstance/> 虽然我们要在后面讨论设置bean的属性,但是这个方法意味着工厂bean本身能够被容器通过依赖注射 来管理和配置 3.2.4.Bean的标志符(id与name 每一个bean都有一个或多个id(也叫作标志符,或名字;这些名词说的是一回事)。这些id在管理bean 的 BeanFactory或 Application Context中必须是唯一的。一个bean差不多总是只有一个id,但是如果 个bean有超过一个的id,那么另外的那些本质上可以认为是别名 在一个Xm1 BeanFactory中(包括 Application Context的形式),你可以用id或者name属性来指定bean Version 1.1
ǏŌVWXY¿÷òäŵ:ôZYIÁÂ^_Óð«¬ȼSTÓðGHIǦəȼÌʌî ¦¦ ±²¸¹º»¼½·s§ ȆĄabwx ɳŦ[\«¬:9$%&IʼnŹ *1%''GHljaƂǞɳŦ[\:;IŷxŹ ʍąØ5%*+,-6B$+@GH¨lja[\ȸƘD0,2&E¤ŷx[\òƂǞwũäŵ:ZYôǟ¥¦wx œƛ:^_Iqȼŷx^_ƠſȐ.VW[\«¬:^_wȒƘŭäÁ ŷȒ:9$%&abʇʈ ®¯¤ɳŦƘ ŗÌ{wx9$%&ab:ðpIþÿŷx9$%&ØÖŪ5%*+,-6B$+@lja:[\«¬Ƙ Ƽŷx9$%&a bǟDžœlja¥¦^_:;ÆIƺljaƂǞ[\:;ƘŷxðpI*,$%+$&'+%&*$ ʎʏ{ '+%+2*[\ ɭ9$%& 2@ɦȲ$3%B01$#$%&Ȳ *1%''ɦȲ$3%B01$'3%B01$#$%&Ȳ 5%*+,-6B$+@ɦȲ*,$%+$&'+%&*$Ȳɮ ǏŌ[\¿÷òäŵ:ôZYIÁÂ^_Óðß[\«¬ȼSTÓðGHIǦəȼÌʌ î ¦¦¦ ±²¾¿º»¼½·s wxÓð[\òñɳŦ:ô«¬9$%&. ɳŦ[\ñĘ;ʐI¤wxƣţ:9$%& òŷx9$%&ªLj{;Æô:[\¨«¬é:9$%&Ƙ ŷĂɅI*1%''GHʎʏʂIyǵ5%*+,-69$%&GHʎʏljawx9$%&:ȸȹIŷx9$%&waØ Ȇ:9$%&ůLɉ9$%&IǟƂǞ[\Ƙ y[\cʑNjȩØÖŪ5%*+,-6B$+@GH STƘ ŗÌ{wxðpȱ ɭɯ66 Ý$ 5%*+,- 9$%&( 2* *&+%2&' % B$+@ *%11$@ *,$%+$&'+%&*$ 66ɮ ɭ9$%& 2@ɦȲB-)%*+,-#$%&Ȳ *1%''ɦȲȲɮ ɭ9$%&ɮ ɭɯ66 Ý$ 9$%& + 9$ *,$%+$@ 2% +$ 5%*+,- 9$%& 66ɮ ɭ9$%& 2@ɦȲ$3%B01$#$%&Ȳ 5%*+,-69$%&ɦȲB-)%*+,-#$%&Ȳ 5%*+,-6B$+@ɦȲ*,$%+$&'+%&*$Ȳɮ ɢȩǓǎØȼÌȶǐST9$%&:GHIɤ{ŷx[\Ƽƽƾ9$%&cʑȕßijµÖŪ ľ ¨ú¾.PT ¦À § 9ÁÂà 2@Ä&%B$# ǧwx9$%&ɓœwxůƫx2@òƔɁK=>?IůȸȹʒŷŸȸʓǙ:{w¦ôƘŷŸ2@ú¾9$%& :#$%&)%*+,-ů/0012*%+2&&+$3+ʎʏ{ȥw:Ƙ wx9$%&ʔzƫř{ƺœwx2@Iɤ{Ĥƙ wx9$%&œÕŪwx:2@IƞƟāʃ:ƞŸcdŇäÁų{ķȸƘ wxśB1#$%&)%*+,-òƂƨ/0012*%+2&&+$3+:ɡÜôI ĄäÁ2@ůL&%B$GH¨lja9$%& #$%&'( #$%&)%*+,-./0012*%+2&&+$3+ £$,'2&
Beans, Bean Factory FlApplicationContext 的id(s),并且在这两个或其中一个属性中至少指定一个id。id属性允许你指定一个id,并且它在MML DTD(定义文档)中作为一个真正的ⅫM元素的ID属性被标记,所以ⅫM解析器能够在其他元素指回向 它的时候做一些额外的校验。正因如此,用id属性指定bean的id是一个比较好的方式。然而,ⅫM规 范严格限定了在MLID中合法的字符。通常这并不是真正限制你,但是如果你有必要使用这些字符 在ID中的非法字符),或者你想给bean增加其他的别名,那么你可以通过name属性指定一个或多个id (用逗号,或者分号:分隔) 3.2.5. Singleton的使用与否 Beans被定义为两种部署模式中的一种: singleton或non- singleton(后一种也别叫作 prototype, 尽管这个名词用的不精确因为它并不是非常适合)。如果一个bean是 singleton形态的,那么就只有 一个共享的实例存在,所有和这个bean定义的id符合的bean请求都会返回这个唯一的、特定的实例 如果bean以non- singleton, prototype模式部署的话,对这个bean的每次请求都会创建一个新的bean 实例。这对于例如每个user需要一个独立的user对象这样的情况是非常理想的 Beans默认被部署为 singleton模式,除非你指定。要记住把部署模式变为non- singletion( prototype )后,每一次对这个bean的请求都会导致一个新创建的bean,而这可能并不是你真正想要的。所以仅 仅在绝对需要的时候才把模式改成 prototype 在下面这个例子中,两个bean一个被定义为 singleton,而另一个被定义为non- singleton( prototype )。客户端每次向 BeanFactory请求都会创建新的 exampleBean,而 AnotherExample仅仅被创建一次;在每次 对它请求都会返回这个实例的引用。 class="examples. ExampleBean singleton="false/> <bean name=yetAnother Example : lass="examples. Example Two singleton=true/> 注意:当部署一个bean为 prototype模式,这个bean的生命周期就会有稍许改变。通过定义, Spring 无法管理一个non- singleton/ prototype bean的整个生命周期,因为当它创建之后,它被交给客户端 而且容器根本不再跟踪它了。当说起non- singleton/ prototype bean的时候,你可以把 Spring的角色 想象成“new”操作符的替代品。从那之后的任何生命周期方面的事情都由客户端来处理 BeanFactory中bean的生命周期将会在第3.4.1节“生命周期接口”一节中有更详细的叙述。 3.3.属性,合作者,自动装配和依赖检查 3.3.1.设置bean的属性和合作者 反向控制通常与依赖注入同时提及。基本的规则是bean通过以下方式来定义它们的依赖(比如它们与 之合作的其他对象):构造函数的参数,工厂方法的参数:当对象实例被构造出来或从一个工厂方法 返回后设置在这个实例上的属性。容器的工作就是创建完bean之后,真正地注入这些依赖。这完全是 和一般控制方式相反的(因此称为反向控制),比如bean实例化,或者直接使用构造函数定位依赖关 系,或者类似 Service locator模式的东西。我们不会详细阐述依赖注射的优点,很显然通过使用它 代码变得非常清晰;当bean不再自己査找他们依赖的类而是由容器提供,甚至不需要知道这些类在哪 里以及它们实际上是什么类型,这时高层次的解耦也变得很容易了。 正如上面提到的那样,反向控制/依赖注射存在两种主要的形式: Version 1.1
:2@'IǟǵŷɀxůÉwxGHǏĔljawx2@Ƙ 2@GHƵƶĄljawx2@Iǟǵ|ś² 4Ý4òabņŜôKwxɲȾ:ś²âɬ:4GHß=I ŖÁś²nłµȕÉÊâɬlj¦ |:ŹʍȦwŸʕʃ:¸¹ƘȾɐĤɛI2@GHlja9$%&:2@{wxǬɼƐ:[ÜƘ ȩyIś²ȗ ǁʖɶɴamś² 4J\:ȹ?ƘÖĘŷǟz{ɲȾɴĄI ɤ{ĤƙĄœʎØ ŷŸȹ?ò 4:ñ\ȹ?ôIůLĄʅø9$%&ÉÊ:ķȸI ƞƟĄäÁÖŪ&%B$GHljawxůƫx2@ òʗʘ(ůLIJʘɧIJʙôƘ ¦Å %9fgÄÆ #$%&'ßabɀĂƷʚĭÜ:wĂȱ'2&E1$+&ů&&6'2&E1$+&Ƙ òȼwĂƔķɁK0,++-0$I Ēúŷxȸʓ:zʛȿɐ|ǟz{ñĘɍJôƘ Ĥƙwx9$%&{'2&E1$+&ɡŦ:IƞƟƠƺœ wxĊʜ:ÓðţI Ŗœ.ŷx9$%&ab:2@?J:9$%&Ǎnjɓə¥¦ŷxȥw:ʝea:ÓðƘ Ĥƙ9$%&Á&&6'2&E1$+&I0,++-0$ĭÜƷʚ:ǘI^ŷx9$%&:ǧęǍnjɓə«¬wxé:9$%& ÓðƘŷ^ŌðĤǧx'$,ąØwxȔŰ:'$,^_ŷȒ:ȋȌ{ñƾʅ:Ƙ #$%&'ʁųßƷʚ'2&E1$+&ĭÜIǩñĄljaƘØʞƭƷʚĭÜƢ&&6'2&E1$+2&ò0,++-0$ ôȼIǧwę^ŷx9$%&:ǍnjɓəʟĖwx髬:9$%&Iyŷäǟz{ĄɲȾʅØ:ƘŖÁdz dzdž^ąØ:ŹʍʠƭĭÜȷ}0,++-0$Ƙ ŗÌŷxðpIɀx9$%&wxßab'2&E1$+&Iyāwxßab&&6'2&E1$+&ò0,++-0$ ôƘŬŭŮǧę#$%&)%*+,-Ǎnjɓə«¬é:$3%B01$#$%&Iy/&+$,3%B01$dzdzß«¬węʒǧę ^|Ǎnjɓə¥¦ŷxÓð:ʡƘ ɭ9$%& 2@ɦȲ$3%B01$#$%&Ȳ *1%''ɦȲ$3%B01$'3%B01$#$%&Ȳ '2&E1$+&ɦȲ5%1'$Ȳɮ ɭ9$%& &%B$ɦȲ-$+/&+$,3%B01$Ȳ *1%''ɦȲ$3%B01$'3%B01$#$%&ÝȲ '2&E1$+&ɦȲ+,$Ȳɮ ƼȱȆƷʚwx9$%&0,++-0$ĭÜIŷx9$%&:ghijƠəœʢƶȷƢƘ ÖŪabID0,2&E Ť\ú¾wx&&6'2&E1$+&0,++-0$ 9$%&:ǝxghijI ɐȆ|«¬qȼI|ßsøŬŭŮ yǵijµƿczȪʣʤ|mƘȆǙŐ&&6'2&E1$+&0,++-0$ 9$%&:ŹʍI ĄäÁƭD0,2&E:ʥʦ ʅ_}à&$áÞK?:ʧ®ʨƘ©ƞqȼ:ƃĥghij[Ì:ȋɓɫŬŭ٨½¾ Ƙ #$%&)%*+,-9$%&:ghijǦə ȝ "< ǥ àghijkláwǥœĢɷɸ:ʌîƘ ¦¦ ÇÈCÉ40CÊËÌÍ©¢£ÎÏ ¦¦ ÐÑ 9ÇÈ©É40 ÖĘA !ʼnŹ¿ÂƘ7c:ȗȘ{9$%&ÖŪÁŗ[ܨab|ǎ:òǬĤ|ǎA qJK:ÉÊ^_ôȱVWXY:ZYI[\:ZYʒ Ȇ^_ÓðßVWŲ¨ů©wx[\ ¥¦ȼSTŷxÓðŇ:GHƘijµ:KƠ{«¬ſ9$%&qȼIɲȾĴ !ŷŸƘŷſȐ{ .wɌ[ÜǸ:òɐɛʩôIǬĤ9$%&ÓðĨIůLȍk VWXYaõŋ ƱIůL;ʐD$,2*$ ²*%+,ĭÜ:ʪʫƘǓǎzəɷɸʬî ľ:ƑÐIǠʭȩÖŪ |ȱ ®¯ƢvñĘȇȈʒȆ9$%&zȪMoRʮÊǎ:;y{ɫijµ¿÷IʯǏząØ×ɣŷŸ;Ȗ ǨÁÂ|ǎÓǀŇ{ȵƟ;ÆIŷŹʰĕę:nǿƔƢvǠijɇmƘ ȾĤŇÌ¿Ŋ:ƞȒI ľţɀĂŅØ:ɡÜË #$%&'( #$%&)%*+,-./0012*%+2&&+$3+ £$,'2&
Beans, Bean Factory FlApplicationContext 基于 setter的依赖注射,是在调用无参的构造函数或无参的静态工厂方法实例化你的bean之后, 通过调用你的bean上的 setter方法实现的。在 Bean Factory中定义的使用基于 setter方法的注射依 赖的bean是真正的 JavaBean Spring-般提倡使用基于 setter方法的依赖注射,因为很多的构造 函数参数将会是笨重的,尤其在有些属性是可选的情况下。 基于构造函数的依赖注射,它是通过调用带有许多参数的构造方法实现的,每个参数表示一个合 作者或者属性。另外,调用带有特定参数的静态工厂方法来构造bean可以被认为差不多等同的 接下来的文字会把构造函数的参数看成和静态工厂方法的参数类似。虽然 Spring一般提倡在大多 数情况下使用基于 setter的依赖注射,但是 Spring还是完全支持基于构造函数的依赖注射,因为 你可能想要在那些只提供多参数构造函数并且没有 setter方法的遗留的bean上使用 Spring。另外 对于一些比较简单的bean,一些人更喜欢使用构造函数方法以确保bean不会处于错误的状态 BeanFactory同时支持这两种方式将依赖注射到被管理bean中。(实际上它还支持在一些依赖已经通过构 造函数方法注射后再使用 setter方法注射依赖)。依赖的配置是以 BeanDefinition的形式出现,它和 JavaBeans的 Property Editors起使用从而知道如何把属性从一个格式转变为另一个。真正传送的值被封 装为 Propertyvalue对象。然而,大多数 Spring的使用者并不要直接(比如编程的方式)处理这些类,而 更多地使用一个M定义文件,这个文件会在内部被转变为这些类的实例,用来读取整个 Bean Factor 或 Application Context Bean依赖的决定通常取决于下面这些内容 1. Bean Factory通过使用一个描述所有bean的配置被创建和实例化。大多数的 Spring用户使用一个支 持XM格式配置文件的 BeanFactory或 ApplicationContext实现 2.每一个bean的依赖表现为属性,构造函数参数,或者当用静态工厂方法代替普通构造函数时工厂 方法的参数。这些依赖将会在bean真正被创建出来后提供给bean 3.每一个属性或者构造函数参数要么是一个要被设置的值的定义,要么是一个指向 BeanFactory中其 他bean的引用。在 ApplicationContext的情况下,这个引用可以指向一个父亲 ApplicationContext. 4.每一个属性或构造函数参数的值,必须能够从(配置文件中)被指定的格式转变为真实类型。缺 省情况下, Spring能够把一个字符串格式的值转变为所有内建的类型,比如int,long, String, boolean等等。另外当说到基于XML的 BeanFactory实现的时候(包括 ApplicationContext实现),它 们已经为定义 Lists,Maps,Sets和 Properties集合类型提供了内在的支持。另外, Spring通过使 用 JavaBeans的 Property Editor定义,能够将字符串值转变为其他任意的类型。(你可以为 Property Editor提供你自己的 PropertyEditor定义从而能够转变你自定义的类型;更多关于 PropertyEditors的信息以及如何手工增加自定义的 PropertyEditors请参看第3.9节“注册附 加的定制 PropertyEditor”)。当一个bean属性是一个 Java Class类型, Spring允许你用这个类 的名字的字符串作为这个属性的值, Classeditor这个内建的 Property Editor会帮你把类的名字转 变成真实的 Class实例 5.很重要的一点就是: Spring在 BeanFactory创建的时候要校验 BeanFactory中每一个Bean的配置。 这些校验包括作为Bean引用的属性必须实际引用一个合法的bean(比如被引用的bean也定义在 BeanFactory中,或者当 Application Context时,在父亲 ApplicationContext中)。但是,bean属 性本身直到bean被真实建立的的时候才被设置。对于那些是 singleton并且被设置为 pre- instantiated的bean来说(比如一个 Application Context中的 singletonbean),bean在创建 Bean Factory的时候创建,但是对于其他情况,发生在bean被请求的时候。当一个bean必须被创建 时,它会潜在地导致一系列的其他bean被创建,像它的依赖以及它的依赖的依赖(如此下去)被 创建和赋值。 6.通常你可以信任 Spring做了正确的事情。它会在 BeanFactory装载的时候检查出错误,包括对不存 在bean的引用和循环引用。它会尽可能晩地设置属性和解决依赖(比如创建那些需要的依赖) 也就是在bean真正被创建的时候。这就意味着:就算一个 Bean Factory被正确地装载,稍后当你请 求一个bean的时候,如果创建那个bean或者它的依赖的时候出现了错误,这个 BeanFactory也会抛 出一个异常。比如,如果一个bean抛出一个异常作为缺少或非法属性的结果,这样的情况就会发 Version 1.1
ɱ 7Ō'$++$,: ľI{¤ŤZ:VWXYůŤZ:ɳŦ[\ÓðĨĄ:9$%&qȼI ÖŪ¤Ą:9$%&Ň:'$++$,[\ÓÔ:Ƙ #$%&)%*+,-ab: 7Ō'$++$,[\: ľ :9$%&{ɲȾ:Ù%%#$%&Ƙ D0,2&EwɌ¿ʱ 7Ō'$++$,[\: ľIɐǠƫ:VW XYZYǦə{ʲƗ:I ʳÉœŸGH{äŵ:ȋȌŗƘ ɱ 7ŌVWXY: ľI|{ÖŪ¤ʴœƶƫZY:VW[\ÓÔ:I ǧxZYňǢwxJ KLůLGHƘ āʃI¤ʴœeaZY:ɳŦ[\¨VW9$%&äÁßųʔzƫʵʼn:I kŗ¨:ņȹəƭVWXY:ZYʶ}.ɳŦ[\:ZY;ʐƘ ɢȩD0,2&EwɌ¿ʱȏƫ YȋȌŗ 7Ō'$++$,: ľI ɤ{D0,2&Eă{ſȐæç7ŌVWXY: ľI ɐ ĄäʅØƞŸƺ¿÷ƫZYVWXYǟǵDžœ'$++$,[\:ʇʈ:9$%&Ň D0,2&EƘ āʃ ^ŌwŸǬɼï:9$%&IwŸɑĢɟɠ VWXY[\Áȿʷ9$%&zə½ŌĝĞ:ťŦƘ #$%&)%*+,-ʼnŹæçŷɀĂ[ÜǦ ľŊßú¾9$%&ƘòÓǀŇ|ăæçwŸƣȚÖŪV WXY[\ ľȼȪ '$++$,[\ ľôƘ:PT{Á#$%&4$52&2+2&:ɡÜŲÔI|. Ù%%#$%&':,0$,+-@2+,'wŐ ©y×ɣĤĥƭGH©wxɶÜÇƢāwxƘɲȾŠ:§ß» O,0$,+-£%1$^_ƘȩyIȏƫYD0,2&E: LǟzØȍkòǬĤ³Í:[Üô½¾ŷŸ;Iy ĢƫĴ wxś²abņIŷxņəÅƷßÇƢŷŸ;:ÓðI¨ȰÀǝx#$%&)%*+,- ů/0012*%+2&&+$3+Ƙ #$%&:ƦaÖĘÀƦŌŗÌŷŸÅijË #$%&)%*+,-ÖŪ wxǫîŖœ9$%&:PTß«¬.ÓðĨƘȏƫY:D0,2&Eŭ wxæ çś²ɶÜPTņ:#$%&)%*+,-ů/0012*%+2&&+$3+ÓÔƘ ǧwx9$%&:ňÔGHIVWXYZYIůLȆɳŦ[\®ʧőÖVWXYŹ [\:ZYƘŷŸǦə9$%&ɲȾß«¬Ų¨ȼ¿÷ø9$%&Ƙ " ǧwxGHůLVWXYZYØƟ{wxØßST:§:abIØƟ{wxlj#$%&)%*+,-É Ê9$%&:ʡƘ/0012*%+2&&+$3+:ȋȌŗIŷxʡäÁljwxɉʸ /0012*%+2&&+$3+9$%&Ƙ < ǧwxGHůVWXYZY:§Iʎʏȕ©òPTņôßlja:ɶÜÇƢɲÓ;ÆƘʹ ʺȋȌŗID0,2&Eȕƭwxȹ?ǭɶÜ:§ÇƢŖœÅ¬:;ÆIǬĤ2&+( 1&EID+,2&E( 91$%&ʵʵƘāʃȆǙŊ7Ōś²:#$%&)%*+,-ÓÔ:ŹʍòƂƨ/0012*%+2&&+$3+ÓÔôI| ǎƣȚab²2'+'( %0'( D$+'.,0$,+2$'íJ;Æ¿÷mÅ:æçƘāʃID0,2&EÖŪ Ù%%#$%&': ,0$,+-@2+,abIȕǦȹ?ǭ§ÇƢÉÊƃƼ:;ÆƘòĄäÁ ,0$,+-@2+,¿÷ĄMo:,0$,+-@2+,ab©yȕÇƢĄMab:;ÆʒĢƫŋŌ ,0$,+-@2+,':ŃńÁÂĤĥ¢Mab:,0$,+-@2+,'ǍZʶȝ " ǥ à :a,0$,+-@2+,áôƘȆwx9$%&GH{wxÙ%% 1%'';ÆID0,2&EƵƶĄŷx; :ȸȹ:ȹ?ǭKŷxGH:§I1%''@2+, ŷxŬ:,0$,+-@2+,əʻĄƭ;:ȸȹÇ Ƣ}ɲÓ:1%''ÓðƘ C ǠƗØ:wÐƠ{ȱD0,2&E#$%&)%*+,-«¬:Źʍظ¹#$%&)%*+,-ǧwx#$%&:PTƘ ŷŸ¸¹ƂƨK#$%&ʡ:GHʎʏÓǀʡwxJ\:9$%&òǬĤßʡ:9$%&Ɣab #$%&)%*+,-IůLȆ/0012*%+2&&+$3+ŹIɉʸ/0012*%+2&&+$3+ôƘɤ{I9$%&G HcʑȍŊ9$%&ßɲÓ¬Ű::ŹʍʠßSTƘ^ŌƞŸ{'2&E1$+&ǟǵßST 0,$62&'+%&+2%+$@:9$%&¨ǙòǬĤwx/0012*%+2&&+$3+:'2&E1$+&9$%&ôI9$%&«¬ #$%&)%*+,-:Źʍ«¬Iɤ{^ŌÉÊȋȌI g9$%&ßǍnj:ŹʍƘȆwx9$%&ʎʏß«¬ ŹI|əƲĴʟĖwƱɵ:ÉÊ9$%&ß«¬Iȑ|:ÁÂ|::òĤɛŗʼôß «¬.ʽ§Ƙ ` ÖĘĄäÁŃƃD0,2&EȦmȾȿ:ȋƘ|ə#$%&)%*+,-Oǯ:ŹʍQRŲĝĞIƂƨ^zţ 9$%&:ʡ.ʾɎʡƘ|əĒäʿĴSTGH.nƦòǬĤ«¬ƞŸąØ:ôI ƔƠ{9$%&ɲȾß«¬:ŹʍƘŷƠƼƽƾȱƠÒwx#$%&)%*+,-ßȾȿĴOǯIʢȼȆĄǍ njwx9$%&:ŹʍIĤƙ«¬ƞx9$%&ůL|::ŹʍŲÔmĝĞIŷx#$%&)%*+,-Ɣəˀ ŲwxėĘƘǬĤIĤƙwx9$%&ˀŲwxėĘKʹĔůñ\GH:ŚƙIŷȒ:ȋȌƠə #$%&'( #$%&)%*+,-./0012*%+2&&+$3+ £$,'2&
Beans, Bean Factory FlApplicationContext 生。这种潜在地推迟一些配置错误可见性的行为正是 ApplicationContext默认预实例化 singleton bean的原因。以前期的时间和内存为代价在 beans真正需要之前创建它们,你就可以在 ApplicationContext创建的时候找出配置错误,而不是在后来。如果你愿意,你也可以覆盖这种 默认的行为,设置这些 singleton bean为1azy-1oad(不是预实例化的) 几个例子 首先,一个使用 BeanFactory以及基于 setter方法的依赖注射。下面是一个定义了一些bean的 mlBeanFactory配置文件的一小部分。接下去是正式的bean的代码,演示了正确的 setter方法声明。 <bean id="exampleBean class="examples. ExampleBean> <property name="beanOne ><ref bean="anotherExampleBean"/></property> <property name=bean Two ><ref bean="yetAnotherBean"/></property> <property name=integer Property ><value>1</value></property) <bean id="another ExampleBean class=examples. AnotherBean/> <bean id="yetAnotherBean"class="examples. YetAnotherBean/> public class ExampleBean I private Another Bean beanOne private YetAnother Bean beanTwo private int public void setBeanOne (AnotherBean beanOne)i this bean One bean One public void setBeanTwo(YetAnotherBean beanTwo)I this. beanTwo beanTwo: public void setIntegerProperty (int i) i this. i =1 正如你所看到的一样, setter方法被声明以符合ⅫM文件中指定的属性。(XML文件中的属性,直接对 应着 Root BeanDefinition中的 PropertyValues对象) 接着是一个使用 IoC type3(基于构造函数的依赖注射)的 BeanFactory。下面是XML配置中的一段,指 定了构造函数参数以及展示构造函数的代码 <bean id="exampleBean class="examples. ExampleBean> <constructor-argxref bean="anotherExampleBean"/>/constructor-arg> <constructor-arg>ref bean yetAnotherBean/></constructor-arg> <constructor-arg>value>1</value></constructor-arg) C/bean> <bean id="anotherExampleBean class=examples. AnotherBean/> <bean id="yetAnotherBean"class="examples. YetAnotherBean/ ublic class ExampleBean I private Another Bean beanOne private YetAnother Bean beanTwo private int public ExampleBean(AnotherBean anotherBean, YetAnotherBean yetAnotherBean, int i)t this bean One anotherBean Version 1.1
gƘŷĂƲĴˁ˂wŸPTĝĞäɝH:Ⱦ{/0012*%+2&&+$3+ʁų˃ÓðĨ'2&E1$+& 9$%&:ɖɐƘÁj:Źr.Åţ®˄9$%&'ɲȾąØq«¬|ǎIĄƠäÁ /0012*%+2&&+$3+«¬:ŹʍʮŲPTĝĞIyz{ȼ¨ƘĤƙĄ˅ƼIĄƔäÁˆˇŷĂ ʁų:ISTŷŸ'2&E1$+& 9$%&1%ž-61%@òz{˃ÓðĨ:ôƘ ǃxðpË ˈɄIwx #$%&)%*+,-ÁÂ7Ō'$++$,[\: ľƘŗÌ{wxabmwŸ9$%&: śB1#$%&)%*+,- PTņ:wōƷIJƘkŗʼ{ȾÜ:9$%&:®¯IˉǢmȾȿ:'$++$,[\þÿƘ ɭ9$%& 2@ɦȲ$3%B01$#$%&Ȳ *1%''ɦȲ$3%B01$'3%B01$#$%&Ȳɮ ɭ0,0$,+- &%B$ɦȲ9$%& &$Ȳɮɭ,$5 9$%&ɦȲ%&+$,3%B01$#$%&Ȳɮɭ0,0$,+-ɮ ɭ0,0$,+- &%B$ɦȲ9$%&ÝȲɮɭ,$5 9$%&ɦȲ-$+/&+$,#$%&Ȳɮɭ0,0$,+-ɮ ɭ0,0$,+- &%B$ɦȲ2&+$E$,,0$,+-Ȳɮɭ%1$ɮɭ%1$ɮɭ0,0$,+-ɮ ɭ9$%&ɮ ɭ9$%& 2@ɦȲ%&+$,3%B01$#$%&Ȳ *1%''ɦȲ$3%B01$'/&+$,#$%&Ȳɮ ɭ9$%& 2@ɦȲ-$+/&+$,#$%&Ȳ *1%''ɦȲ$3%B01$'ɰ$+/&+$,#$%&Ȳɮ 0912* *1%'' 3%B01$#$%& ɨ 0,2%+$ /&+$,#$%& 9$%& &$ɧ 0,2%+$ ɰ$+/&+$,#$%& 9$%&Ýɧ 0,2%+$ 2&+ 2ɧ 0912* 2@ '$+#$%& &$/&+$,#$%& 9$%& &$ ɨ +2'9$%& &$ ɦ 9$%& &$ɧ ɩ 0912* 2@ '$+#$%&Ýɰ$+/&+$,#$%& 9$%&Ý ɨ +2'9$%&Ý ɦ 9$%&Ýɧ ɩ 0912* 2@ '$+&+$E$,,0$,+-2&+ 2 ɨ +2'2 ɦ 2ɧ ɩ ɩ ȾĤĄŖʶŊ:wȒI'$++$,[\ßþÿÁ?Jś²ņlja:GHƘòś²ņ:GHIȍk^ ªƾĪ+#$%&4$52&2+2&:,0$,+-£%1$'^_ô kƾ{wx +-0$"ò7ŌVWXY: ľô:#$%&)%*+,-ƘŗÌ{ś²PT:wˊIlj amVWXYZYÁÂĻǢVWXY:®¯ȱ ɭ9$%& 2@ɦȲ$3%B01$#$%&Ȳ *1%''ɦȲ$3%B01$'3%B01$#$%&Ȳɮ ɭ*&'+,*+,6%,Eɮɭ,$5 9$%&ɦȲ%&+$,3%B01$#$%&Ȳɮɭ*&'+,*+,6%,Eɮ ɭ*&'+,*+,6%,Eɮɭ,$5 9$%&ɦȲ-$+/&+$,#$%&Ȳɮɭ*&'+,*+,6%,Eɮ ɭ*&'+,*+,6%,Eɮɭ%1$ɮɭ%1$ɮɭ*&'+,*+,6%,Eɮ ɭ9$%&ɮ ɭ9$%& 2@ɦȲ%&+$,3%B01$#$%&Ȳ *1%''ɦȲ$3%B01$'/&+$,#$%&Ȳɮ ɭ9$%& 2@ɦȲ-$+/&+$,#$%&Ȳ *1%''ɦȲ$3%B01$'ɰ$+/&+$,#$%&Ȳɮ 0912* *1%'' 3%B01$#$%& ɨ 0,2%+$ /&+$,#$%& 9$%& &$ɧ 0,2%+$ ɰ$+/&+$,#$%& 9$%&Ýɧ 0,2%+$ 2&+ 2ɧ 0912* 3%B01$#$%&/&+$,#$%& %&+$,#$%&( ɰ$+/&+$,#$%& -$+/&+$,#$%&( 2&+ 2 ɨ +2'9$%& &$ ɦ %&+$,#$%&ɧ #$%&'( #$%&)%*+,-./0012*%+2&&+$3+ £$,'2&