2.1 Spring配置的可选方案
在XML中显式配置
在Java中进行显式配置
隐式的bean发现机制和自动装配机制
建议是,尽可能使用隐式的配置,在必须使用显式配置时(比如你没有源代码),最好采用JavaConfig而不是XML
只有想要使用便利的XML命名空间并且在JavaConfig没有同样的实现时,才应该使用XML
JavaConfig相对于XML的直接优势是重构友好,并且构造bean时可以通过Java代码精细控制
2.2 自动化装配Bean
Spring从两个角度实现自动化装配
组件扫描:Spring会自动发现应用上下文中所创建的Bean
自动装配:Spring自动满足bean之间的依赖
@Component用于告知Spring这是一个Bean,需要实例化,具有同样功能的还有@Repository、@Service和@Controller
可使用@ComponentScan注解开启组件扫描,此时Spring会扫描配置类所在的包以及它们的子包
若想更改扫描的包,可以使用value属性(只能指定一个)或者basePackages属性(是一个数组,可以指定多个)指定要扫描的基本包
此外,还可以使用basePackageClasses,该属性是一个Class数组,可以提供多个Class,Spring会以这些Class所在的包作为基本包
可以在需要扫描的包中创建一个空标记接口,并将basePackages设置为这个接口,这样可以保持对重构的友好引用
如果使用XML配置,也可以使用 <context:component-scan base-package=""/>起用组件扫描
Spring能很方便地进行单元测试:
1.创建一个普通类,添加@RunWith(SpringJunit4ClassRunner.class)注解
2.使用@contextConfiguration()提供配置信息,XML使用location属性,JavaConfig使用class属性
3.在测试类内部可以使用@Autowired等注解进行自动装配,之后即可进行单元测试
可以使用@Component注解的value属性为定义的bean命名,也可是使用基于JDI规范所定义的@Name注解来为bean定义名称
可以使用@Autowired注解进行Bean的自动装配,该注解一般用在构造器,属性的set方法上
其实@Autowired能用在类的任何方法上,Spring都会尝试满足方法参数上所声明的依赖,如果只有一个Bean满足条件,那么这个Bean会被装配进来
如果没有匹配的bean,那么应用上下文创建的时候会抛出异常
为了避免异常,可以设置@Autowired的required属性为false,表示允许为空,但此时运行时可能出现空指针异常
如果有多个bean满足依赖关系,Spring也会抛出一个异常,表明没有明确指定bean进行自动装配
可以使用基于JDI的@Inject实现和@Autowired相同的功能
2.3 通过Java代码装配Bean
在进行显式配置时,JavaConfig是更好的方案,它更加强大、类型安全并且对重构友好
JavaConfig不应该包含任何业务逻辑,也不应该侵入到业务逻辑代码之中
一般将JavaConfig置于单独的包中,使它与其他的应用程序逻辑分离开来
相关注解有:@Configuration、@ComponentScan、@Bean、@Scope
注意最好不要自己new进行注入,因为@Bean注解方法所产生的bean默认为单例的,若需要多例的bean,可以利用@scope注解更改
可以使用调用方法进行注入,这要求被注入的bean的方法在同一个JavaConfig中:
@Bean
public Person person(){
return new Person(head());
}
利用方法参数进行注入,可用性强,事实上可以是任何方式产生的bean都可以被注入进来(包括XML的注解扫描的bean,而且可按名称或类型,只要没有歧义即可):
@Bean
public Person person(Head head){
return new Person(head);
}
2.4 通过XML装配Bean
使用<bean>标签声明一个简单的bean
<bean id="minstrel" class="com.hao.ioc.Minstrel">
使用<constructor-arg>标签进行构造器注入,可以利用c命名空间精简配置
<bean id="cdPlayer" class="sound.CDPlayer">
<constructor-arg ref="compactDisc"/>
</bean>
<bean id="cdPlayer" class="sound.CDPlayer" c:cd-red="compactDisc"/>
<bean id="cdPlayer" class="sound.CDPlayer" c:_0-red="compactDisc"/>
<bean id="cdPlayer" class="sound.CDPlayer" c:_-red="compactDisc"/>
还可以将字面值通过构造器注入
<bean id="compactDisc" class="sound.BlankDisk">
<constructor-arg value="..."/>
<constructor-arg value="..."/>
</bean>
<bean id="compactDisc" class="sound.BlankDisk" c:_title="..." c:_artist="..."/>
<bean id="compactDisc" class="sound.BlankDisk" c:_0="..." c:_1="..."/>
装配集合(c命名空间无法做到的)
可以使用<null/>表示null
使用<list>标签表示集合,可用于集合的装配,<set>的用法和<list>同理
<list>
<value>1</value>
<value>2</value>
<value>3</value>
</list>
<list>
<ref bean="1"/>
<ref bean="2"/>
<ref bean="3"/>
</list>
通用的规则:对强依赖使用构造器注入,可选性的依赖使用属性注入
使用<property>标签设置属性或者利用p命名空间
基于util命名空间的<util:list>可以用于构造列表Bean
2.5 导入和混合配置
1.在JavaConfig中引入配置
可使用@Import注解引入其他JavaConfig类的配置
可使用@ImportResource注解引入其他XML配置
可以创建一个更高层的配置类,在这个类上引入其他所需要的JavaConfig类
2.在XML中引入配置
可以使用<import>标签引入其他XML配置
<import resource="classpath:app.xml"/>
可以使用bean标签引入JavaConfig配置
甚至可以使用<context:component-scan>扫描JavaConfig类所在的包,引入这些JavaConfig类的配置
3.常规做法
通常会使用一个跟配置,然后这个配置会将更多的装配类或JavaConfig组合起来
比如,在XML中定义扫描配置类所在的包,然后由配置类进行Bean的配置
2.6 小结
Spring框架的核心是Spring容器
容器负责管理应用程序中组件的生命周期,他会创建组件并保证他们的依赖能够得到满足
Spring装配Bean的三种主要方式:自动化装配、基于JavaConfig的显式配置以及基于XML的显式配置
建议尽可能使用自动化配置,以避免显式配置所带来的维护成本
如果确实需要显式配置的话,应该优先选择基于JavaConfig的配置,它比基于XML的配置更加强大、类型安全并且易于重构