Spring从两个角度实现自动化装配:
1.组件扫描:Spring会自动发现引用上下文所创建的bean
2.自动装配:Spring自动满足bean之间的依赖
注:组件扫描和自动装配组合在一起可以发挥强大威力,能够将显示配置降低到最少
一、创建可被识别的bean
通过案例来具体讲解怎么创建可被识别的bean:
1.定义一个接口
package lm.practice.bean; /** * Created by Administrator on 2017/4/17. */ /** * 唱片接口 */ public interface CompactDisc { void play(); }
2.实现接口
package lm.practice.bean.impl; import lm.practice.bean.CompactDisc; import org.springframework.stereotype.Component; /** * Created by Administrator on 2017/4/17. */ /** * 唱片接口的实现类: * 带有@Component注解的CompactDisc的实现类 * @Component: 这个注解表示该类将作为组件类,告诉Spring要为这个类创建bean * 组件扫描默认是不启用的,所以需要显示配置一下Spring,命令它去寻找 * 带有该注解的类,并为其创建bean * 启动组件扫描的两种方式: * 1.注解@ComponentScan 表示启用了组件扫描 * 2.xml配置 */ @Component public class CompactDiscImpl implements CompactDisc { private String title="Sgt. Papper's Lonely Heartsub Band"; private String artist="The Beatles"; public void play() { System.out.println("Playing "+title+" by " +artist); } }
注意:@Component注解表示该类是一个组件类,告诉Spring要为该类创建bean
由于组件扫描默认是不启用的,所以需要显示配置Spring,命令它去寻找带有@Component注解的类,并且为该类创建bean,组件扫描的两种方式:
(一)注解法
import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; /** * Created by Administrator on 2017/4/17. */ /*** 使用注解的方式启用组件扫描 * @Configuration: 这个注解表示该类是一个配置类, * 该类应该包含在Spring应用上下文中如何创建bean的细节*/@Configuration@ComponentScanpublic class CDPlayerConfig {}
(二)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"> <!--xml方式启用组件扫描--> <context:component-scan base-package="lm.practice.*"/> </beans>
base-package中指定扫描范围。
3.测试类
import lm.practice.bean.CDPlayerConfig; import lm.practice.bean.CompactDisc; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; import static org.junit.Assert.assertNotNull; /** * Created by Administrator on 2017/4/17. */ /** * 注释: * 1.SpringJUnit4ClassRunner:以便在测试开始的时候自动创建Spring的应用上下文 * 2.注解@ContextConfiguration告诉需要在CDPlayerConfig中加载配置,因为CDPlayerConfig类中包含了@ComponentScan, * 因此,最终的应用上下文中应该包含CompactDisc的bean * 3.@Autowired注解以便于将CompactDiscbean注入到测试代码中 * */ @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(classes = CDPlayerConfig.class) //@ContextConfiguration(locations = "classpath:spring-component-scan.xml") public class CDPlayerTest { @Autowired private CompactDisc cd; @Test public void test(){ assertNotNull(cd); } }
就像注释中说的那样,Spring的SpringJUnit4ClassRunner指明在测试开始的时候自动创建Spring的应用上下文,而注解@ContextConfiguration会告诉它所需要在哪个类中加载配置。
二、为组件扫描的bean命名
Spring应用上下文的bean都会有一个给定了ID,如果没有明确定义ID的话,系统会默认分配一个ID,该ID是对应类的类名首个字母小写,例如使用@Component注解为组件类的CompactDiscImpl的ID,默认为compactDiscImpl。
那么,如果想要自己指定ID名,该怎么做呢?这里有两种方式
1.通过注解@Component指定,形如:@Component("compactDiscImpl")
2.通过java的注入规范(JDI)中提供的注解@Named指定ID,即在组件类上加上注解@Named(“ID”),用于替代@Component(“ID”)注解
例如本例中的注解类,还可以这样写:
//@Component //@Component("ID") @Named("ID") public class CompactDiscImpl implements CompactDisc { private String title="Sgt. Papper's Lonely Heartsub Band"; private String artist="The Beatles"; public void play() { System.out.println("Playing "+title+" by " +artist); } }
三、设置组件扫描的基础包
到现在应用指定,通过注解@Component指定组件类的时候,组件扫描默认是不启用的,要想启用组件扫描,必须在Spring中进行显式配置,可以在xml中启用,也可以通过注解的方式,在XMl中配置的时候,我们可以通过配置base-packages限定扫描的包,而注解方式同样可以。
如果没有为@ComponentScan设置任何属性,那么默认在配置类所在的包作为基础包,在这里可以通过设置注解@ComponentScan的属性指定扫描的包的范围(其他包,或多个包)
1.方法一:设置basePackages属性属性
@ComponentScan(basePackages=“lm.practice.*”)
@ComponentScan(basePackages={“lm.practice.bean”,“lm.practice.services”})
从上面的两个例子可以看出,这种方式直接将你要设置的包罗列在basePackages中即可。
2.方法二:设置注解的basePackageClasses属性
@ComponentScan(basePackageClasses=CDPlayer.class)
@ComponentScan(basePackageClasses={CDPlayer.class,DVDPlayer.class})
从上面的两个例子可以看出,这种方式设置的是basePackageClasses属性,属性值是类,这就表示将会扫描这些类所在的包(也可以是接口)。
注:可以创建进行扫描的空标记接口
四、通过为bean添加注解实现自动装配
1.什么是自动装配
简单的说,自动装配就是让Spring自动满足bean依赖。
2.怎么实现自动装配
为了声明要进行自动装配,需要借助Spring的@Autowired注解。例如CDPlayer类的构造器上添加了@Autowired,表明当Spring创建CDPlayer的bean时,会通过这个构造器来进行实例化并且会传递一个可设置给CompactDisc类型的bean。
@Autowired除了可以用在构造器上,还可以用在Setter方法上,作用相同。
在自动装配bean的时候,如果要装配的bean不存在,那么Spring就会抛出异常,此时可以将@Autowired的required属性设置为false,这样spring会将这个bean处于未装配的状态。
另外,还可以使用@Inject注解代替@Autowired注解。