Ⅰ Spring載入配置文件(org.springframework.beans.factory.BeanDefinitionStoreException)
1、首先手動載入Spring配置文件有兩個類,分別是;兩個類的區別。

Ⅱ 二、springboot配置文件
1. 配置文件
  
 Spring Boot使用一個全局的配置文件
  
 application.properties
  
 application.yml
  
 配置文件的作用:修改Spring Boot自動配置的默認值,SpringBoot在底層都給我們自動
  
 配置好。有什麼配置項,可以移步官方文檔
  
 配置文件一般放在src/main/resources目錄或者類路徑/confifig下,當然還有很多位置可
  
 以放,它們會有不同優先順序,後面會講到。
  
 YAML (YAML Ain't Markup Language)
  
 簡單介紹
  
 <!--綁定配置文件處理器,配置文件進行綁定的時候就會有提示-->
  
 <dependency>
  
 <groupId>org.springframework.boot</groupId>
  
 <artifactId>spring-boot-configuration-processor</artifactId>
  
 <optional>true</optional>
  
 </dependency>
  
 <!-- 將應用打包成一個可執行Jar包,直接使用java -jar xxxx的命令來執行 -->
  
 <build>
  
 <plugins>
  
 <plugin>
  
 <groupId>org.springframework.boot</groupId>
  
 <artifactId>spring-boot-maven-plugin</artifactId>
  
 </plugin>
  
 </plugins>
  
 </build>以前的配置文件:大多是xml
  
 .yml是YAML語言的文件,以數據為中 心,比json、xml等更適合做配置文件
  
 全局配置文件的可以對一些默認配置值進行修改
  
 配置實例
  
 xml:
  
 yml:
  
 2. YAML語法
  
 基本語法
  
 K:(空格)V 標識一對鍵值對
  
 以空格的縮進來控制層級關系
  
 只要是左對齊的一列數據,都是同一層級的
  
 屬性和值也是大小寫敏感
  
 實例:
  
 值的寫法
  
 普通的值
  
 k: v 字面量直接來寫,字元串默認不用添加單引號
  
 " " 雙引號 不會轉義字元串裡面的特殊字元;
  
 <server>
  
 <port>8081</port>
  
 </server>
  
 server:
  
 port: 8081
  
 server:
  
 port: 8081
  
 path: /hello // 冒號後面的空格不要拉下' ' 單引號 會轉義字元,特殊字元最終是一個普通的字元串
  
 對象
  
 普通寫法:
  
 行內寫法
  
 frends:{ lastName: zhang,age: 18 }
  
 Map
  
 示例:
  
 maps: {k1: v1,k2: v2}
  
 數組
  
 普通寫法:
  
 pets: // var onj = {pets: ['cat','pig','dog']}
  
 - cat
  
 - pig
  
 - dog
  
 行內寫法
  
 pets:[cat, pig, dog]
  
 配置文件獲取
  
 將配置文件中的每一個值映射到此組件中
  
 1. Persion
  
 name: "wang \n qian" // 輸出:wang 換行 qian
  
 frends:
  
 lastName: zhang
  
 age: 20package com.wrq.boot.bean;
  
 @Component
  
 @ConfigurationProperties(prefix = "persion")
  
 public class Persion {
  
 private String name;
  
 private int age;
  
 private double weight;
  
 private boolean boss;
  
 private Date birth;
  
 private Map<String,Object> maps;
  
 private List<Object> list;
  
 private Dog dog;
  
 此處,這個bean的getter、setter和tostring方法已經省略,千萬不能忽略!
  
 }
  
 @ConfifigurationProperties 意思是:我們類裡面的屬性和配置文件中的屬性做綁定
  
 不使用此註解,可以在bean的屬性添加@value()註解,如下:
  
 @Component
  
 // @ConfigurationProperties(prefix = "persion")
  
 public class Persion {
  
 @value("${persion.name}") // $()讀取配置文件、環境變數中的值
  
 private String name;
  
 @value("#{11*2}") // #{SpEL} 採用表達式
  
 private int age;
  
 @value("true") // 直接賦值
  
 private boolean boos;
  
 }
  
 此處採用@ConfifigurationProperties的方式,@value()和@ConfifigurationProperties的
  
 區別見下方表格。prefifix = "persion" 配置文件中那個下面的屬性來一一映射
  
 @Component 如果想要這個註解起作用,必須放到容器裡面
  
 2. Dog
  
 package com.wrq.boot.bean;
  
 public class Dog { // 用作Persion中的屬性
  
 private String name;
  
 private int age;
  
 此處,這個bean的getter、setter和tostring方法已經省略,千萬不能忽略!
  
 }
  
 3. 配置文件
  
 方式一: application.yml
  
 persion:
  
 name: 王大錘
  
 age: 18
  
 weight: 125
  
 boss: false
  
 birth: 2018/5/5
  
 maps: {k1: v1,k2: v2}
  
 list:
  
 - wangli
  
 - wang
  
 dog:
  
 name: xiaogou
  
 age: 2
方式二: application.propertiespersion.name = 王大錘
  
 persion.age = 18
  
 persion.weight = 125
  
 persion.boss = false
  
 persion.birth = 2018/5/5
  
 persion.maps.k1 = v1
  
 persion.maps.k2 = v2
  
 persion.dog.name = xiaogou
  
 persion.dog.age = 15
  
 4. 測試類:BootApplicationTests
  
 package com.wrq.boot;
  
 @RunWith(SpringRunner.class)
  
 @SpringBootTest
  
 public class BootApplicationTests {
  
 @Autowired
  
 Persion persion;
  
 @Test
  
 public void contextLoads() {
  
 System.out.print(persion);
  
 }
  
 }
  
 5. 運行 BootApplicationTests方法
  
 控制台列印:
  
 application.yml的結果:
  
 Persion{name='王大錘', age=18, weight=125.0, boss=false, birth=Sat May
  
 05 00:00:00 CST 2018, maps={k1=v1, k2=v2}, list=[wangli, wang],
  
 dog=Dog{name='xiaogou', age=2}}
  
 application.properties的結果:
  
 Persion{name='��Ǭ', age=18, weight=125.0, boss=false, birth=Sat
  
 May 05 00:00:00 CST 2018, maps={k2=v2, k1=v1}, list=[wangli, wang],
  
 dog=Dog{name='xiaogou', age=15}}
  
 把Bean中的屬性和配置文件綁定,通過yml文件和properties都可以做到,但是properties
  
 文件出現亂碼。
  
 properties中文讀取亂碼:File->Settings->File Encodings最底部選utf-8、Tranparent打
  
 上勾
  
 註解比較
  
 @value和@ConfifigurationProperties獲取值比較
名詞解釋:
  
 鬆散綁定
  
 last-name和lastName都可以獲取導致,則代表支持鬆散綁定
  
 JSR303@Component
  
 @ConfigurationProperties(prefix = "persion") // 如果使用的是@value注入值
  
 時,無法使用校驗
  
 @Validated // 添加此註解
  
 public class Persion {
  
 @Email // 配置文件書寫的屬性必須是郵箱格式,不符合報錯!
  
 private String name;
  
 }
  
 復雜類型封裝
  
 如果獲取配置文件中map的值時,@value是獲取不到值的
  
 @value("${persion.maps}") // 由於使用的是@value,無法獲取配置文件中的map
  
 private Map<String,Object> maps;
  
 @PropertySource
  
 @PropertySource:載入指定配置文件
  
 @ConfifigurationProperties()默認是從全局配置文件中獲取值,也就是
  
 application.properties這個文件中獲取值。
  
 如果做的配置很多,全局的配置文件就會特別大,為了方便管理。我會創建不同的配置文
  
 件定向管理不同的配置。
  
 如創建persion.properties文件單獨存放persion需要的配置
  
 @PropertySource就是用來導入創建的配置文件
  
 示例:
  
 1. persion.properties
  
 同時把兩個全局的配置中關於Persion的配置都注釋掉persion.name = 王弟弟
  
 persion.age = 18
  
 persion.weight = 125
  
 persion.boss = false
  
 persion.birth = 2018/5/5
  
 persion.maps.k1 = v1
  
 persion.maps.k2 = v2
  
 persion.dog.name = xiaogou
  
 persion.dog.age = 15
  
 2. Persion
  
 package com.wrq.boot.bean;
  
 @Component
  
 @PropertySource(value = {"classpath:persion.properties"})
  
 @ConfigurationProperties(prefix = "persion")
  
 public class Persion {
  
 private String name;
  
 private int age;
  
 private double weight;
  
 private boolean boss;
  
 private Date birth;
  
 private Map<String,Object> maps;
  
 private List<Object> list;
  
 private Dog dog;
  
 此處,這個bean的getter、setter和tostring方法已經省略,千萬不能忽略!
  
 }
  
 這樣運行測試類,控制台就可以列印persion.properties中的數據。
  
 通過下面的註解,把類路徑下的persion.properties載入進來。並且把persion開頭的數
  
 據進行綁定。
  
 @PropertySource(value = {"classpath:persion.properties"})@ConfifigurationProperties(prefifix = "persion")
  
 @ImportResource
  
 @ImportResource:導入Spring的配置文件,讓配置文件生效。
  
 示例:
  
 1. com.wrq.boot.service
  
 package com.wrq.boot.service;
  
 /**
  
 * Created by wangqian on 2019/1/12.
  
 */
  
 public class HelloService {
  
 }
  
 2. resources目錄手動建立bean.xml
  
 <?xml version="1.0" encoding="UTF-8"?>
  
 <beans xmlns="http://www.springframework.org/schema/beans"
  
 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  
 xsi:schemaLocation="http://www.springframework.org/schema/beans
  
 http://www.springframework.org/schema/beans/spring-beans.xsd">
  
 <bean id="helloService" class="com.wrq.boot.service.HelloService">
  
 </bean>
  
 </beans>
  
 3. 測試類
  
 package com.wrq.boot;
  
 @RunWith(SpringRunner.class)
  
 @SpringBootTest
  
 public class BootApplicationTests {
  
 @Autowired
  
 ApplicationContext ioc;@Test
  
 public void testConfig() {
  
 boolean b = ioc.containsBean("helloService");
  
 System.out.print(b);
  
 }
  
 }
  
 試圖通過添加一個Spring的配置文件bean.xml來把HelloService注入進去。
  
 運行測試類結果:false
  
 結果表明IoC容器中並不包含HelloService,即:配置文件bean.xml沒有生效
  
 解決方式
  
 方式一: 主程序中進行配置@ImportResouece註解
  
 package com.wrq.boot;
  
 @ImportResource(locations = {"classpath:bean.xml"}) // 通過此配置是
  
 bean.xml生效
  
 @SpringBootApplication
  
 public class BootApplication {
  
 public static void main(String[] args) {
  
 //應用啟動起來
  
 SpringApplication.run(BootApplication.class, args);
  
 }
  
 }
  
 方法二:通過配置類實現,這種方式也是Spring Boot推薦的
  
 1. com.wrq.boot.confifigpackage com.wrq.boot.config;
  
 /**
  
 * Created by wangqian on 2019/1/12.
  
 */
  
 @Configuration
  
 public class MyConfig {
  
 // 將方法的返回值添加到容器之中,並且容器中這個組件的id就是方法名
  
 @Bean
  
 public HelloService helloService(){
  
 System.out.print("通過@Bean給容器添加組件了..");
  
 return new HelloService();
  
 }
  
 }
  
 @Confifiguration標注這是一個配置類
  
 通過@Bean註解,將方法的返回值添加到容器之中,並且容器中這個組件的id就是方
  
 法名
  
 2. 把主程序類中@ImportResource()配置注釋掉
  
 3. 測試成功,添加了HelloService()組件
  
 3. 配置文件佔位符
  
 隨機數
  
 RandomValuePropertySource:配置文件中可以使用隨機數
  
 ${random.value}
  
 ${random.int}
  
 ${random.long}
  
 ${random.uuid}
  
 ${random.int(10)}
  
 ${random.int[1024,65536]}
  
 屬性配置佔位符可以在配置文件中引用前面配置過的屬性(優先順序前面配置過的這里都能用)
  
 ${app.name:默認值}來指定找不到屬性時的默認值
  
 persion.name = 王弟弟${random.uuid}
  
 persion.age = ${random.int}
  
 persion.dog.name = ${persion.name}_dog
  
 4. Profifile 多環境支持
  
 Profifile是Spring對不同環境提供不同配置功能的支持,可以通過激活、 指定參數等方式
  
 快速切換環境
  
 1. 多Profifile的方式
  
 格式:application-{profifile}.properties/yml
  
 application-dev.properties
  
 application-prod.properties
  
 默認採用application.properties配置文件,如果使用別的,需要激活:
  
 1. application.properties中配置:
  
 # 激活application-dev.properties配置文件
  
 spring.profiles.active=dev
  
 2. application-dev.properties:
  
 server.port=8082
  
 3. 運行BootApplication主程序:
  
 2019-01-12 20:46:09.345 INFO 14404 --- [main]
  
 s.b.c.e.t. : Tomcat started on port(s):
  
 8082 (http)
  
 2. 多文檔塊的方式
  
 除了上方多Profifile的方式來切換環境,也可以通過YAML多文檔塊的方式。示例:
  
 application.yml:
  
 server:
  
 port: 8081
  
 spring:
  
 profiles:
  
 active: dev
  
 ---
  
 spring:
  
 profiles: dev
  
 server:
  
 port: 8083
  
 ---
  
 spring:
  
 profiles: prod
  
 server:
  
 port: 8084
  
 3. 激活指定Profifile
  
 1. application.properties中配置:
  
 # 激活application-dev.properties配置文件
  
 spring.profiles.active=dev
  
 2. application.yml中配置
  
 server:
  
 port: 8081
  
 spring:
  
 profiles:
  
 active: dev
  
 ---
  
 spring:
  
 profiles: dev
  
 server:
  
 port: 80833. 啟動配置-參數
  
 在IDE中,類似於配置tomcat的地方,按下方配置:
  
 Program arguments:--spring.profiles.active=dev
  
 4. 啟動配置-虛擬機
  
 在IDE中,類似於配置tomcat的地方,按下方配置:
  
 VM options:-Dspring-profiles-active=dev
  
 5. 命令行 使用Maven的package命令打包,移動到jar的目錄。
  
 java -jar spring-boot-project-config.jar --spring.profiles.active=dev
  
 5. 配置文件優先順序
  
 GitHub對應項目:boot-confifig-position
  
 優先順序
  
 Spring Boot 啟動會掃描以下位置的application.properties或者 application.yml文件作
  
 為Spring boot的默認配置文件
  
 fifile:./confifig/ (項目根目錄confifig文件夾下的配置文件)
  
 fifile:./ (項目根目下的配置文件)
  
 classpath:/confifig/ (resources目錄confifig文件夾下的配置文件)
  
 classpath:/ (resources目下的配置文件)
  
 以上是按照優先順序從高到低的順序,所有位置的文件都會被載入,高優先順序配置內容會覆
  
 蓋低優先順序配置內容,形成互補配置。
  
 默認配置
  
 我們也可以通過配置spring.confifig.location來改變默認配置。
  
 項目打包後以後,我們可以使用命令行參數的形式,啟動項目的時候來指定配置文件的新
  
 位置;指定配置文件和默認載入的這些配置文件共同起作用,形成互補配置。
  
 1. Maven->package對項目打包2. 把待使用的配置文件放在本地文件夾中,如:D:/application.properties
  
 3. 命令行執行命令
  
 java -jar boot-config-position-xxxxxx.jar --
  
 spring.config.location=D:/application.properties
  
 這樣即使項目上線了,我們也可以通過修改本地的配置文件,使用一行命令即可,極大方
  
 便了運維人員。
  
 6. 外部配置載入順序
  
 Spring Boot 支持多種外部配置方式
  
 可以從以下位置載入配置,優先順序從高到低,高優先順序配置覆蓋低優先順序的,所以配置形
  
 成互補配置。
  
 1. 命令行參數
  
 java -jar boot-config-position-xxxxxx.jar --server.port // 多個配置用空格
  
 隔開
  
 2. 來自java:comp/env的JNDI屬性
  
 3. Java系統屬性(System.getProperties())
  
 4. 操作系統環境變數
  
 5. RandomValuePropertySource配置的random.*屬性值
  
 6. jar包外部的application-{profifile}.properties或application.yml(帶spring.profifile)配
  
 置文件
  
 7. jar包內部的application-{profifile}.properties或application.yml(帶spring.profifile)配
  
 置文件
  
 8. jar包外部的application.properties或application.yml(不帶spring.profifile)配置文件
  
 9. jar包內部的application.properties或application.yml(不帶spring.profifile)配置文件
  
 10. @Confifiguration註解類上的@PropertySource
  
 11. 通過SpringApplication.setDefaultProperties指定的默認屬性
  
 注意:從jar包外向jar包內尋找,優先載入profifile最後載入不帶profifile,更多參考官方文
  
 檔
  
 7. 自動配置原理GitHub對應項目:boot-confifig-autoconfifig
  
 1. 配置文件寫什麼?
  
 配置文件可配置屬性查閱
  
 2. 什麼是註解,如何實現一個註解?
  
 關於註解的機制和相關原理可以移步此篇博客
  
 3. 配置原理解析
  
 我們運行Spring Boot應用是從main方法啟動,在主程序類上有一個
  
 @SpringBootApplication註解。
  
 @SpringBootApplication是一個復合註解,包括@ComponentScan,和
  
 @SpringBootConfifiguration,@EnableAutoConfifiguration。
  
 @SpringBootConfifiguration繼承自@Confifiguration,二者功能也一致,標注當前類
  
 是配置類,並會將當前類內聲明的一個或多個以@Bean註解標記的方法的實例納入到
  
 srping容器中,並且實例名就是方法名。
  
 @EnableAutoConfifiguration的作用啟動自動的配置,@EnableAutoConfifiguration注
  
 解的意思就是SpringBoot根據你添加的jar包來配置你項目的默認配置,比如根據
  
 spring-boot-starter-web ,來判斷你的項目是否需要添加了webmvc和tomcat,就
  
 會自動的幫你配置web項目中所需要的默認配置
  
 @ComponentScan,掃描當前包及其子包下被@Component,@Controller,
  
 @Service,@Repository註解標記的類並納入到spring容器中進行管理。是以前的co
  
 ntext:component-scan(以前使用在xml中使用的標簽,用來掃描包配置的平行支
  
 持)。
  
 @SpringBootApplication註解分析
  
 配置原理視頻講解
  
 4. 自動配置類判斷
  
 在配置文件properties中設置:debug=true 來讓控制台列印自動配置報告,方便的得知
  
 那些配置類生效。
  
 =========================
  
 AUTO-CONFIGURATION REPORT
  
 =========================Positive matches:
  
 -----------------
  
  matched:
  
 - @ConditionalOnClass found required class
  
 'org.springframework.web.servlet.DispatcherServlet';
  
 @ConditionalOnMissingClass did not find unwanted class
  
 (OnClassCondition)
  
 - @ConditionalOnWebApplication (required) found 'session' scope
  
 (OnWebApplicationCondition)
  
 Negative matches:
  
 -----------------
  
 ActiveMQAutoConfiguration:
  
 Did not match:
  
 - @ConditionalOnClass did not find required classes
  
 'javax.jms.ConnectionFactory',
  
 'org.apache.activemq.ActiveMQConnectionFactory' (OnClassCondition)
Ⅲ Spring中讀取bean配置文件的幾種方式
BeanFactory允許InputStream作為構造函數的參數,也可以org.springframework.core.io.Resource介面。下面這個例子是用ClassPathResource作為參數:
Resource resource = new ClassPathResource("bean.xml");
BeanFactory factory = new XmlBeanFactory(resource);
ActionBean action = (ActionBean) factory.getBean("actionBean");    
如果同一個Bean在配置文件有多個bean的定義,則用下面的方法取得所有的對象:
Resource resource = new ClassPathResource("bean.xml");
ListableBeanFactory factory = new XmlBeanFactory(resource);
Map helloBeans = factory.getBeansOfType(ActionBean.class, false, false);
Ⅳ spring 配置文件的bean自動注入失敗的解決方法是什麼
一個Spring注入問題,首先看一個普通Spring Bean,
publicclassFoo{
@Autowired
Barbar;
publicvoiddoSomething(){
bar.doSomething();
}
}
Spring配置一:
<beanid="bar"class="com.test.Bar"></bean>
<beanid="foo"class="com.test.Foo"></bean>
單元測試:
@Test
publicvoidtest_doSomthing(){
ApplicationContextctx=("applicationContext-test.xml");
Foofoo=ctx.getBean(Foo.class);
foo.doSomething();
}
執行上述測試方法,報錯
java.lang.NullPointerException
atcom.test.Foo.doSomething(Foo.java:15)
atcom.test.FooTest.test_doSomthing(FooTest.java:13)
即foo bean中的bar並未注入。
Spring配置二:
<context:component-scanbase-package="com.test"></context:component-scan>
當改成配置二後執行上述單元測試方法便能成功通過。經分析日誌及查看源代碼,發現使用配置二時供裝載了6個bean,如下所示:
DEBUGorg.springframework.beans.factory.support.AbstractBeanDefinitionReader.loadBeanDefinitions(AbstractBeanDefinitionReader.java:216)[applicationContext-test.xml]
DEBUGorg.springframework.context.support.AbstractApplicationContext.obtainFreshBeanFactory(AbstractApplicationContext.java:530)Beanfactoryfororg.springframework.context.support.@3c4e80d3:org.springframework.beans.factory.support.DefaultListableBeanFactory@14cc51c8:definingbeans[bar,foo,org.springframework.context.annotation.,org.springframework.context.annotation.,org.springframework.context.annotation.,org.springframework.context.annotation.];rootoffactoryhierarchy
而使用配置一時只有兩個bean,如下所示:
DEBUGorg.springframework.beans.factory.support.AbstractBeanDefinitionReader.loadBeanDefinitions(AbstractBeanDefinitionReader.java:216)[applicationContext-test.xml]
DEBUGorg.springframework.context.support.AbstractApplicationContext.obtainFreshBeanFactory(AbstractApplicationContext.java:530)Beanfactoryfororg.springframework.context.support.@45ebbb93:org.springframework.beans.factory.support.DefaultListableBeanFactory@18481697:definingbeans[bar,foo];rootoffactoryhierarchy
配置二執行單元測試通過的原因似乎就在於多出的這幾個bean。是不是只要有context:component-scan元素在自動就會有這幾個bean的產生?驗證此假設
在配置一中添加一個無實際意義的context:component-scan元素,如下所示:
<context:component-scanbase-package="com.nonexist"></context:component-scan>
這時執行單元測試能通過,同配置二一樣也會裝載6個bean。那麼這6個bean中到底哪個對注入bar到Foo中起了作用呢?
經過斷點調試發現是 bean起了作用,見輸出日誌:
2015-04-2520:23:09DEBUGorg.springframework.beans.factory.annotation.InjectionMetadata.<init>(InjectionMetadata.java:60)Foundinjectedelementonclass[com.test.Foo]:AutowiredFieldElementforcom.test.Barcom.test.Foo.bar
2015-04-2520:23:09DEBUGorg.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:85)'foo':AutowiredFieldElementforcom.test.Barcom.test.Foo.bar
2015-04-2520:23:09DEBUGorg.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:245)'bar'
2015-04-2520:23:09DEBUGorg.springframework.beans.factory.annotation..registerDependentBeans(.java:424)Autowiringbytypefrombeanname'foo'tobeannamed'bar'
2015-04-2520:23:09DEBUGorg.springframework.beans.factory.support..createBean(.java:458)'foo'
那麼直接在配置一種顯式添加bean呢?如下所示:
<beanid="bar"class="com.tcl.account.service.test.Bar"></bean>
<beanid="foo"class="com.tcl.account.service.test.Foo"></bean>
<beanid=""class="org.springframework.beans.factory.annotation."></bean>
測試會不會通過?會通過。見日誌:
DEBUGorg.springframework.beans.factory.support.AbstractBeanDefinitionReader.loadBeanDefinitions(AbstractBeanDefinitionReader.java:216)[applicationContext-test.xml]
DEBUGorg.springframework.context.support.AbstractApplicationContext.obtainFreshBeanFactory(AbstractApplicationContext.java:530)Beanfactoryfororg.springframework.context.support.@7767d3c1:org.springframework.beans.factory.support.DefaultListableBeanFactory@1924ed52:definingbeans[bar,foo,];rootoffactoryhierarchy
DEBUGorg.springframework.beans.factory.annotation.InjectionMetadata.<init>(InjectionMetadata.java:60)Foundinjectedelementonclass[com.test.Foo]:AutowiredFieldElementforcom.test.Barcom.test.Foo.bar
DEBUGorg.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:85)'foo':AutowiredFieldElementforcom.test.Barcom.test.Foo.bar
DEBUGorg.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:245)'bar'
DEBUGorg.springframework.beans.factory.annotation..registerDependentBeans(.java:424)Autowiringbytypefrombeanname'foo'tobeannamed'bar'
DEBUGorg.springframework.beans.factory.support..createBean(.java:458)'foo'
那麼為什麼在配置文件中添加了context:componet-scan元素後就會自動添加那另外4個bean呢?經過斷點調試發現Spring隱式裝載的4個bean是在如下方法中載入的:
Set<BeanDefinitionHolder>org.springframework.context.annotation.AnnotationConfigUtils.(,Objectsource)
其調用鏈如下所示:

