Ⅰ 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目录下)