javascript
[Spring]IoC容器之进击的注解
先啰嗦兩句:
第一次在博客園使用markdown編輯,感覺渲染樣式差強人意,還是github的樣式比較順眼。
概述
Spring2.5 引入了注解。
于是,一個問題產生了:使用注解方式注入 JavaBean 是不是一定完爆 xml方式?
未必。正所謂,仁者見仁智者見智。任何事物都有其優缺點,看你如何取舍。來看看注解的優缺點:
優點:大大減少了配置,并且可以使配置更加精細——類,方法,字段都可以用注解去標記。
缺點:使用注解,不可避免產生了侵入式編程,也產生了一些問題。
- 你需要將注解加入你的源碼并編譯它;
注解往往比較分散,不易管控。
注:spring 中,先進行注解注入,然后才是xml注入,因此如果注入的目標相同,后者會覆蓋前者。
啟動注解
Spring 默認是不啟用注解的。如果想使用注解,需要先在xml中啟動注解。
啟動方式:在xml中加入一個標簽,很簡單吧。
注:<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。*/@Requiredpublic void setName(String name) {this.name = name;}public String getSex() {return sex;}public void setSex(String sex) {this.sex = sex;} }@Autowired
@Autowired注解可用于修飾屬性、setter方法、構造方法。
注:@Autowired注解也可用于修飾構造方法,但如果類中只有默認構造方法,則沒有必要。如果有多個構造器,至少應該修飾一個,來告訴容器哪一個必須使用。
可以使用JSR330的注解@Inject來替代@Autowired。
范例
public class AnnotationAutowired {private static final Logger log = LoggerFactory.getLogger(AnnotationRequired.class);@Autowiredprivate 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;}@Autowiredpublic void setFieldB(Banana fieldB) {this.fieldB = fieldB;}public Orange getFieldC() {return fieldC;}public void setFieldC(Orange fieldC) {this.fieldC = fieldC;}public AnnotationAutowired() {}@Autowiredpublic 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注解中,提到了如果發現有多個候選的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;}@Autowiredpublic 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規定的注解@Resource。這個注解根據指定的名稱來注入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規定的用于生命周期的注解。
從其名號就可以看出,一個是在構造之后調用的方法,一個是銷毀之前調用的方法。
public class AnnotationPostConstructAndPreDestroy {private static final Logger log = LoggerFactory.getLogger(AnnotationPostConstructAndPreDestroy.class);@PostConstructpublic void init() {log.debug("call @PostConstruct method");}@PreDestroypublic 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方法、構造方法。
范例
public class AnnotationInject {private static final Logger log = LoggerFactory.getLogger(AnnotationInject.class);@InjectApple fieldA;Banana fieldB;Orange fieldC;public Apple getFieldA() {return fieldA;}public void setFieldA(Apple fieldA) {this.fieldA = fieldA;}public Banana getFieldB() {return fieldB;}@Injectpublic void setFieldB(Banana fieldB) {this.fieldB = fieldB;}public Orange getFieldC() {return fieldC;}public AnnotationInject() {}@Injectpublic 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();} }總結
以上是生活随笔為你收集整理的[Spring]IoC容器之进击的注解的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 1-3 数组的反序输出
- 下一篇: 20145234黄斐《信息安全系统设计基