装配Bean方式
一、装配Bean方式汇总
Spring容器负责创建Bean并通过DI来协调对象间关系。
Bean如何进行装配,spring提供了下面三种基本方式+混合方式。
很多场景可以通过组件扫描和自动装配方式实现自动化装配Bean,但是,需要将第三方库的组件装配到应用中,是没有办法在它的类上添加@Component和@Autowired注解。此时只能采用显示装配Bean:Java显式和XML显式。
二、自动化装配Bean
实现自动化装配Bean,主要有两步骤:组件扫描和自动装配。
组件扫描(component scanning):Spring 会自动发现应用上下文中所创建的 bean【默认不开启】。
自动装配(autowiring):让Spring自动满足bean依赖的一种方法,在满足依赖的过程中,会在 Spring 应用上下文中寻找匹配某个 bean 需求的其他 bean【可使用@Autowired 注解实现】。
2.1 组件扫描
Spring默认情况下,组件扫描是不启用的。我们还需要显式配置一下 Spring,从而命令它去寻找带有@Component、@Service注解的类,并为其创建bean。
@Configuration --配置spring容器(应用上下文),将该类注入成Bean对象
@ComponentScan ----在spring中启用组件扫描
public class scanConfig {
}
—由于没有其他配置信息,那么@ComponentScan会默认扫描scanConfig类所在的包及包下的所有子包,查找带@Component、@Service注解的类。
2.2 自动装配
可以利用@Autowired注解帮忙寻找Bean及依赖的Bean信息。
2.3 具体实例讲解
下面以实际例子讲述@Component、@Service注解的类,怎样将Bean对象扫描到IOC容器,并且怎么装配使用。
—接口
public interface AutoBeanDesc {
public String way();
}
—实现子类(@Component)
@Component
public class DescImpl implements AutoBeanDesc{
@Override
public String way() {
return "DescImpl way .";
}
}
—注解类(@Component)
@Component
public class AutowiConstructorDesc {
private AutoBeanDesc autoBeanDesc;
@Autowired //构造器上加注解
public AutowiConstructorDesc(AutoBeanDesc autoBeanDesc){
this.autoBeanDesc = autoBeanDesc;
}
public void desc1(){
System.out.println(autoBeanDesc.way()+"AutowiConstructorDesc");
}
}
—注解类(@Service)
@Service
public class AutowiSetterDesc {
private AutoBeanDesc autoBeanDesc;
/**
* 将 required 属性设置为false 时,Spring 会尝试执行自动装配,
* 但是如果没有匹配的 bean 的话,Spring 将会让这个 bean 处于未装配的状 态。
*/
@Autowired(required=false) //用在Setter方法
public void setCompactDisc(AutoBeanDesc autoBeanDesc){
this.autoBeanDesc = autoBeanDesc;
}
public void desc1(){
System.out.println(autoBeanDesc.way()+"AutowiSetterDesc");
}
}
@Configuration
//@ComponentScan(basePackages ={"com.wwy.JavaBean.*"})
@ComponentScan(basePackages ={"com.wwy.JavaBean.AutoConfigBean"})
//@ComponentScan(basePackages ={"com.wwy.JavaBean.AutoConfigBean","com.wwy.JavaBean.XmlConfigBean"})
public class BeanConfig {
}
在JavaBean包下,有一个BeanConfig类,这个类没任何信息,@ComponentScan注解是spring启动组件扫描,@Configuration注解将BeanConfig类注入到Bean对象。
—Test验证
@ContextConfiguration(classes = BeanConfig.class) //指定bean注入的配置文件
//使用标准的JUnit @RunWith注释来告诉JUnit使用Spring TestRunner
@RunWith(SpringJUnit4ClassRunner.class)
public class test {
@Autowired
private AutoBeanDesc autoBeanDesc;
@Autowired
AutowiConstructorDesc autowiConstructorDesc;
@Autowired
AutowiSetterDesc autowiSetterDesc;
@Test
public void test() {
System.out.println(autoBeanDesc.way());
autowiConstructorDesc.desc1();
autowiSetterDesc.desc1();
}
}
三、Java显式装配Bean
—接口及实现子类
public interface JavaBeanDesc {
public String way();
}
public class JavaBeanDescImpl implements JavaBeanDesc {
@Override
public String way() {
return "JavaBeanDescImpl way.";
}
}
public class JavaConstructorDesc {
private JavaBeanDesc javaBeanDesc;
public JavaConstructorDesc(JavaBeanDesc javaBeanDesc){
this.javaBeanDesc = javaBeanDesc;
}
public String way(){
return "JavaConstructorDesc "+javaBeanDesc.way();
}
}
—JavaConfig类
@Configuration和@Bean将对应的类注入成Bean对象。
@Configuration //配置spring容器(应用上下文),将该类注入成Bean对象
public class JavaConfig {
@Bean
public JavaBeanDesc getJavaBeanDesc(){
return new JavaBeanDescImpl();
}
@Bean
public JavaConstructorDesc getJavaConstructorDesc(JavaBeanDesc desc){
return new JavaConstructorDesc(desc);
}
}
@Component
public class JavaBeanDescV2 {
@Autowired
JavaBeanDesc javaBeanDesc; //前面已经注入成Bean对象,所以直接装配使用
public String way(){
return "JavaBeanDescV2 "+javaBeanDesc.way();
}
}
—测试方法
@Service
public class JavaBeanService {
@Autowired
JavaBeanDesc javaBeanDesc;
@Autowired
JavaConstructorDesc javaConstructorDesc;
@Autowired
JavaBeanDescV2 javaBeanDescV2;
public void test(){
System.out.println(javaBeanDesc.way());
System.out.println(javaConstructorDesc.way());
System.out.println(javaBeanDescV2.way());
}
}
四、XML显式装配Bean
基于XML装配Bean两种方式:构造器注入、属性注入。对于强依赖,使用构造器注入;对于可选的属性使用属性注入。
4.1 构造器注入
----接口
public interface XmlBeanDesc {
public void way();
}
----实现类
public class XmlDescImpl implements XmlBeanDesc {
@Override
public void way() {
System.out.println("XmlDescImpl way .");
}
}
–这个类将字面量注入到构造器中
public class XmlDescImplV2 implements XmlBeanDesc {
private String title;
private String name;
private List<String> list;
public XmlDescImplV2(String title,String name){
this.title = title;
this.name = name;
}
public XmlDescImplV2(String title,String name,List<String> list){
this.title = title;
this.name = name;
this.list = list;
}
@Override
public void way() {
System.out.println("XmlDescImplV2 way . title:"+title+" name:"+name+
" list:"+ JSON.toJSONString(list));
}
}
—应用的实现类
public class XmlPlayer {
private XmlBeanDesc xmlBeanDesc;
public XmlPlayer(XmlBeanDesc xc){
this.xmlBeanDesc = xc;
}
public void play(){
xmlBeanDesc.way();
}
}
—applicationContent.xml中配置
<!--使用XML装配Bean【使用构造器注入】-->
<!--spirng发现这个Bean元素时,会调用XmlDescImpl的默认构造函数来创建Bean-->
<bean id="xmlDescImplV1" class="com.wwy.JavaBean.XmlConfigBean.XmlDescImpl"/>
<!--spirng发现这个Bean元素时,会调用XmlDescImplV2的重写的构造函数来创建Bean-->
<bean id="xmlDescImplV2" class="com.wwy.JavaBean.XmlConfigBean.XmlDescImplV2">
<constructor-arg value="title:hello"/>
<constructor-arg value="name:wwy"/>
<constructor-arg>
<list>
<value>list1</value>
<value>list2</value>
</list>
</constructor-arg>
</bean>
<!--以构造函数方式注入初始化xmlPlayerBean-->
<bean id="xmlPlayer" class="com.wwy.JavaBean.XmlConfigBean.XmlPlayer">
<constructor-arg ref="xmlDescImplV2"></constructor-arg>
</bean>
—这样的话,测试使用
@Service
public class JavaBeanService {
@Autowired
XmlPlayer xmlPlayer;
@PostConstruct
public void test(){
xmlPlayer.play();
}
}
4.2 (setter)属性注入
public class XmlSetterPlayer {
private XmlBeanDesc xmlBeanDesc;
public void setXmlBeanDesc(XmlBeanDesc xc){ //setter属性方法
this.xmlBeanDesc = xc;
}
public void play(){
xmlBeanDesc.way();
}
}
—applicationContent.xml中配置
<!--使用XML装配Bean【使用属性注入】-->
<bean id="xmlSetterPlayer" class="com.wwy.JavaBean.XmlConfigBean.XmlSetterPlayer">
<property name="xmlBeanDesc" ref="xmlDescImplV2"></property>
</bean>
—这样的话,测试使用
@Service
public class JavaBeanService {
@Autowired
XmlSetterPlayer xmlSetterPlayer;
@PostConstruct
public void test(){
xmlSetterPlayer.play();
}
}
五、混合装配Bean
注意:下面的是参考其他博客的,具体的没尝试过。
(一)多个JavaConfig类进行配置:
在每个配置类上使用@Configuration注解;
在其中一个配置类上使用@Import(AnotherJavaConfigClass.class)即可实现导入;
【也可以在一个统一的JavaConfig类上使用@Import注解导入其他的所有JAVA配置类:@Import(AnotherJavaConfigClass.class, SomeElseJavaConfigClass.class)】
(二)在JavaConfig类中导入在XML中配置的Bean:
1.在Java配置类上增加一个@ImportResource注解:@ImportResource(“classpath:cd-config.xml”)
(三)在XML中导入另一个XML配置文件:
1.在目标XML文件中使用元素:<import resource=“cd-config.xml”
(四)没有一个直接的方法能将JavaConfig类导入到xml文件,间接的,通过声明一个配置累的Bean来导入: