前言

上一篇中,我们介绍了spring自动装配(autowire)的特性。而从系列一开始,我们似乎就一直在xml配置文件中捣鼓,包括上篇的自动装配。不过,自从spring2.5开始,spring还支持了基于注解(annotation)的配置方式。那么这篇我们就来介绍下这个特性,看看它能给我们带来多大的惊喜。

基于annotation的配置

在默认情况下,spring的annotation是没有开启的,为了支持这一特性,我们需要修改下配置文件如下:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
    http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.1.xsd">
    <context:annotation-config></context:annotation-config>
</beans>

只要加入

<context:annotation-config></context:annotation-config>

上面这个配置,你就可以通过注解(annotation)的方式来完成上一篇中同样自动装配bean的功能。这个如何做?暂且保密,等等哦,往下看会有的。

几个常用的annotation

  • @Required 这个注解应用于bean的setter方法。
  • @Autowired 这个注解应用于bean的属性setter方法,构造方法,属性等。
  • @Qualifier 这个注解一般会和@Autowired一起出现,当有多个bean具有相同类型的时候,你可以通过这个注解来明确指定是哪个bean。
  • JSR-250 Annotations spring还支持@Resource,@PostConstruct和@PreDestroy annotations等基于JSR-250的annotation。

还挺多,新手会不会晕了,不过别担心,今天我们之挑一个和上篇有关的,剩下的下次介绍,这样做原因一是为了保持和上篇的连贯性,二是不要让新手一次接受太多东西,三呢是作者偷懒,今天不想写那么多了。。

@Autowired 注解

没错,今天就是它了,从名称可以看出它也是自动装配嘛,比上篇的基于xml的自动装配形象多了,当时才没有告诉我们呢,只是说了个byName什么的。什么?你记得了?那赶紧回去看上一篇吧。好了,那我们继续还是以上篇的例子。首先,我们将Beans.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"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
    http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.1.xsd">

    <context:annotation-config></context:annotation-config>

    <bean id="tv" class="sirk_spring_tuto.demo.TV"></bean> 
    <bean id="screen" class="sirk_spring_tuto.demo.CRTScreen"></bean>
</beans>

然后再修改TV.java:

package sirk_spring_tuto.demo;

import org.springframework.beans.factory.annotation.Autowired;

public class TV {

/**
 * 这里给属性增加自动装配注解
 */
@Autowired
private Screen screen;



public void powerOn(){
    this.screen.show();
}

public Screen getScreen() {
    return screen;
}

public void setScreen(Screen screen) {
    this.screen = screen;
}
}

最后其他文件都不变,最后运行:

package sirk_spring_tuto.demo;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class App {

public static void main(String[] args) {
    ApplicationContext ctx = new ClassPathXmlApplicationContext("Beans.xml");
    TV tv = (TV) ctx.getBean("tv");
    tv.powerOn();

}

}

如果没有什么错误,结果将会和上一篇一样。但是竟然出错了:

Caused by: java.lang.NoClassDefFoundError: org/springframework/core/type/AnnotatedTypeMetadata

看到如此异常,不必惊慌,没找到类,一定是忘记导入什么包了,原来在xml配置中新加入的context定义需要用到spring-context包,于是加入。最终终于运行成功啦。如果你还没成功,一定是什么地方写错了,认真检查哦。

如果已经成功,接着我们来尝试把注解用到setter方法上:

public class TV {


private Screen screen;



public void powerOn(){
    this.screen.show();
}

public Screen getScreen() {
    return screen;
}

/**
 * 这里给属性增加自动装配注解
 */
@Autowired
public void setScreen(Screen screen) {
    this.screen = screen;
}
}

一样可以哦,再来试下构造方法:

public class TV {

private Screen screen;


/**
 * 这里给属性增加自动装配注解
 */
@Autowired
public TV(Screen sc){
    this.screen = sc;
}


public void powerOn(){
    this.screen.show();
}

public Screen getScreen() {
    return screen;
}


public void setScreen(Screen screen) {
    this.screen = screen;
}
}

是不是很简单?除了这几种用法,它还有另一种用法:

package sirk_spring_tuto.demo;

import org.springframework.beans.factory.annotation.Autowired;



public class TV {


private Screen screen;
private RemoteControl rc;


/**
 * 这里给属性增加自动装配注解
 */
@Autowired
public TV(Screen sc){
    this.screen = sc;
}


public void powerOn(){
    this.screen.show();
}

public Screen getScreen() {
    return screen;
}


public void setScreen(Screen screen) {
    this.screen = screen;
}

public RemoteControl getRc() {
    return rc;
}

@Autowired(required = false)
public void setRc(RemoteControl rc) {
    this.rc = rc;
}

}

这里我们给电视机类新增了遥控属性,并且我们没有修改xml配置文件,也就是说,我们没有在配置文件中配置遥控类的bean,但是在setRc方法上面我们写的是:

@Autowired(required = false)

这样,尽管没有着要装配的bean,但是因为required是false,所以也没有报错,如果你去掉required=false,只留下@Autowired那就不一样了。这种用法实际不多,就不详细展开了。

小结

今天介绍了spring的基于annotation的配置,并以上篇为例子,使用@Autowired注解实现了下,并简要介绍了spring的几种主要注解,下文将介绍剩下的几种注解。

##文档信息