目录结构
![](https://img.kancloud.cn/31/14/3114f12af2a27bac7e6699d27aa75d4d_425x378.png)
没有使用 spring 的构造器注入形式:
![](https://img.kancloud.cn/22/bb/22bbcf945082e53cf1ae8836ec338117_326x202.png)
`DeclareSpringComponent`是用于 spring 的,暂时不理。
`ConstructorInjection`是普通构造器注入,`Dependency`是依赖项。通过在构造器中提供依赖项,实现基于构造器的依赖注入。
~~~
// 注意 @Autowired 只能用于其中一个构造器自动注入
~~~
---
接着有个三个spring应用类:
![](https://img.kancloud.cn/a5/d3/a5d3ee3a0dcf921ade2d1e77b6cbce06_425x378.png)
其中 `DeclareSpringComponents` 就是演示使用 spring 构造器注入而已。
~~~
public class DeclareSpringComponents {
public static void main(String... args) {
GenericXmlApplicationContext ctx = new GenericXmlApplicationContext();
ctx.load("classpath:spring/app-context-annotation.xml");
ctx.refresh();
MessageProvider messageProvider = ctx.getBean("provider",
MessageProvider.class);
System.out.println(messageProvider.getMessage());
ctx.close();
}
}
~~~
对应的 xml 配置文件:
~~~
<!--省略 schema -->
<context:component-scan
base-package="com.apress.prospring5.ch3.annotated"/>
<bean id="message" class="java.lang.String"
c:_0="希望你会好好的 I hope that someone gets my message in a bottle"/>
<bean id="message2" class="java.lang.String"
c:_0="I know I won't be injected :("/>
~~~
上面配置文件扫描到 `com.apress.prospring5.ch3.annotated` 这个包下的 bean :
~~~
@Repository("provider")
public class ConfigurableMessageProvider implements MessageProvider {
private String message;
// 根据参数名来自动注入,构造器注入
@Autowired
public ConfigurableMessageProvider(String message) {
this.message = message;
}
@Override
public String getMessage() {
return this.message;
}
}
~~~
它对应的 `MessageProvider` 是:
~~~
@Repository("provider")
public class ConfigurableMessageProvider implements MessageProvider {
private String message;
// 根据参数名来自动注入,构造器注入
@Autowired
public ConfigurableMessageProvider(String message) {
this.message = message;
}
@Override
public String getMessage() {
return this.message;
}
}
~~~
---
接下来看看 `ConstructorConfusion` 这个类里边演示了两个构造器,spring 根据构造器的参数类型判断应该注入那个 bean.
~~~
public class ConstructorConfusion {
private String someValue;
//两个构造器注入,根据构造器参数的类型来判断注入哪一个
public ConstructorConfusion(String someValue) {
System.out.println("ConstructorConfusion(String) called");
this.someValue = someValue;
}
public ConstructorConfusion(int someValue) {
System.out.println("ConstructorConfusion(int) called");
this.someValue = "Number: " + someValue;
}
public static void main(String... args) {
GenericXmlApplicationContext ctx = new GenericXmlApplicationContext();
ctx.load("classpath:spring/app-context-xml.xml");
ctx.refresh();
ConstructorConfusion cc = (ConstructorConfusion) ctx.getBean("constructorConfusion");
System.out.println(cc);
ctx.close();
}
public String toString() {
return someValue;
}
}
~~~
在 xml 配置文件里 bean 标签指定构造器参数的类型,据此确定依赖注入的类型。
~~~
<bean id="provider"
class="com.apress.prospring5.ch3.xml.ConfigurableMessageProvider"
c:message="I hope that someone gets my message in a bottle"/>
<bean id="constructorConfusion"
class="com.apress.prospring5.ch3.xml.ConstructorConfusion">
<constructor-arg type="int">
<value>90</value>
</constructor-arg>
</bean>
~~~