接上篇文章(二)spring 的依赖注入,您了解多少?,继续聊下依赖注入的类型:setter方法注入、字段注入、方法注入和接口注入,我们逐一介绍各种注入类型。
setter方法注入
先说下它的使用场景,主要应用在多依赖和非强制依赖注入的情景下,使用场景正好跟构造函数注入互补。
setter方法注入模式有自动注入(byName和byType)和手动注入模式(xml资源配置元信息、java注解元信息和api配置元信息)。接下来还是直接上代码,先看下xml的手动注入方式,还是用(一)spring 的依赖注入,您了解多少?文章中的User和UserHodler类代码:
<?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="user" class="*.User">
<property name="id" value="1" />
<property name="name" value="张三" />
</bean>
<bean class="*.UserHolder" >
<property name="user" ref="User" />
</bean>
</beans>
这种方式应用的比较多,再看下另外一种方式,java注解元信息的手动注解方式,还是直接看代码:
public class SetterDIDemo {
public static void main(String[] args) {
// 创建 BeanFactory 容器
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext();
// 注册 Configuration Class(配置类)
applicationContext.register(SetterDIDemo .class);
XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(applicationContext);
String xmlResourcePath = "classpath:/META-INF/di-setter-context.xml";
// 加载 XML 资源,解析并且生成 BeanDefinition
beanDefinitionReader.loadBeanDefinitions(xmlResourcePath);
// 启动 Spring 应用上下文
applicationContext.refresh();
// 依赖查找并且创建 Bean
UserHolder userHolder = applicationContext.getBean(UserHolder.class);
System.out.println(userHolder);
// 显示地关闭 Spring 应用上下文
applicationContext.close();
}
@Bean
public UserHolder userHolder(User user) {
UserHolder userHolder = new UserHolder();
userHolder.setUser(user);
return userHolder;
}
}
跟构造函数的java注解元信息手动注入方式几乎一致,流程也是大致相同:创建beanFactory容器==》注册配置类==》加载xml资源,解析并且生成BeanDefinition ==》启动spring应用上下文==》依赖查找并创建Bean==>最后关闭spring应用上下文。
再看一种比较底层的手动注解方式,即api配置元信息注解方式,还是先直接上代码:
public class ApiSetterDIDemo {
public static void main(String[] args) {
// 创建 BeanFactory 容器
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext();
// 生成 UserHolder 的 BeanDefinition
BeanDefinition userHolderBeanDefinition = createUserHolderBeanDefinition();
// 注册 UserHolder 的 BeanDefinition
applicationContext.registerBeanDefinition("userHolder", userHolderBeanDefinition);
XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(applicationContext);
String xmlResourcePath = "classpath:/META-INF/di-setter-context.xml";
// 加载 XML 资源,解析并且生成 BeanDefinition
beanDefinitionReader.loadBeanDefinitions(xmlResourcePath);
// 启动 Spring 应用上下文
applicationContext.refresh();
// 依赖查找并且创建 Bean
UserHolder userHolder = applicationContext.getBean(UserHolder.class);
System.out.println(userHolder);
// 显示地关闭 Spring 应用上下文
applicationContext.close();
}
/**
* 为 {@link UserHolder} 生成 {@link BeanDefinition}
*
* @return
*/
private static BeanDefinition createUserHolderBeanDefinition() {
BeanDefinitionBuilder definitionBuilder = BeanDefinitionBuilder.genericBeanDefinition(UserHolder.class);
definitionBuilder.addPropertyReference("user", "superUser");
return definitionBuilder.getBeanDefinition();
}
}
用到了spring的BeanDefinition接口,这个接口主要描述了bean的实例化,包括属性值、构造函数参数值和一些在实现类中用到的信息。包括xml和java注解方式注入,其底层都是beanDefinition接口实现,有兴趣的可以研究下这个接口。