装配方式
使用Spring就是要让Spring帮助我们管理这些Class的实例也就是这些Bean,但是作为开发人员,我们需要告诉Spring哪儿些bean需要装配和怎么装配到一起,Spring提供了三类装配机制:
- 自动化发现和装配Bean。
- 在Java代码中显示配置Bean。
- 在XML里显示配置Bean。
这些方式可以单独使用,也可以配合一起使用。
虽然Spring给了我们很多种方式,但是如果我们滥用的话,我们的代码也会很难维护的,没有一个标准说让我们必须用某种方式,但是我们的一般原则是通用的配置,比如数据库配置等使用XML文件配置进行装配或者在Config的Java代码里进行显式配置,业务对应的Bean使用自动装配让Spring自己扫描和发现。
接下来我们会花四章的篇幅讲解一下,如何使用这三种装配方式,最后我们再讲解一下怎么使用混合方式进行装配,本章就讲解一下Spring自动发现和装配的方式,这也是我们最常用的方式。
自动化装配Bean
我之前写过一篇很简单的装配和注入Bean的例子 ,这个例子写的是人打电话的,现在我们实现一个CD播放器播放音乐的功能,实现这个之前,我们先一点理论知识。
Spring从两个角度实现自动化装配的:
1. 组件扫描: Spring会自动发现上下文中所创建的Bean。
2. 自动装配: Spring会自动满足Bean之间的依赖。
这样的功能你难道不喜欢么,它会最大化的降低我们的显示配置。
例子
pom.xml文件下添加Spring基础依赖:
<properties>
<java.version>1.8</java.version>
<spring.version>4.3.12.RELEASE</spring.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-expression</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context-support</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.8.10</version>
</dependency>
</dependencies>
在java目录下建立一个包,叫soundsystem。
soundsystem包下我们先定义两个接口。
一个是播放器的接口:
public interface MediaPlayer {
void play();
}
一个是CD的接口:
public interface CompactDisc {
void play();
}
写两个实现,并且这两个实现通过注解@Component标识,这样Spring扫描时,才会自动装配这Bean,也就是这个对应类的实现:
播放器的实现
@Component
public class CDPlayer implements MediaPlayer {
private CompactDisc cd;
@Autowired
public CDPlayer(CompactDisc cd) {
this.cd = cd;
}
public void play() {
cd.play();
}
}
播放器的实现我们用的是构造器注入,也就是把CompactDisc通过CDPlayer的构造器注入到CDPlayer里。
实际上有多种方式可以注入,构造器,属性,属性的方法等都可以。
属性的注入:
@Autowired
private CompactDisc cd;
属性方法注入:
@Autowired
public void setCd(CompactDisc cd){
this.cd = cd;
}
属性方法注入不只是Setter方法,任何一个满足@Autowired,并且参数是CompactDisc的都可以实现,只是我们习惯性的放在setter方法上。
一个CD:
@Component
public class SgtPeppers implements CompactDisc {
private String title = "Sgt. Pepper's Lonely Hearts Club Band";
private String artist = "The Beatles";
public void play() {
System.out.println("Playing " + title + " by " + artist);
}
}
到此为止,我们的Bean已经写完了,现在我们需要告诉Spring,我们需要装配这些Bean。
有两种方式,一种是XML声明,一种是Java代码声明。
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:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
<context:component-scan base-package="soundsystem" />
</beans>
写一个Main方法测试我们的代码是否可以正常运行
public class Main {
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("soundsystem.xml");
CompactDisc disc = context.getBean(CompactDisc.class);
disc.play();
}
}
从上面的代码来看,我们没有声明任何Bean,也没有在xml声明任何东西,只是告诉Spring,你需要再soundsystem下寻找Bean然后依赖装配就可以了。
另外一种,是JavaConfig的形式,我们可以新建一个类,然后用注解@Configuration和@ComponentScan标注好就可以了,为了减少篇幅,我们直接在Main这个类上加上这两个注解:
@Configuration
@ComponentScan
public class Main {
public static void main(String[] args) {
ApplicationContext context = new AnnotationConfigApplicationContext(Main.class);
CompactDisc disc = context.getBean(CompactDisc.class);
disc.play();
}
}
执行后同样可以达到我们要的效果。
为组件扫描的Bean命名
有人就要问了,@Component声明的Bean的名称是什么呢,实际上就是类名的第一个字母小写,我们也可以指定Bean的名称,比如@Component(“cd”),那么这个Bean的名称就是cd。
设置扫描的基础包
@ComponentScan默认会扫描标注的类所在的包下以及子包下的所有类,我们的例子值里并没有指定任何包名,所以还是能运行。
有时候,我们会有很多包,为了提高启动速度,我们只想扫描部分包怎么办呢?
当然有办法,@ComponentScan可以指定基础的包,比如@ComponentScan(basePackages = {“abc”, “efg”})这种形式,就可以指定Spring扫描abc和efg包下面的类。
好了,自动扫描和注入的方式就先讲到这,有不妥的地方,欢迎指正,下一篇我们接着讲Java代码装配Bean。