Bean的注入
在Spring Framework中,Bean的注入方式主要有以下两种形式:
- 构造器注入
- SET注入
1. 构造器注入
依赖信息见Spring Beans初始化相关章节的依赖信息
首先编写一个Service,如下:
public class ConstructorClientService {
private String name;
private ClientService clientService;
public ConstructorClientService(String name, ClientService clientService) {
this.name = name;
this.clientService = clientService;
}
public String getName() {
return name;
}
public ClientService getClientService() {
return clientService;
}
}
public class ClientService {}
以XML为例,初始化该对象及其依赖关系,META-INF/applicationContext.xml文件内容如下:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
https://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="service" class="com.vielat.springframework.bean.service.ConstructorClientService">
<constructor-arg name="name" value="Michael" />
<constructor-arg name="clientService">
<null/>
</constructor-arg>
</bean>
</beans>
上述配置中,ConstructorClientService构造器中有两个参数,一个是普通字符串,一个是对象类型,通过设置constructor-arg参数,然后可以进行注入,上述对象类型直接设置为
测试类如下:
@Test
public void testConstructorInitializing() {
ApplicationContext ac = new ClassPathXmlApplicationContext("META-INF/applicationContext.xml");
ConstructorClientService clientService = ac.getBean("service", ConstructorClientService.class);
System.out.println(clientService);
System.out.println(clientService.getName() +" -->" + clientService.getClientService());
}
若想为对象类型赋值,需要使用如下形式:
<bean id="service" class="com.vielat.springframework.bean.service.ConstructorClientService">
<constructor-arg name="name" value="Michael" />
<constructor-arg name="clientService" ref="clientService">
<!--<null/>-->
</constructor-arg>
</bean>
<bean id="clientService" class="com.vielat.springframework.bean.service.ClientService" />
也可以使用下标的方式指定需要注入的值,如下:
<bean id="service" class="com.vielat.springframework.bean.service.ConstructorClientService">
<!--<constructor-arg name="name" value="Michael" />
<constructor-arg name="clientService" ref="clientService">
<!–<null/>–>
</constructor-arg>-->
<constructor-arg index="0" value="Michael" />
<constructor-arg index="1" ref="clientService" />
</bean>
使用类型指定需要注入的值,如下:
<bean id="service" class="com.vielat.springframework.bean.service.ConstructorClientService">
<!--<constructor-arg name="name" value="Michael" />
<constructor-arg name="clientService" ref="clientService">
<!–<null/>–>
</constructor-arg>-->
<!-- <constructor-arg index="0" value="Michael" />
<constructor-arg index="1" ref="clientService" />-->
<constructor-arg type="String" value="Michael" />
<constructor-arg type="com.vielat.springframework.bean.service.ClientService" ref="clientService" />
</bean>
若存在多个相同类型时无法注入
c命名空间的简化写法此处略,详细信息见Spring Beans初始化相关章节。
2. SET注入
在Spring Framework中,除了构造器注入外,还有一种使用SET方式的注入。
为简化代码,在此引入lombok相关插件,插件安装成功后,新增依赖信息如下:
<properties>
...
<lombok.version>1.18.22</lombok.version>
</properties>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>${lombok.version}</version>
</dependency>
新增Service类,如下:
@Data
public class AdvancedClientService {
private String name;
private Integer age;
private Properties props;
private List<String> hobbies;
private Map<String,Object> map;
private Set<String> emails;
private ClientService clientService;
}
在该对象中,定义了多种不同类型的属性值,包括普通字符、int、Properties、集合、Map及对象等,若要为相应属性值赋值,XML需要使用如下配置的方式:
<bean id="advancedClientService" class="com.vielat.springframework.bean.service.AdvancedClientService">
<property name="name" value="Michael"/>
<property name="age" value="18"/>
<property name="props">
<props>
<prop key="username">root</prop>
<prop key="password">root</prop>
</props>
</property>
<property name="hobbies">
<list>
<value>Reading</value>
<value>Writing</value>
</list>
</property>
<property name="map">
<map>
<entry key="name" value="Michael"/>
<entry key="age" value="18" />
</map>
</property>
<property name="emails">
<set>
<value>aaa@163.com</value>
<value>bbb@qq.com</value>
</set>
</property>
<property name="clientService">
<ref bean="clientService" />
</property>
</bean>
<bean id="clientService" class="com.vielat.springframework.bean.service.ClientService" />
测试类如下:
@Test
public void testInjection() {
ApplicationContext ac = new ClassPathXmlApplicationContext("META-INF/applicationContext.xml");
System.out.println(ac.getBean("advancedClientService"));
}
执行结果如下:
AdvancedClientService(name=Michael, age=18, props={password=root, username=root}, hobbies=[Reading, Writing], map={name=Michael, age=18}, emails=[aaa@163.com, bbb@qq.com], clientService=com.vielat.springframework.bean.service.ClientService@1cab0bfb)
Process finished with exit code 0
从上述执行结果可以看出,对于普通属性,如字符或Integer等,Spring Framework会根据具体对象类型非常完美的进行类型转换,这块属于类型转换的范畴,后续章节会进行相应的介绍,此处略。
针对Properties属性的设值,除上述
<property name="props">
<!--<props>
<prop key="username">root</prop>
<prop key="password">root</prop>
</props>-->
<value>
username=root
password=root
</value>
</property>
上述配置在value
属性中的信息,会使用JavaBeans
的PropertyEditor
机制,将字符串转换为相应的Properties
实例。
对象应用的赋值可以简化为如下方式:
<!--<property name="clientService">
<ref bean="clientService" />
</property>-->
<property name="clientService" ref="clientService" />
同样,上述property属性也可以使用p命名空间进行简写,如下:
<bean id="advancedClientService" class="com.vielat.springframework.bean.service.AdvancedClientService" p:name="Michael">
<!--<property name="name" value="Michael"/>-->
<property name="age" value="18"/>
...
</bean>