使用注解完成自动装配

/ Spring / 没有评论 / 335浏览

在上一篇中我们演示了spring可以很方便的让我们使用注解来实例化对象,但需要一个前提,就是必须在spring的配置文件中设置扫描相应注解类的规则。在这一篇中我们将采用这种方式用注解的来演示之前文章中已经介绍过的自动装配的功能。由于自动装配功能在之前的文章中已经介绍过了,所以我们废话不多说,直接看测试用例。

@Component("work")
public class Work {

private String address;

public Work() {
setAddress("北京");
}

public String getAddress() {
return address;
}

public void setAddress(String address) {
this.address = address;
}

@Override
public String toString() {
return "Work{" +
"address='" + address + '\'' +
'}';
}
}
@Component("user")
public class User {

private String username;
private String password;
private String nickname;
private Work work;

public User() {
setUsername("admin");
setNickname("吉林乌拉");
setPassword("jilinwula");
}

public String getUsername() {
return username;
}

public void setUsername(String username) {
this.username = username;
}

public String getPassword() {
return password;
}

public void setPassword(String password) {
this.password = password;
}

public String getNickname() {
return nickname;
}

public void setNickname(String nickname) {
this.nickname = nickname;
}

public Work getWork() {
return work;
}

public void setWork(Work work) {
this.work = work;
}

@Override
public String toString() {
return "User{" +
"username='" + username + '\'' +
", password='" + password + '\'' +
", nickname='" + nickname + '\'' +
", work=" + work +
'}';
}
}
<context:component-scan base-package="com.jilinwula.spring"/>
@Test
public void test() {
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("bean.xml");
User user = applicationContext.getBean("user", User.class);
System.out.println(user);
}
User{username='admin', password='jilinwula', nickname='吉林乌拉', work=null}

因为我们什么都没有做所以work对象并没有自动注入到user对象的work属性中。那我们怎么样才能用注解实现自动注入呢。spring为我们提供了Autowired注解。Autowired注解的目的是默认采用按类型匹配的方式,在IOC容器中查找相应的对象。因为我们已经用Component注解实例化了work对象,所以此时是可以按类型在容器中,查找到该对象的。所以spring就会自动将work对象注入到user对象的work属性中。我们看下面的测试。

@Component("user")
public class User {

private String username;
private String password;
private String nickname;
@Autowired
private Work work;

public User() {
setUsername("admin");
setNickname("吉林乌拉");
setPassword("jilinwula");
}

public String getUsername() {
return username;
}

public void setUsername(String username) {
this.username = username;
}

public String getPassword() {
return password;
}

public void setPassword(String password) {
this.password = password;
}

public String getNickname() {
return nickname;
}

public void setNickname(String nickname) {
this.nickname = nickname;
}

public Work getWork() {
return work;
}

public void setWork(Work work) {
this.work = work;
}

@Override
public String toString() {
return "User{" +
"username='" + username + '\'' +
", password='" + password + '\'' +
", nickname='" + nickname + '\'' +
", work=" + work +
'}';
}
}
User{username='admin', password='jilinwula', nickname='吉林乌拉', work=Work{address='北京'}}

我看已经成功的用Autowired注解将work对象注入到了user对象中。现在我们看一下Autowired注解的源码。

@Target({ElementType.CONSTRUCTOR, ElementType.METHOD, ElementType.PARAMETER, ElementType.FIELD, ElementType.ANNOTATION_TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Autowired {
boolean required() default true;
}

我们看到Autowired注解中还有一个required属性。required属性默认为ture,当属性为ture时的意思是说如果在IOC容器中找不到相应的对象时spring就会抛出异常。如果设置为false则不会抛出异常。上面我们已经说过了,Autowired默认是按类型注入的,那么如果IOC容器中有多个相同类型的对象,那么Autowired注解会注入哪个对象呢?我们用下面的测试用例来验证一下。

<bean id="work" class="com.jilinwula.spring.work.Work" p:address="上海"/>
<context:component-scan base-package="com.jilinwula.spring"/>
User{username='admin', password='jilinwula', nickname='吉林乌拉', work=Work{address='上海'}}

我们看如果配置文件中的id和注解中的设置的是相同的,那么配置文件中的对象会覆盖注解中的对象。当然我们也可以指定名字来选择我们想要注入的对象。spring为我们提供了Qualifier注解。当容器中有多个相同类型时,我们可以用Qualifier注解指定我们到底选择哪个对象注入。

@Component("work1")
public class Work {

private String address;

public Work() {
setAddress("北京");
}

public String getAddress() {
return address;
}

public void setAddress(String address) {
this.address = address;
}

@Override
public String toString() {
return "Work{" +
"address='" + address + '\'' +
'}';
}
}
<bean id="work2" class="com.jilinwula.spring.work.Work" p:address="上海"/>
<context:component-scan base-package="com.jilinwula.spring"/>
@Component("user")
public class User {

private String username;
private String password;
private String nickname;
@Qualifier("work1")
@Autowired
private Work work;

public User() {
setUsername("admin");
setNickname("吉林乌拉");
setPassword("jilinwula");
}

public String getUsername() {
return username;
}

public void setUsername(String username) {
this.username = username;
}

public String getPassword() {
return password;
}

public void setPassword(String password) {
this.password = password;
}

public String getNickname() {
return nickname;
}

public void setNickname(String nickname) {
this.nickname = nickname;
}

public Work getWork() {
return work;
}

public void setWork(Work work) {
this.work = work;
}

@Override
public String toString() {
return "User{" +
"username='" + username + '\'' +
", password='" + password + '\'' +
", nickname='" + nickname + '\'' +
", work=" + work +
'}';
}
}
User{username='admin', password='jilinwula', nickname='吉林乌拉', work=Work{address='北京'}}
@Component("user")
public class User {

private String username;
private String password;
private String nickname;
@Qualifier("work2")
@Autowired
private Work work;

public User() {
setUsername("admin");
setNickname("吉林乌拉");
setPassword("jilinwula");
}

public String getUsername() {
return username;
}

public void setUsername(String username) {
this.username = username;
}

public String getPassword() {
return password;
}

public void setPassword(String password) {
this.password = password;
}

public String getNickname() {
return nickname;
}

public void setNickname(String nickname) {
this.nickname = nickname;
}

public Work getWork() {
return work;
}

public void setWork(Work work) {
this.work = work;
}

@Override
public String toString() {
return "User{" +
"username='" + username + '\'' +
", password='" + password + '\'' +
", nickname='" + nickname + '\'' +
", work=" + work +
'}';
}
}
User{username='admin', password='jilinwula', nickname='吉林乌拉', work=Work{address='上海'}}