当前位置: 首页 >服务端 > [Spring]IoC容器之进击的注解

[Spring]IoC容器之进击的注解

先啰嗦两句:
第一次在博客园使用markdown编辑,感觉渲染样式差强人意,还是github的样式比较顺眼。

概述

Spring2.5 引入了注解。
于是,一个问题产生了:使用注解方式注入 JavaBean 是不是一定完爆 xml方式?
未必。正所谓,仁者见仁智者见智。任何事物都有其优缺点,看你如何取舍。来看看注解的优缺点:
优点:大大减少了配置,并且可以使配置更加精细——类,方法,字段都可以用注解去标记。
缺点:使用注解,不可避免产生了侵入式编程,也产生了一些问题。

  • 你需要将注解加入你的源码并编译它;
  • 注解往往比较分散,不易管控。

注: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() {retu name;}/** * @Required 注解用于bean属性的setter方法并且它指示,受影响的bean属性必须在配置时被填充在xml配置文件中, *否则容器将抛出BeanInitializationException。 */@Requiredpublic void setName(String name) {this.name = name;}public String getSex() {retu 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() {retu fieldA;}public void setFieldA(Apple fieldA) {this.fieldA = fieldA;}public Banana getFieldB() {retu fieldB;}@Autowiredpublic void setFieldB(Banana fieldB) {this.fieldB = fieldB;}public Orange getFieldC() {retu 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() {retu dog;}public void setDog(Animal dog) {this.dog = dog;}public Animal getCat() {retu 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() {retu null;}}class Dog extends Animal {public String getName() {retu "狗";}}class Cat extends Animal {public String getName() {retu "猫";}}

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() {retu flower;}public void setFlower(Plant flower) {this.flower = flower;}public Plant getTree() {retu 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() {retu fieldA;}public void setFieldA(Apple fieldA) {this.fieldA = fieldA;}public Banana getFieldB() {retu fieldB;}@Injectpublic void setFieldB(Banana fieldB) {this.fieldB = fieldB;}public Orange getFieldC() {retu 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();}}

作者:静默虚空
来源链接:https://www.cnblogs.com/jingmoxukong/p/5899187.html

版权声明:
1、JavaClub(https://www.javaclub.cn)以学习交流为目的,由作者投稿、网友推荐和小编整理收藏优秀的IT技术及相关内容,包括但不限于文字、图片、音频、视频、软件、程序等,其均来自互联网,本站不享有版权,版权归原作者所有。

2、本站提供的内容仅用于个人学习、研究或欣赏,以及其他非商业性或非盈利性用途,但同时应遵守著作权法及其他相关法律的规定,不得侵犯相关权利人及本网站的合法权利。
3、本网站内容原作者如不愿意在本网站刊登内容,请及时通知本站(javaclubcn@163.com),我们将第一时间核实后及时予以删除。





本文链接:https://www.javaclub.cn/server/113146.html

标签:Spring注解
分享给朋友: