spring从两个角度来实现自动化装配git
public interface CompactDisc { void play(); }
@Component public class SgtPeppers implements CompactDisc { public void play() { ... } }
使用@Component注解代表该类会做为组件类,并告知spring要为此类建立beanweb
@Configuration @ComponentScan public class CDPlayerConfig { }
若没有其余配置,@ComponentScan 默认会扫描与配置类相同的包,即spring将会扫描此包以及此包下的全部子包,查找带有@Component
注解的类,并自动为其建立一个bean.
当使用XML启用组件扫描,可使用spring context命名空间的<context:component-scan base-package="package Name">
元素spring
spring应用上下文中全部的bean都会给定一个ID,上述案例中尽管没有明确为bean命名,可是spring会根据类名为其指定一个ID(将类名的第一个字母变为小写),例如SgtPeppers 指定的ID为sgtPeppers.
也能够为此bean设置不一样的Id安全
@Component("testabc") public class SgtPeppers implements CompactDisc { ...... }
另外一种为bean命名的方式,不使用@Component注解,而使用Java依赖注入规范(Java Dependency Injection)中提供的@Named
注解svg
@Named("abcd") public class SgtPeppers implements CompactDisc { ...... }
@Component与@Named在大多数场景中,它们是能够相互替换的,二者之间有一些细微的差别.
查阅了一些资料,稍微了解了一下两者的细微差别:
@Named JSR-330不提供组合模型,@Component是可组合注解
例:学习
// @Named 不能这样组合的 @Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) @Documented @Named("test") public class Test { ...... } // @Component 能够组合 @Target({ElementType.TYPE}) @Retention(RetentionPolicy.RUNTIME) @Documented @Component("test2") public class Test2 { ...... }
咱们在启用组件扫描时,用到的@ComponentScan
注解,没有为其设置任何属性,那么,它会按照默认规则,以配置类所在的包做为基础包进行组件扫描.ui
若是咱们将配置类 放在单独的包中,是其与其余应用代码分开,此时默认的基础包就不能知足咱们的需求了.this
这时可使用 @ComponentScan
的 value
属性,指明包的名称code
@Configuration @ComponentScan("autoconfig") public class CDPlayerConfig { }
若还想清晰的代表此包为基础包,可使用 basePackages
属性设置component
@Configuration @ComponentScan(basePackages ="autoconfig") public class CDPlayerConfig { }
basePackages
属性是复数形式,因此能够设置扫描多个基础包
@Configuration @ComponentScan(basePackages ={"autoconfig","autoconfig2"}) public class CDPlayerConfig { }
basePackages
属性是类型不安全,好比重构代码后,基础包可能会出现错误.
此时可使用 basePackageClasses
属性, 指定为包中所包含的类或接口.
@Configuration @ComponentScan(basePackageClasses ={CDPlayer.class,DVDPlayer.class}) public class CDPlayerConfig { }
也能够建立一个用来进行扫描的空标记接口,例如:
public interface TestInterface { void play(); } @Component public class A implements TestInterface { ...... } @Component public class B implements TestInterface { ...... } @Configuration @ComponentScan(basePackageClasses ={TestInterface.class}) public class TestConfig { }
使用注解@Autowired
实现自动装配,例如在 构造器
上添加此注解
@Component public class CDPlayer implements MediaPlayer { private CompactDisc cd; @Autowired public CDPlayer(CompactDisc cd) { this.cd = cd; } public void play() { cd.play(); } }
@Autowired
注解不只能使用在 构造器
上,也能使用在 属性的Setter
方法上
@Autowired public void setCompactDisc(CompactDisc cd) { this.cd = cd; }
Setter方法并没有特殊之处,@Autowired
注解能够用在类的任何方法上,假设CDPlayer 类有一个insertDisc()方法,@Autowired
注解也能发挥相同的做用.
@Autowried public void insertDisc(CompactDisc cd) { this.cd = cd; }
无论是构造器,Setter方法,仍是其余方法,spring 都会尝试知足方法参数上所声明的依赖,
若有且只有一个bean
,那么这个bean将会被装配进来.
若没有匹配的bean,那么在应用上下文建立时,spring会抛出一个异常,此时能够设置@Autowried注解的required属性为false
@Autowired(required=false) public CDPlayer(CompactDisc cd) { this.cd = cd; }
若将@Autowried注解的required属性设置为false,spring会尝试执行自动装配,但若是没有匹配的bean的话,spring会让这个bean处于未装配状态,若是未在代码中进行null检查,则可能会出现NullPointerException
若是有多个bean都能知足依赖关系,spring将会抛出一个异常,代表没有明确指定要选择哪一个bean进行自动装配.(自动装配中的歧义性)
@Autowried
是spring特有注解,也可使用Java依赖注入规范提供的 @Inject
, 两者存在细微差异(这两个的细微差异,暂时没查阅到),但多数状况下均可以相互替换.
源码: https://gitee.com/jincheng-921/sp_ch2_2.git
最近在看spring in action(第4版) ,边看边写点笔记,整理一下,仅供本身学习记录使用,案例是从书中的源码筛选出来的.