概述
Spring2.5 引入了注解。
于是且预,一個問題產(chǎn)生了:使用注解方式注入 JavaBean 是不是一定完爆 xml方式耙册?
未必给僵。正所謂,仁者見仁智者見智详拙。任何事物都有其優(yōu)缺點帝际,看你如何取舍。來看看注解的優(yōu)缺點:
優(yōu)點
:大大減少了配置饶辙,并且可以使配置更加精細——類蹲诀,方法,字段都可以用注解去標記弃揽。
缺點
:使用注解脯爪,不可避免產(chǎn)生了侵入式編程,也產(chǎn)生了一些問題矿微。
- 你需要將注解加入你的源碼并編譯它痕慢;
- 注解往往比較分散,不易管控涌矢。
注:spring 中掖举,先進行注解注入,然后才是xml注入蒿辙,因此如果注入的目標相同拇泛,后者會覆蓋前者滨巴。
啟動注解
Spring 默認是不啟用注解的思灌。如果想使用注解,需要先在xml中啟動注解恭取。
啟動方式:在xml中加入一個標簽泰偿,很簡單吧。
<context:annotation-config/>
注:
<context:annotation-config/>
只會檢索定義它的上下文蜈垮。什么意思呢耗跛?就是說裕照,如果你
為DispatcherServlet指定了一個WebApplicationContext
,那么它只在controller中查找@Autowired
注解调塌,而不會檢查其它的路徑晋南。
Spring注解
@Required
@Required
注解只能用于修飾bean屬性的setter方法。受影響的bean屬性必須在配置時被填充在xml配置文件中羔砾,否則容器將拋出BeanInitializationException
负间。
public class AnnotationRequired {
private String name;
private String sex;
public String getName() {
return name;
}
/**
* @Required 注解用于bean屬性的setter方法并且它指示,受影響的bean屬性必須在配置時被填充在xml配置文件中姜凄,
* 否則容器將拋出BeanInitializationException政溃。
*/
@Required
public void setName(String name) {
this.name = name;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
}
@Autowired
@Autowired
注解可用于修飾屬性、setter方法态秧、構(gòu)造方法董虱。
注:
@Autowired
注解也可用于修飾構(gòu)造方法,但如果類中只有默認構(gòu)造方法申鱼,則沒有必要愤诱。如果有多個構(gòu)造器,至少應該修飾一個捐友,來告訴容器哪一個必須使用转锈。
可以使用JSR330的注解@Inject
來替代@Autowired
。
范例
public class AnnotationAutowired {
private static final Logger log = LoggerFactory.getLogger(AnnotationRequired.class);
@Autowired
private Apple fieldA;
private Banana fieldB;
private Orange fieldC;
public Apple getFieldA() {
return fieldA;
}
public void setFieldA(Apple fieldA) {
this.fieldA = fieldA;
}
public Banana getFieldB() {
return fieldB;
}
@Autowired
public void setFieldB(Banana fieldB) {
this.fieldB = fieldB;
}
public Orange getFieldC() {
return fieldC;
}
public void setFieldC(Orange fieldC) {
this.fieldC = fieldC;
}
public AnnotationAutowired() {}
@Autowired
public AnnotationAutowired(Orange fieldC) {
this.fieldC = fieldC;
}
public static void main(String[] args) throws Exception {
AbstractApplicationContext ctx =
new ClassPathXmlApplicationContext("spring/spring-annotation.xml");
AnnotationAutowired annotationAutowired =
(AnnotationAutowired) ctx.getBean("annotationAutowired");
log.debug("fieldA: {}, fieldB:{}, fieldC:{}", annotationAutowired.getFieldA().getName(),
annotationAutowired.getFieldB().getName(),
annotationAutowired.getFieldC().getName());
ctx.close();
}
}
xml中的配置
<!-- 測試@Autowired -->
<bean id="apple" class="org.zp.notes.spring.beans.annotation.sample.Apple"/>
<bean id="potato" class="org.zp.notes.spring.beans.annotation.sample.Banana"/>
<bean id="tomato" class="org.zp.notes.spring.beans.annotation.sample.Orange"/>
<bean id="annotationAutowired" class="org.zp.notes.spring.beans.annotation.sample.AnnotationAutowired"/>
@Qualifier
在@Autowired
注解中楚殿,提到了如果發(fā)現(xiàn)有多個候選的bean都符合修飾類型撮慨,Spring就會抓瞎了。
那么脆粥,如何解決這個問題砌溺。
可以通過@Qualifier
指定bean名稱來鎖定真正需要的那個bean。
范例
public class AnnotationQualifier {
private static final Logger log = LoggerFactory.getLogger(AnnotationQualifier.class);
@Autowired
@Qualifier("dog") /** 去除這行变隔,會報異常 */
Animal dog;
Animal cat;
public Animal getDog() {
return dog;
}
public void setDog(Animal dog) {
this.dog = dog;
}
public Animal getCat() {
return cat;
}
@Autowired
public void setCat(@Qualifier("cat") Animal cat) {
this.cat = cat;
}
public static void main(String[] args) throws Exception {
AbstractApplicationContext ctx =
new ClassPathXmlApplicationContext("spring/spring-annotation.xml");
AnnotationQualifier annotationQualifier =
(AnnotationQualifier) ctx.getBean("annotationQualifier");
log.debug("Dog name: {}", annotationQualifier.getDog().getName());
log.debug("Cat name: {}", annotationQualifier.getCat().getName());
ctx.close();
}
}
abstract class Animal {
public String getName() {
return null;
}
}
class Dog extends Animal {
public String getName() {
return "狗";
}
}
class Cat extends Animal {
public String getName() {
return "貓";
}
}
xml中的配置
<!-- 測試@Qualifier -->
<bean id="dog" class="org.zp.notes.spring.beans.annotation.sample.Dog"/>
<bean id="cat" class="org.zp.notes.spring.beans.annotation.sample.Cat"/>
<bean id="annotationQualifier" class="org.zp.notes.spring.beans.annotation.sample.AnnotationQualifier"/>
JSR 250注解
@Resource
Spring支持 JSP250規(guī)定的注解@Resource
规伐。這個注解根據(jù)指定的名稱來注入bean。
如果沒有為@Resource
指定名稱匣缘,它會像@Autowired
一樣按照類型去尋找匹配猖闪。
在Spring中,由CommonAnnotationBeanPostProcessor
來處理@Resource
注解肌厨。
范例
public class AnnotationResource {
private static final Logger log = LoggerFactory.getLogger(AnnotationResource.class);
@Resource(name = "flower")
Plant flower;
@Resource(name = "tree")
Plant tree;
public Plant getFlower() {
return flower;
}
public void setFlower(Plant flower) {
this.flower = flower;
}
public Plant getTree() {
return tree;
}
public void setTree(Plant tree) {
this.tree = tree;
}
public static void main(String[] args) throws Exception {
AbstractApplicationContext ctx =
new ClassPathXmlApplicationContext("spring/spring-annotation.xml");
AnnotationResource annotationResource =
(AnnotationResource) ctx.getBean("annotationResource");
log.debug("type: {}, name: {}", annotationResource.getFlower().getClass(), annotationResource.getFlower().getName());
log.debug("type: {}, name: {}", annotationResource.getTree().getClass(), annotationResource.getTree().getName());
ctx.close();
}
}
xml的配置
<!-- 測試@Resource -->
<bean id="flower" class="org.zp.notes.spring.beans.annotation.sample.Flower"/>
<bean id="tree" class="org.zp.notes.spring.beans.annotation.sample.Tree"/>
<bean id="annotationResource" class="org.zp.notes.spring.beans.annotation.sample.AnnotationResource"/>
@PostConstruct和@PreDestroy
@PostConstruct
和@PreDestroy
是JSR 250規(guī)定的用于生命周期的注解培慌。
從其名號就可以看出,一個是在構(gòu)造之后調(diào)用的方法柑爸,一個是銷毀之前調(diào)用的方法吵护。
public class AnnotationPostConstructAndPreDestroy {
private static final Logger log = LoggerFactory.getLogger(AnnotationPostConstructAndPreDestroy.class);
@PostConstruct
public void init() {
log.debug("call @PostConstruct method");
}
@PreDestroy
public void destroy() {
log.debug("call @PreDestroy method");
}
}
JSR 330注解
從Spring3.0開始,Spring支持JSR 330標準注解(依賴注入)。
注:如果要使用JSR 330注解馅而,需要使用外部jar包祥诽。
若你使用maven管理jar包,只需要添加依賴到pom.xml即可:
<dependency>
<groupId>javax.inject</groupId>
<artifactId>javax.inject</artifactId>
<version>1</version>
</dependency>
@Inject
@Inject
和@Autowired
一樣瓮恭,可以修飾屬性雄坪、setter方法、構(gòu)造方法屯蹦。
范例
public class AnnotationInject {
private static final Logger log = LoggerFactory.getLogger(AnnotationInject.class);
@Inject
Apple fieldA;
Banana fieldB;
Orange fieldC;
public Apple getFieldA() {
return fieldA;
}
public void setFieldA(Apple fieldA) {
this.fieldA = fieldA;
}
public Banana getFieldB() {
return fieldB;
}
@Inject
public void setFieldB(Banana fieldB) {
this.fieldB = fieldB;
}
public Orange getFieldC() {
return fieldC;
}
public AnnotationInject() {}
@Inject
public AnnotationInject(Orange fieldC) {
this.fieldC = fieldC;
}
public static void main(String[] args) throws Exception {
AbstractApplicationContext ctx =
new ClassPathXmlApplicationContext("spring/spring-annotation.xml");
AnnotationInject annotationInject = (AnnotationInject) ctx.getBean("annotationInject");
log.debug("type: {}, name: {}", annotationInject.getFieldA().getClass(),
annotationInject.getFieldA().getName());
log.debug("type: {}, name: {}", annotationInject.getFieldB().getClass(),
annotationInject.getFieldB().getName());
log.debug("type: {}, name: {}", annotationInject.getFieldC().getClass(),
annotationInject.getFieldC().getName());
ctx.close();
}
}