Spring容器负责创建应用程序中的bean,并通过DI来协调这些对象的关系。
Spring提供了三种主要装配bean的机制:
1、在XML中显示配置
2、在Java中进行显式配置
3、隐式的bean发现和自动装配
建议尽可能地使用自动装配机制,显式配置越少越好。当年必须使用显式配置的时候(比如,有些源码不是你来维护的,当你需要为这些代码
配置bean的时候,因为源码可能没有@Component @Configuration 注解),推荐使用 类型安全并且比XML更加强大的JavaConfig
自动化装配Bean:
Spring 从两个角度实现自动化装配bean:
1、组件扫描(Component scanning):Spring会自动发现应用上下文中所创建的bean(该bean带有@Component @Service @Controller @Reposity任意一种注解都可以)
2、自动装配(autowiring):spring自动满足bean之间的依赖(自动注入依赖)
例如以下例子:
目录结构
先看下JavaConfig 上下文配置类:
//@ComponentScan(basePackages={"interfaces","xxx"})中括号里面用逗号隔开,可以指定扫描多个包,
//如果不指定扫描的包,则会默认扫描跟配置类同一个包中的类文件
package config;
import interfaces.MarkIf;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
//@ComponentScan(basePackages="interfaces") 或者@ComponentScan("interfaces")
//@ComponentScan(basePackages={"interfaces"})
@Configuration//该注解对spring容器说我是 配置文件
@ComponentScan(basePackageClasses=MarkIf.class)//该注解表示扫描该类所在包中的所有bean组件
//这种方式比上面使用字符创的方式更好,因为如果代码重构删掉包了就可能造成错误, 当然这种方式我们最好不要使用我们
//有用的bean类,可以在要扫描的包中创建一个标记类方便spring扫描,例如MarkIf.class就是一个空的标记类
public class TestConfig {
}
package interfaces;
/**
* 标记类
* spring java配置类默认扫描与该配置类下面的所有注解的bean,但是项目中
* 我们的bean 往往不会在跟配置类在一个包中,这时我们可以指定扫描的包,如下
* @CompentScan(basePackages={"pack1",pack2}),
* 但是通过字符串指定包名 不够安全,因为如果代码有的包名被移除了就会发生错误,
* 所以spring,提供了@ComponentScan(basePackageClasses={MarkIf.class}),
* 扫描该接口或者该类所在的包 中的所有 注解 生成bean
* @author Administrator
*
*/
public interface MarkIf {
}
创建接口:
package interfaces;
public interface DiskInterface {
void play();
}
实现类:
package interfaces;
import org.springframework.stereotype.Component;
@Component//要使用自动准备必须加该注解,spring容器扫描看到该注解,则容器帮我们生成该对象
public class JayDisk implements DiskInterface {
public void play() {
System.out.println("sing song");
}
}
使用Junit4测试:
package interfaces;
import javax.annotation.Resource;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import config.TestConfig;
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes=TestConfig.class)//加载配置文件
public class CDPlayer {
// @Autowired 自动注入接口的实现
// @Qualifier("diskImpl")//因为autowired默认是按照类型注入的,即按照接口的去找实现类注入,如果有多于一个以上的该接口实现spring会报错不懂
//要选哪个实现类注入,使用Qualifier指定具体的bean id,跟autowired配合一起使用,这样即使有多个实现也不会报错了。 spring默认的bean Id为该类的类名
//首字母小写作为bean ID,当然也可以手动指定自己想要的bean id,像这样@Component("dsk")或者@Component(value="dsk")
@Resource(name="dsk")//该注解按照指定的bean id去找到对应的bean进行注入,它等价于@Autowired @Qualifier("dsk")
//尽量使用它代替autowired,因为它是java自带实现的,不是由spring框架实现的,能降低与spring的耦合, resource默认
//按照name=bean id匹配,当根据name找不到的时候,会按照类型去找就跟autowired一样,此时如果有大于一个以上的实现类,也是会报错的
private DiskInterface di;
@Test
public void sing(){
di.play();
}
}