spring 中有三种主要方式的bean装配
- 隐士的bean发现机制和自动化配置
- 基于java的显示配置
- 基于xml的显示配置
隐士的bean发现机制和自动化配置
Spring从两个角度来实现自动化装配
组件扫描(component scanning):Spring会自动发现上下文中所创建的bean。
自动装配(autowiring):Spring 自动满足bena之间的依赖。
两者组合使用,能大幅减少你的显示配置。
@Component 注解表明该类是组件类 (这里还有java提供的@Named 两者之间有略微差异,但是大多数场景是可以替换的)
@Configuration 注解表示该类是配置类
@ComponentScan 这个注解是启用组件扫描,默认扫描该类相同包及其子包。
(这里除了使用注解开始Spring组件扫描外,还可以在xml中使用 <context:component -scan base-package="需要扫描的包">,
同时如果你想扫描多个包,就给@ComponentScan传递{"a包","b包"……},如果你还想更小粒度,更加安全的使用扫描时你还可以 这样 @ComponentScan(basePackageClasses={a.class,b.class}) 指定为该包下的类或者接口)
@Autowired 注解将bean注入 (这里@Autowired 和java提供的@Inject有略微的差异,大多场景下两者是可以相互替换的)
package com.mvtech;
public interface CompDisc{
void play{};
}
package com.mvtech;
@Component
public class SgtPeppers implements CompDisc{
private String title ="刘亦菲";
private String artist = "高圆圆";
public void play(){
Sout("我喜欢看"+title+"和"+artist+"的电视剧");
}
}
package com.mvtech;
@Configiuration
@ComponentScan
public class CDConfig{}
通过以上伪代码即可自动将SgtPeppers对象创建到Spring容器中,并给赋予一个默认的id属性值 类名的首字母小写,同学们也可以自己给定只要在@Component或者@Named 中传递一个参数即可 ,可以不用写xml是不是感觉很简洁类呀。
但是如果你还需要测试上面的伪代码仅仅是将对象创建到Spring容器中。如果你需要实现自动装配还需要@Autowired注解
具体伪代码如下
public class Test{
@Autowired
private CompDisc cd;
public video test(){
cd.pla
}
}
这里简述一下自动装配@Autowired 他可以写任何的方法上,Spring会尝试满足方法参数上所声明的依赖,同时@Autowired还可以设置required属性,默认为true 如果找不到对应的bean 将会报错,当设置为false时,如果找不到对应合适的bean将会传递null值;
基于java的显示配置
当你需要注入的对象是第三方的时候,自动配置就不能满足我们的需求了,这时候就需要显示化配置了。
1 如何创建javaConfig 呢? 创建javaConfig的关键在于@Configuration 注解,在一个普通的java类上添加@Configuration注解,这个类就变成了java配置类。
2 目前你有了java配置类,但是并没有bean,那么如何声明简单的Bean呢? @Bean注解,他会将结果返回值注册为Spring应用上下文中的Bean,(注意该bean的ID值为方法名,但是你也可以自己指定 @Bean的name属性的值)
@Bean
public Car getCar(){
return new Car();
}
把这个方法写在javaConfig中,就将一个bean加入到了Spring的容器中。 当我们需要注入的对象是第三方的类库,我们在javaConfig中写一个方法加上@Bean注解,然后在该方法中返回第三方的对象。这样就达到我们的目的了。同时你还可以在该方法内写你任何的需要的逻辑。
带有@Bean注解的方法可以采取任何方法来生产Bean实例(只要java语言通过)。如构造器 、Setter等多种。
基于xml装配bean
在使用xml为Spring装配时候,你需要创建一个xml,并且要以<beans>为根元素。同时还需要声明多个xml模式(XSD文件)如 <beans xmls="http://www.springframework.org/shema/beans"> 等等。
要在xml中声明一个bean 还需要 <bean>元素 <bean id="id值" class="类的全限定类名"> 这里如果不明确ID值,spring会自动分配一个ID值,这个自动分配的ID值是 类的全限定类名#0 这里#0是一个计数形式。#0 #1 #2 所以我们一般需要指定id值,后面也会用到id值。当Spring发现这个<bean>时候 ,他会默认调用class中指定类的默认构造来创建bean。(这里没有javaConfig强大,因为javaConfig可以使用任何方式)
在xml中声明DI时,实际上是有两种方案的 <constructor-arg>元素 和c-命名空间(spring3.0引入),二者区别就是c-命名空间比较简洁易懂,但是有些事情元素可以办到而c-命名空间就办不到了。所以我们详细介绍一下元素方案,c-命名空间不做介绍,想了解的请看spring官方文档。
constructor-arg 为构造注入调用构造器
<bean>元素 <bean id="id值" class="类的全限定类名">
<constructor-arg ref="另一个bean的id属性值" > (bean的注入)
<constructor-arg value="字面量值" > (字面量的注入 )
<constructor-arg > (集合注入 这里list元素还可以换成set元素 区别就是去重 和无序)
<list>
<ref="" >
<ref="" >
或者
<value> 值
<value> 值
</list>
</constructor-arg >
</bean>
property 为get set注入 基本上和 <constructor-arg > 一样 区别就是 property 还有一个 value属性可以用来注入字面量
<bean>元素 <bean id="id值" class="类的全限定类名">
<property name="" ref="另一个bean的id属性值" >
</bean>
以上三种bean的装配都说完了,我们应该优先选择自动装配,其次是javaConfig 再xml 原因已经说过了。但是在实际开发中仅仅使用一种就能完成的项目较少,常常会发生混合配置。我们简述一下导入和混合配置
导入和混合配置
javaConfig 引入另一个javaConfig(或者拆分)使用@import, @import 传入类.class即可。
在javaConfig中引入xml配置 使用@ImportResource(“classpath:xml名称”)
在一个xml中引入另一个xml(或者拆分) 使用 <import resource="x.xml">即可
在xml中引入javaConfig 普通的bean装配就是啦。