補充一:
若仍用配置一,但單元測試改成如下形式也可以測試通過。
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations={"classpath:/applicationContext-test.xml"})
publicclassFooTest2{
@Autowired
privateFoofoo;
@Test
publicvoidtest_doSomthing(){
foo.doSomething();
}
}
當然一點都不意外,這種方式也會隱式載入那4個bean,見日誌:
DEBUGorg.springframework.beans.factory.support.AbstractBeanDefinitionReader.loadBeanDefinitions(AbstractBeanDefinitionReader.java:216)[classpath:/applicationContext-test.xml]
INFOorg.springframework.context.support.AbstractApplicationContext.prepareRefresh(AbstractApplicationContext.java:500)Refreshingorg.springframework.context.support.GenericApplicationContext@51f3336e:startupdate[SunApr2617:27:35CST2015];rootofcontexthierarchy
DEBUGorg.springframework.context.support.AbstractApplicationContext.obtainFreshBeanFactory(AbstractApplicationContext.java:530)Beanfactoryfororg.springframework.context.support.GenericApplicationContext@51f3336e:org.springframework.beans.factory.support.DefaultListableBeanFactory@4f9d1352:definingbeans[bar,foo,org.springframework.context.annotation.,org.springframework.context.annotation.,org.springframework.context.annotation.,org.springframework.context.annotation.];rootoffactoryhierarchy
補充二,若使用的是@Value,效果同@Autowired,即也需要隱式載入 bean。
publicclassFoo{
@Value("${bar}")
Stringbar;
publicvoiddoSomething(){
System.out.println(bar);
}
}
補充三:
若使用配置一,@PostConstruct標注的方法也不會被執行,但此時需要隱式載入的Spring bean是:org.springframework.context.annotation.
補充四:
在配置一中添加如下配置
<context:annotation-config/>
也會隱式載入那4個bean
Ⅳ Spring有幾種配置方式
Spring有幾種配置方式 ?
   基於XML文件的配置 這種配置文件的格式常用<beans>開頭,然後運用一系列的bean定義和專門的應用配置選項組成。 Spring XML配置方式是使用被Spring命名空間所支持的一些列XML的標簽來實現的。
   基於註解的配置 可以使用註解的方式來代替XML方式的bean元素的配置。這就是組件掃描,常用依賴注入的一些註解有: @Controller @Service @Autowired @RequestMapping @RequestParam @ModelAttribute @Cacheable @CacheFlush @Resource @PostConstruct @PreDestroy @Repository @Scope @SessionAttributes @InitBinder @Required @Qualifier
   組件掃描: 容器會掃描base-package指定的包及其子包下面的所有類,如果該類有一些特定的註解,則納入容器進行管理。
   在類前面添加的一些特定的註解: @Component 通用註解 @Repository 持久層註解 @Service 業務層註解、 @Controller 控制層註解
   基於Java的配置
Ⅵ java中spring框架中的beanConfig.xml配置文件放在哪裡呢
這個不是一定的,隨你自己的意思,你可以放在WEB-INF里,也可以放在classpath下。只需在配置web.xml時指定位置即可。
  
<listener>
   <listener-class>
    org.springframework.web.context.ContextLoaderListener
   </listener-class>
  </listener>
  
 <context-param>
   <param-name>contextConfigLocation</param-name>
   <param-value>
    classpath:beans.xml
   </param-value>
  </context-param>
  
上面就是web.xml中對spring容器的初始化配置,<context-param>中<param-value>中的classpath:beans.xml 即是spring配置文件beans.xml的位置(classpath下,在myeclipse的工程中是src目錄下)