概述
对于在容器中的bean而言, 它的工作可能依赖于其他Bean, 比如一台电脑的工作依赖于鼠标,键盘,屏幕和主机. 当我们对每一个Bean完成初始化时候, 需要确定一种装配方式, 将它所依赖的Bean注入进去.
Spring提供了三种依赖装配方案:
- 通过XML来显式指定装配值.
- 通过JavaConfig进行装配.
- 通过自动装配机制.
通过XML显式配置装配
使用使用XML来显式装配时候, 我们又可以选择三种方法:
- 通过setter来注入属性值.
- 通过构造函数来注入属性值.
- 通过Factory对象来直接注入Bean.
提示: 如果Java中没有任何构造函数, 则编译会自动生成一个默认的构造函数.
在XML中使用Setter来实现依赖注入
采用setter注入需要有两个前提:
- 类需要有的无参构造函数.
- 类需要有对属性的设置方法setXxx.
Java代码:
public class Keyboard {
private String name;
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "Keyboard{" +
"name='" + name + '\'' +
'}';
}
}
// 电脑
public class Computer {
private String name;
private Keyboard keyboard;
public void setName(String name) {
this.name = name;
}
public void setKeyboard(Keyboard keyboard) {
this.keyboard = keyboard;
}
@Override
public String toString() {
return "Computer{" +
"name='" + name + '\'' +
", keyboard=" + keyboard +
'}';
}
}
public static void main(String[] args) {
String path = "classpath:/application-di-computer.xml";
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext(path);
Keyboard keyboard = context.getBean(lab.anoper.ioc.di.computer.component.Keyboard.class);
System.out.println(keyboard);
Computer computer = context.getBean(lab.anoper.ioc.di.computer.component.Computer.class);
System.out.println(computer);
}
bean定义文件:
<!--通过属性注入-->
<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://www.springframework.org/schema/beans"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"
default-autowire="byName">
<bean id="hpKeyboard" class="lab.anoper.ioc.di.computer.component.Keyboard">
<!-- 惠普键盘 -->
<property name="name" value="HP"/>
</bean>
<bean id="computer" class="lab.anoper.ioc.di.computer.component.Computer">
<property name="name" value="Walter"/>
<property name="keyboard" ref="hpKeyboard"/>
</bean>
</beans>
输出结果:
Keyboard{name='HP'}
Computer{name='Walter', keyboard=Keyboard{name='HP'}}
在XML中使用构造方法注入
使用构造函数注入需要有一个前提: 有相应的构造函数. 如果我们使用第三方时候, 并没有提供setXxx方法时候, 可以使用构造函数注入.
java代码:
public class Keyboard {
private String name;
public Keyboard(String name) {
this.name = name;
}
@Override
public String toString() {
return "Keyboard{" +
"name='" + name + '\'' +
'}';
}
}
public class Computer {
private String name;
private Keyboard keyboard;
public Computer(String name, Keyboard keyboard) {
this.name = name;
this.keyboard = keyboard;
}
@Override
public String toString() {
return "Computer{" +
"name='" + name + '\'' +
", keyboard=" + keyboard +
'}';
}
}
public class DIDemo {
public static void main(String[] args) {
String path = "classpath:/application-di-computer-cons.xml";
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext(path);
Keyboard keyboard = context.getBean(lab.anoper.ioc.di.computer.component.Keyboard.class);
System.out.println(keyboard);
Computer computer = context.getBean(lab.anoper.ioc.di.computer.component.Computer.class);
System.out.println(computer);
}
}
配置文件:
<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://www.springframework.org/schema/beans"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"
default-autowire="byName">
<bean id="hpKeyboard" class="lab.anoper.ioc.di.computer.component.Keyboard">
<constructor-arg value="HP"/>
</bean>
<bean id="computer" class="lab.anoper.ioc.di.computer.component.Computer">
<constructor-arg value="Walter"/>
<constructor-arg ref="hpKeyboard"/>
</bean>
</beans>
输出结果:
Keyboard{name='HP'}
Computer{name='Walter', keyboard=Keyboard{name='HP'}}
使用JavaConfig显式装配依赖
如果要是用JavaConfig显式装配依赖, 则需要使用@Configuration
, @Bean
等注解.
- @Configuration: 用于指示这个类中存在一个或者多个bean, 并且这些bean可以由Spring容器管理.
- @Bean: 指示这个方法会产生一个可以由Spring容器管理的bean.
Java代码:
@Configuration
public class ComputerConfig {
@Bean
public Keyboard keyboard () {
return new Keyboard("HP");
}
@Bean
public Computer computer() {
return new Computer("Walter", keyboard());
}
}
public class DIDemo {
public static void main(String[] args) {
String scanPackages = "lab.anoper.ioc.di.computer.config";
// 指定要扫描的包
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(scanPackages);
Computer computer = context.getBean("computer", lab.anoper.ioc.di.computer.component.Computer.class);
System.out.println(computer);
}
}
运行结果:
Computer{name='Walter', keyboard=Keyboard{name='HP'}}
使用自动装配注入依赖
使用自动装配主要依赖于autowired
注解来实现, 这个注解可以注解在属性上, setter方法上或者构造函数上. 注解在setter上或者是属性上, 最终将会采用setter注入方法.注解在构造函数上, 最终会采用构造函数注入方法.
需要使用到如下注解:
- @Component: 指示此类是一个"组件", 当自动扫描时候, 将会被视为一个候选.
- @Autowired: 将构造函数,字段,setter方法或config方法标记为由Spring的依赖项注入工具自动装配.