Spring容器负责创建Bean,并通过依赖注入协调这些对象之间的关系。Bean的装配方式即Bean依赖注入。Spring支持多种形式的Bean装配方式,如基于XML的装配,基于注解的装配和自动装配等。
1. 基于XML的Bean装配
基于XML的装配方式有2种,属性setter方法注入和构造方法注入。
setter方法注入
Spring实例化Bean的过程中,Spring会首先调用Bean的默认构造方法来实例化一个Bean对象,然后通过反射的方式调用setter方法注入属性值。所以setter方法注入必须满足2个条件:
- Bean类必须提供一个默认的构造方法。
- Bean类必须为要注入的属性提供对应的setter方法。
在配置文件中,在<bean>元素的子元素<property>中将每个属性注入值。
例:
entity类
package com.ssm.entity;
public class Hello {
private String name;
public void setName(String name) {
this.name = name;
}
public void say() {
System.out.println("hello"+name);
}
}
spring配置文件
<bean id="hello" class="com.ssm.entity.Hello">
<property name="name" value="张三"></property>
</bean>
测试类
public class Test {
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("application.xml");
Hello h = (Hello)context.getBean("hello");
h.say();
}
运行结果:
构造方法注入
Spring使用构造方法注入被依赖的实例,构造方法可以是有参的或者无参的。Spring采用反射的方式,通过使用构造方法来注入,每个参数代表一个依赖。在配置文件中,一个<constructor-arg>元素代表构造方法的一个参数,使用时不区分顺序。避免混淆,可以用index属性指定参数的位置索引(从0开始),另外还可以使用type属性指定参数类型,避免字符串和基本数据类型混淆。
例:
entity类
package com.ssm.entity;
public class AdminInfo {
private int id;
private String name;
private String pwd;
//setter注入id
public void setId(int id) {
this.id = id;
}
//构造方法注入name和pwd
dminInfo(String name, String pwd) {
this.name = name;
this.pwd = pwd;
}
public void print() {
System.out.println(id + "--" + name + "--" + pwd);
}
}
配置文件
<bean id="adminInfo" class="com.ssm.entity.AdminInfo">
<property name="id" value="5"></property>
<constructor-arg name="name" value="admin" index="0" type="String"></constructor-arg>
<constructor-arg name="pwd" value="admin" index="1" type="String"></constructor-arg>
</bean>
测试类
package com.ssm;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import com.ssm.entity.AdminInfo;
public class Test {
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("application.xml");
AdminInfo adminInfo = (AdminInfo)context.getBean("adminInfo");
adminInfo.print();
}
}
运行结果:
2. 基于注解(Annotation)的Bean装配
Spring有一系列的注解:
- @Component
用来描述Spring中的Bean,仅仅表示一个组件(Bean),可以作用在任何层次。使用时只需要标在类上面即可。 - @Repository
用来把Dao层(数据访问层)的类标识为Spring中的Bean。 - @Service
用来把Service层(业务层)标识为Spring中的Bean。 - @Controller
用来把Controller层(控制层)标识为Spring中的Bean。 - @Autowired
用于对Bean的属性变量、setter方法、构造方法进行标注,配合对应的注解处理器完成Bean的自动配置。@Autowired注解默认按照Bean类型进行装配,加上@Qualifier,可直接指定一个Bean实例名称来装配。 - @Resource
相当于@Autowired.区别是:@Resource默认按照Bean实例名称进行装配。它包含name和type属性。name被解析为Bean实例的名称,type被解析为Bean实例的类型,如果指定name,则按照实例名称进行装配,如果指定type,则按照Bean类型进行装配。如果都不指定,则先按Bean实例名称装配,匹配失败后再按Bean类型装配,如果都无法匹配的话,抛出NoSuchBeanDefinitionException - @Qualifier
与@Autowired配合,将默认按Bean类型装配改成默认按Bean实例名称装配,Bean实例名称由@Qualifier的参数指定。
3. 自动装配
Spring的<bean>元素有一个autowire属性,可通过设置autowire属性来自动装配Bean。自动装配就是将一个Bean注入到其他Bean的Property中。
autowire的属性值:
- default
默认值,由<bean>的上级<beans>的default-autowire属性确定。例如<beans default-autowire=“byName">,则<bean>里的autowire=”byName",向上级看齐。 - byName
根据property的name自动装配,如果一个Bean的name和另一个Bean的property的name相同,则自动装配这个Bean到property中。 - byType
根据property的type自动装配,如果一个Bean的type和另一个Bean的property的type相同,则自动装配这个Bean到property中。 - constructor
根据构造参数的数据类型,进行byType模式的自动装配。 - autodetect
如果有默认的构造函数,使用constructor模式,否则使用byType模式。 - no
默认情况下,不使用自动装配,Bean依赖必须通过ref元素定义。