简介
Spring自动化装配bean的具体应用,属于DI(依赖注入)里面的具体实现和编程范畴。
1.Spring配置的可选方案
- 在XML中进行显式的配置;
- 在Java中进行显式的配置;
- 隐式的bean发现机制和自动装配;
推荐尽可能使用自动装配机制,显示装配越少越好,在必须显示装配时建议用比XML更强大且类型安全的JavaConfig注解,最后才用XML,所以本篇基本不谈第三点(自己用起来都觉得有点麻烦)
2.自动化装配bean
Spring从两个角度实现自动化装配:
- 组件扫描(component scanning):Spring会自动发现应用上下文中所创建的bean
- 自动装配(autowiring):Spring自动满足bean之间的依赖
2.1创建可被发现的bean
首先定义一个接口,只有一个printMessage()方法
package helloWorld;
public interface Message {
void printMessage();
}
然后创建一个它的实现
package helloWorld;
import org.springframework.stereotype.Component;
@Component
public class MessagePrinter implements Message{
@Override
public void printMessage(){
System.out.println("hello world!");
}
}
Component翻译过来就是组件的意思,此时的@Component注解表明该类会作为组件类,并告知Spring要为MessagePrinter类创建bean。
由于组件扫描默认是不启用的,所以还要有一个显式的配置类,从而让容器去寻找@Component注解的类,@ComponentScan默认会扫描与配置类相同的包
package helloWorld;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
@Configuration
@ComponentScan
public class HelloWorldConfig {
}
2.1.1设置组件扫瞄的基础包
@ComponentScan到目前为止还没有设置任何属性,这意味着,他会按照默认设置将配置类所在的包作为基础包(basepackage)来扫描组件。有时我们想将所有的配置类都提取出来放在单独的包中,使其与其他的应用代码区分开来,如果是这样的话,默认的基础包就不能满足要求了。
此时我们需要在@ComponentScan的value属性中指明包的名称
@Configuration
@ComponentScan("helloWorld")
public class HelloWorldConfig {
}
如果有多个基础包,那么可以通过basePackages属性设置
@Configuration
@ComponentScan(basePackages = {"a","b",...})
public class HelloWorldConfig {
}
但是这样做是类型不安全的(not type safe),如果你重构代码的话,那么所制定的基础包很有可能会发生错误。
为此将包设置为简单的String类型之外,@ComponentScan还提供了另一种方法,那就是将其指定为包中所包含的类或者接口,这些类所在的包将会作为组件扫瞄的基础包,重构如下
@Configuration
@ComponentScan(basePackageClasses = {MessagePrinter.class, MessageMain.class})
public class HelloWorldConfig {
}
其实更加保险点的方法可以考虑在包中创建一个用来进行扫描的空标记接口(marker interface)。通过标记接口方式,你依然能够保持对重构友好的接口引用,但可以避免引用任何实际的应用程序代码。
2.1.2为组件扫描的bean命名
Spring应用上下文中所有的bean都会给定一个ID,若未制定默认ID为类名并将第一个字母变为小写。例如将上面的MessagePrinter类设置ID后如下所示:
package helloWorld;
import org.springframework.stereotype.Component;
@Component("printer")
public class MessagePrinter implements Message{
@Override
public void printMessage(){
System.out.println("hello world!");
}
}
2.2通过为bean添加@Autowired注解实现自动装配
package helloWorld;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
@Component
public class MessageMain {
private MessagePrinter mess;
@Autowired
public MessageMain(MessagePrinter mess) {
this.mess = mess;
}
public void print() {
mess.printMessage();
}
}
自动装配就是让Spring自动满足bean依赖的一种方法,在满足依赖的过程中,会在Spring上下文中寻找匹配某个bean需求的其他bean。为了声明要进行自动装配,我们可以借助Spring的@Autowired注解。