sping的配置方案有三种:
隐式的bean发现机制和自动装配
在xml中显示配置
在java中进行显示配置
尽可能的使用自动装配,显示装配越少越好,如果必须要用显示装配,最好用javaConfig装配。(javaConfig比XML安全)
xml配置
优势:集中配置,代码配置分离更加方便管理
劣势:繁杂,编译期不容易发现错误
javaConfig配置
优势:代码简洁,
劣势:国内xml配置方式比较多,不容易被人接受
一、自动化装配bean
@Component:表明这是一个组件,可以用@Named替代
@ComponentScan:组件扫描
@Configuration:表明这时一个配置类
@Autowired:自动装配组件,可以用@Inject替代
@Named和@Inject都来自java依赖注释规范的,如果想使用这两个注解需要引入依赖:
<!-- java依赖注入文档 -->
<dependency>
<groupId>javax.inject</groupId>
<artifactId>javax.inject</artifactId>
<version>1</version>
</dependency>
1、创建组件
创建4个组件,歌手Singer接口:
/**可以直接用@Component,他会默认给这个bean指定一个id为singer,
* 当然你也可以自己指定id,如@Conponent("singer")如果多个包中有相同名字的类,会不会混淆Bean?bean跟包的存储方式是否相同?
*/
@Component
public interface Singer {
public void sing();
}
周杰伦实现Singer,会sing()
@Component
public class ZhouJL implements Singer {
@Override
public void sing() {
System.out.println("周杰伦 is Singing");
}
}
播放器Player 接口:
@Component
public interface Player {
public void play();
}
CDPlayer播放器实现Player
@Component
public class CDPlayer implements Player{
@Autowired
private Singer singer;
/** 注意: 上面一个@Autowired可以不写,而这个不写会报错。
* 很疑惑?我项目中确实恰恰相反,可能需要配置吧?
*/
@Autowired
public CDPlayer(Singer singer) {
this.singer = singer;
}
@Override
public void play() {
singer.sing();
}
}
2、配置组件
@Configuration
/**
* 1.用@ComponentScan只会扫描当前包下的组件
* 2.用@ComponentScan("com.cs.model.stu")会扫面包com.cs.model.stu下的组件,但是不利于代码重构与维护,
* 当然还可以显示指示:@ComponentScan(basePackages = "com.cs.model.stu")
* 还可以指定多个包路径:@ComponentScan(basePackages = {"com.cs.model.stu","com.cs.model.ss"})
* 3.指示类所在包路径:
* @ComponentScan(basePackageClasses = Singer.class),他会扫描Singer所在包下的所有组件
* @ComponentScan(basePackageClasses = {Singer.class,People.class}),扫描多个类的包路径
*/
@ComponentScan("com.cs.model.stu")
public class SingerConfig {
}
3、测试
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = SingerConfig.class)
public class ZhouJLSingTest {
@Autowired
private Singer singer;
@Autowired
private Player player;
@Test
public void testSing() {
assertNotNull(singer);
}
/*会不会很疑惑?接口调用其方法结果是调用的实现类的方法*/
@Test
public void testPlay() {
player.play();
}
}
测试是可以通过的。结果如下:
周杰伦 is Singing
二、使用java装配bean
1、既然要优先使用自动装配,那为什么为什么要用java显示装配呢?
A:假如有时候需要将第三方库中的组件装配到应用中,这个时候没有办法在第三方库中的类上加@component,因此这时需要显示配置bean。
2、为什么显示装配优先使用javaConfig 而不是 xml配置?
A:java更为强大、类型安全且(java语言的她点)对重构友好
这个很简单,主要是类跟配置文件不一样:
i.需要装配的类不需要加@Component注解
ii.配置文件不再使用@ComponentScan,而是使用@Bean
3、代码格式
Config在一个单独的包中,里面最好只配置bean,不应该有任何的业务逻辑。
使用java装配bean,示例如下:
类只举一个例子:
//这里无需@Component注解
public interface Player {
public void play();
}
public class SingConfig {
//使用@Bean装置bean,给创建的bean赋id使用name属性
@Bean(name = "singer")
public Singer singer() {
return new ZhouJL();
}
@Bean(name = "player")
public Player player() {
//singer()返回的是Singer的Bean,而不是他的对象的引用:@Bean会拦截所有对他的调用
return new CDPlayer(singer());
}
}
测试代码:
@RunWith(SpringJUnit4ClassRunner.class)
//@ContextConfiguration(classes = SingerConfig.class)
@ContextConfiguration(classes = SingConfig.class)
public class ZhouJLSingTest {
@Autowired
private Singer singer;
@Autowired
private Player player;
@Test
public void testSing() {
assertNotNull(singer);
}
@Test
public void testPlay() {
player.play();
}
}
三、使用xml显示装配bean
建议最好使用前两种来装配bean,学习xml只是为了维护项目中的老旧xml。
同样,类不需要任何注解,只需要在xml中配置即可,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"
xmlns:c="http://www.springframework.org/schema/c"
xmlns:p="http://www.springframework.org/schema/p"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
http://www.springframework.org/schema/context">
<bean id="singer" class="com.cs.model.stu.ZhouJL"/>
<!-- <bean id="player" class="com.cs.model.stu.CDPlayer">
<constructor-arg ref="singer"></constructor-arg>
</bean> -->
<bean id="player" class="com.cs.model.stu.CDPlayer"
c:_0-ref="singer"/>
</beans>
注意:
如果一个类需要被引用,这个类最好需要定义一个Id。
用xml定义bean的时候,如果不明确指给定Id,bean会根据类名的全限定名进行命名,例如:
<bean id="singer" class="com.cs.model.stu.ZhouJL"/>
如果不写id=”singer”,bean Id将会是com.cs.model.stu.ZhouJL#0。而在自动配置、javaConfig配置如下:
//如果使用@Component,bean id 默认为player(类名的首字母小写)
@Component("player")
public interface Player {
public void play();
}
public class SingConfig {
//如果不指定name ,则bean id 为方法名。
@Bean(name = "singer")
public Singer singer() {
return new ZhouJL();
}
}
可以看出差别,如果都不指定bean id,则:
如果使用@Component,bean id 默认为类名的首字母小写(player)
用javaConfig,如果不指定name ,则bean id 为方法名
用xml定义bean的时候,如果不明确指给定Id,bean会根据类名的全限定名进行命名
测试代码如下:
package test;
@RunWith(SpringJUnit4ClassRunner.class)
public class ZhouJLSingTest {
AnnotationConfigApplicationContext annotationConfigApplicationContext = new AnnotationConfigApplicationContext("config/sing.xml");
private Singer singer = annotationConfigApplicationContext.getBean(ZhouJL.class);
@Test
public void testSing() {
assertNotNull(singer);
}
}