[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() {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容器之进击的注解相关推荐
- 【小家Spring】Spring注解驱动开发---向Spring Ioc容器中注册Bean的7种方式
每篇一句 比你有钱的人一定会比你努力,而比你努力的人终有一天会比你有钱 前言 Spring是一个非常强大的反转控制(IOC)框架,以帮助分离项目组件之间的依赖关系.因此可以说Spring容器对Bean ...
- 头条一面:Spring IOC容器中只存放单例Bean吗?
最近,很多小伙伴出去面试,感觉自己面的不是很理想,回来后,不少小伙伴把面试题做了记录发给我,让我给大家解析下,然后发出来.当我看到这些面试题时,快速在脑海中构建起了整个知识体系,从基础到框架.从分布式 ...
- Spring点滴一:Spring Ioc 容器
Spring 容器: Spring 容器是Spring框架的核心.Spring容器将创建Bean对象实例,把它们联系在一起,配置它们,并管理它们整个生命周期从创建到销毁.Spring 容器通过依赖注入 ...
- Spring IOC 容器源码分析 - 填充属性到 bean 原始对象
1. 简介 本篇文章,我们来一起了解一下 Spring 是如何将配置文件中的属性值填充到 bean 对象中的.我在前面几篇文章中介绍过 Spring 创建 bean 的流程,即 Spring 先通过反 ...
- Spring IOC 容器源码分析 - 创建原始 bean 对象
1. 简介 本篇文章是上一篇文章(创建单例 bean 的过程)的延续.在上一篇文章中,我们从战略层面上领略了doCreateBean方法的全过程.本篇文章,我们就从战术的层面上,详细分析doCreat ...
- Spring IOC 容器源码分析 - 创建单例 bean 的过程
1. 简介 在上一篇文章中,我比较详细的分析了获取 bean 的方法,也就是getBean(String)的实现逻辑.对于已实例化好的单例 bean,getBean(String) 方法并不会再一次去 ...
- Spring IOC 容器源码分析 - 获取单例 bean
1. 简介 为了写 Spring IOC 容器源码分析系列的文章,我特地写了一篇 Spring IOC 容器的导读文章.在导读一文中,我介绍了 Spring 的一些特性以及阅读 Spring 源码的一 ...
- spring注入普通java类_普通java类如何取得注入spring Ioc容器的对象
[除了使用XML配置外,还可以选择使用基于注解(annotation)的配置方式,其依赖于字节码来织入组件.注解注入在XML注入之前完成,因此在XML配置中可以重载注解注入的属性. 一.建一个Spri ...
- Spring —— IoC 容器详解
引言 本篇博客总结自官网的<The IoC Container>,其中会结合王富强老师的<Spring揭秘>融入自己的语言和理解,争取通过这一篇文章彻底扫除spring IOC ...
最新文章
- react学习笔记(二)编写第一个react组件
- aop对请求后端的参数修改_Spring Boot AOP之对请求的参数入参与返回结果进行拦截处理...
- Andlinux 使用记录(转)
- PHP面试题:合并两个数组有几种方式,试比较它们的异同
- 《Effective Java》读书笔记 Item 1:考虑静态工厂方法,而不是构造器
- 才博教育:AI口语学习平台上云
- kotlin教程(1)
- fiddler抓包工具-- 本地资源替换线上文件
- reactrouter4路由钩子_react router @4 和 vue路由 详解(八)vue路由守卫
- opencv 轮廓检测
- 新年计算机等级的决定的英语,新年决定英语对话及译文
- [转载] python元组特点_python元组的优势有哪些
- 数据结构上机实践第四周项目6- 循环双链表应用
- python中访问lmdb
- android view 画文字,【Android自定义View】绘图之文字篇(三)
- php vld扩展,Linux安装php-vld扩展
- 轴承选型选不好,可别再说轴承质量差劲啦!
- 聊聊H5浏览器实现扫一扫
- 智遥工作流软件,转下一步时数据保存解析
- 常见计算机蓝屏代码,码住!常见电脑蓝屏代码和解决方法
热门文章
- linux设置双屏拼接_双屏办公,用起来到底有多爽
- c++读取.dat文件_MySQL 数据文件类型
- linux常用网络诊断命令,linux网络常用诊断工具
- springboot设置运行内存_docker run容器 设置 jvm 运行springboot 程序
- 项目代码从GitHub上克隆到本地
- 【直播】回放与PPT下载!深度学习如何用于摄影图像的处理?
- 【AI产品】一键去除杂物,Photo Eraser助你拍出美丽照片
- 【AI白身境】学深度学习你不得不知的爬虫基础​​​​​​​
- 产销对接行动倡议书-万祥军:长效机制谋定丰收节交易会
- 【NOIP2002】【codevs1098】均分纸牌