任何一个成功的应用都是由多个为了实现某个业务目标而相互协作的组件构成的,这些组件必须相互了解、能够相互协作完成工作。
例如,在一个在线购物系统中,订单管理组件需要与产品管理组件以及信用卡认证组件协作;这些组件还需要跟数据库组件协作从而进行数据库读写操作。
在Spring应用中,对象无需自己负责查找或者创建与其关联的其他对象,由容器负责将创建各个对象,并创建各个对象之间的依赖关系。
通俗的来说,Spring就是一个工厂,Bean就是Spring工厂的产品,对于Spring工厂能够生产那些产品,这个取决于领导的决策,也就是配置文件中配置。
因此,对于开发者来说,我们需要关注的只是告诉Spring容器需要创建哪些bean以及如何将各个bean装配到一起。对于Spring来说,它要做的就是根据配置文件来创建Bean实例,并调用Bean实例的方法完成“依赖注入”。
Bean的定义
- < beans/>是Sring配置文件的根节点
- 一个< beans/>节点里面可以有多个节点
在定义Bean的时候,通常要指定两个属性:id和class。其中id用来指明bean的标识符,这个标识符具有唯一性,Spring对bean的管理以及bean之间这种依赖关系都需要这个属性;而class指明该bean的具体实现类,这里不能是接口(可以是接口实现类)全路径包名.类名。 -
//一个Bean的配置 <bean id="bean" class="实现类" />
或者
@Component("bean") public class Bean { ... }
当我们用XML配置了这个bean的时候,该bean实现类中必须有一个无参构造器,故Spring底层相当于调用了如下代码:
bean = new 实现类();
如果在bean的配置文件中,通过构造注入如:
<bean id="bean" class="实现类" /> <constructor-arg value="bean"/> </bean>
那么Spring相当于调用了
Bean bean = new 实现类("bean");
Spring的配置方法
Spring容器负责创建应用中的bean,并通过DI维护这些bean之间的协作关系。作为开发人员,你应该负责告诉Spring容器需要创建哪些bean以及如何将各个bean装配到一起。Spring提供三种装配bean的方式:
- 基于XML文件的显式装配
- 基于Java文件的显式装配
- 隐式bean发现机制和自动装配
-
绝大多数情况下,开发人员可以根据个人品味选择这三种装配方式中的一种。Spring也支持在同一个项目中混合使用不同的装配方式。
《Spring实战》的建议是:尽可能使用自动装配,越少写显式的配置文件越好;当你必须使用显式配置时(例如,你要配置一个bean,但是该bean的源码不是由你维护),尽可能使用类型安全、功能更强大的基于Java文件的装配方式;最后,在某些情况下只有XML文件中才又你需要使用的名字空间时,再选择使用基于XML文件的装配方式。
自动装配Bean
Spring通过两个角度来实现自动装配:
- 组件扫描,Spring会自动发现应用上下文中所创建的bean
- 自动装配,Spring自动满足bean之间的依赖
-
《Spring实战》中用了一个例子来说明,假设你需要实现一个音响系统,该系统中包含CDPlayer和CompactDisc两个组件,Spring将自动发现这两个bean,并将CompactDisc的引用注入到CDPlayer中。
首先创建CD的概念——CompactDisc接口,如下所示:
package soundsystem; /** * @author 李智 * @date 2017/5/9 */ public interface CompactDisc { void play(); }
CompactDisc接口的作用是将CDPlayer与具体的CD实现解耦合,即面向接口编程。这里还需定义一个具体的CD实现,如下所示:
package soundsystem; import org.springframework.stereotype.Component; /** * @author 李智 * @date 2017/5/9 */ @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 +