[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。
*/
@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方法、构造方法。
注:
@Autowired注解也可用于修饰构造方法,但如果类中只有默认构造方法,则没有必要。如果有多个构造器,至少应该修饰一个,来告诉容器哪一个必须使用。
可以使用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注解中,提到了如果发现有多个候选的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规定的注解@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);
@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方法、构造方法。
范例
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();
}
}
[Spring]IoC容器之进击的注解的更多相关文章
- 纯注解快速使用spring IOC容器
使用spring的ioc容器实现对bean的管理与基本的依赖注入是再经典的应用了.基础使用不在详述. 这里主要介绍下使用注解实现零配置的spring容器.我相信你也会更喜欢使用这种方式.Spring ...
- Spring IOC容器装配Bean_基于注解配置方式
bean的实例化 1.导入jar包(必不可少的) 2.实例化bean applicationContext.xml(xml的写法) <bean id="userDao" cl ...
- 【Spring】非Spring IOC容器下获取Spring IOC上下文的环境
前言 在Spring Web项目中,有些特殊的时候需要在非Spring IOC容器下获取Spring IOC容器的上下文环境,比如获取某个bean. 版本说明 声明POM文件,指定需引入的JAR. & ...
- Spring IOC容器基本原理
2.2.1 IOC容器的概念IOC容器就是具有依赖注入功能的容器,IOC容器负责实例化.定位.配置应用程序中的对象及建立这些对象间的依赖.应用程序无需直接在代码中new相关的对象,应用程序由IOC容器 ...
- spring揭密学习笔记(3)-spring ioc容器:Spring的IoC容器之BeanFactory
1. Spring的IoC容器和IoC Service Provider的关系 Spring的IoC容器和IoC Service Provider所提供的服务之间存在一定的交集,二者的关系如图4-1所 ...
- 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 源码的一 ...
随机推荐
- 【原】Android热更新开源项目Tinker源码解析系列之三:so热更新
本系列将从以下三个方面对Tinker进行源码解析: Android热更新开源项目Tinker源码解析系列之一:Dex热更新 Android热更新开源项目Tinker源码解析系列之二:资源文件热更新 A ...
- transtion:过渡动画
p.p1 { margin: 0.0px 0.0px 0.0px 0.0px; font: 17.0px Monaco; color: #4f5d66 } p.p2 { margin: 0.0px 0 ...
- 获取Canvas当前坐标系矩阵
前言 在我的另一篇博文 Canvas坐标系转换 中,我们知道了所有的平移缩放旋转操作都会影响到画布坐标系.那在我们对画布进行了一系列操作之后,怎么再知道当前矩阵数据状态呢. 具体代码 首先请看下面的一 ...
- 【C#代码实战】群蚁算法理论与实践全攻略——旅行商等路径优化问题的新方法
若干年前读研的时候,学院有一个教授,专门做群蚁算法的,很厉害,偶尔了解了一点点.感觉也是生物智能的一个体现,和遗传算法.神经网络有异曲同工之妙.只不过当时没有实际需求学习,所以没去研究.最近有一个这样 ...
- CSS 特殊属性介绍之 pointer-events
首先看一下 MDN 上关于 pointer-events 的介绍: CSS属性 pointer-events 允许作者控制特定的图形元素在何时成为鼠标事件的 target.当未指定该属性时,SVG 内 ...
- 【NLP】Python NLTK获取文本语料和词汇资源
Python NLTK 获取文本语料和词汇资源 作者:白宁超 2016年11月7日13:15:24 摘要:NLTK是由宾夕法尼亚大学计算机和信息科学使用python语言实现的一种自然语言工具包,其收集 ...
- Entity Framework 手动使用migration里面的up 和down方法。
add-migration -IgnoreChanges 201606100717405_201606100645298_InitialCreate 执行这一句后 ,清空使用map生成的代码,个人不太 ...
- servlet 简介,待完善
什么是Servlet?① Servlet就是JAVA 类② Servlet是一个继承HttpServlet类的类③ 这个在服务器端运行,用以处理客户端的请求 Servlet相关包的介绍--javax. ...
- oracle常用函数及示例
学习oracle也有一段时间了,发现oracle中的函数好多,对于做后台的程序猿来说,大把大把的时间还要学习很多其他的新东西,再把这些函数也都记住是不太现实的,所以总结了一下oracle中的一些常用函 ...
- Java集合类--温习笔记
最近面试发现自己的知识框架有好多问题.明明脑子里知道这个知识点,流程原理也都明白,可就是说不好,不知道是自己表达技能没点,还是确实是自己基础有问题.不管了,再巩固下基础知识总是没错的,反正最近空闲时间 ...