使用@Autowired注解

从Spring2.5开始,最有趣的一种装配Spring Bean的方式是使用注解自动装配Bean的属性。
Spring默认禁用注解装配,最简单的启用方式是使用Spring的context命名空间配置中的<context:annotation-config>元素,如下所示:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd"> <context:annotation-config /> <!-- bean declarations here --> </beans>

继续我们上一节的例子,在xml文件中我们定一个两个bean:falchion bean和guanyu bean,为了实现@Autowired自动装配,我们在GuanYu类中的setWeapon()方法前添加了@Autowired注解,如下:
GuanYu.java:

package com.moonlit.myspring;

import org.springframework.beans.factory.annotation.Autowired;

public class GuanYu implements Hero {
private Weapon weapon; public void perform() {
System.out.println("Guan Yu pick up his weapon.");
weapon.attack();
}
public Weapon getWeapon() {
return weapon;
}
@Autowired
public void setWeapon(Weapon weapon) {
this.weapon = weapon;
}
}

通过基于注解的方式,我们可以不用在xml文件中为guanyu bean添加autowire属性了。
spring-idol内部的代码:

<context:annotation-config />

  <bean id="falchion" class="com.moonlit.myspring.Falchion"  />
<bean id="guanyu" class="com.moonlit.myspring.GuanYu" />

我们不仅可以使用@Autowired注解标注setter方法,还可以标注需要自动装配bean引用的任一方法,比如,我们给GuanYu类的setWeapon方法改名为pickupWeapon,如下:

package com.moonlit.myspring;

import org.springframework.beans.factory.annotation.Autowired;

public class GuanYu implements Hero {
private Weapon weapon; public void perform() {
System.out.println("Guan Yu pick up his weapon.");
weapon.attack();
}
public Weapon getWeapon() {
return weapon;
}
@Autowired
public void pickupWeapon(Weapon weapon) {
this.weapon = weapon;
}
}

再运行测试程序AutowirePractice,输出的结果是一样的,因为虽然没有了setWeapon方法,但是通过@Autowired注解我们通过pickupWeapon方法加falchion bean传递给了guanyu bean。
@Autowired注解甚至可以标注构造器,这样的话我们甚至连set方法都可以不写了:

package com.moonlit.myspring;

import org.springframework.beans.factory.annotation.Autowired;

public class GuanYu implements Hero {
@Autowired
private Weapon weapon; public void perform() {
System.out.println("Guan Yu pick up his weapon.");
weapon.attack();
}
}

@Autowired注解存在两种限制:

  • 没有匹配Bean
  • 匹配多个Bean 不过都有解决办法。

可选的自动装配

默认情况下,@Autowired属性具有强契约特征,其所标注的属性或参数必须是可装配的。如果没有Bean可以装配到@Autowired所标注的属性或参数中,自动装配就会失败(抛出令人讨厌的NoSuchBeanDefinitionException)。
属性不一定非要装配,null值也是可以接受的。在这种场景下,可以通过设置@Autowired的required属性为false来配置自动装配式可选的。例如:

@Autowired(required=false)
private Weapon weapon;

限定歧义性的依赖

有可能存在多个bean满足装配条件,比如,这里,falchion bean和halberd bean都满足装配到guanyu bean的weapon属性中的条件。此时如果只是用@Autowired注解的话就会出问题,才@Autowired竹节虾添加@Qualifier注解如下:

@Autowired
@Qualifier("falchion")
private Weapon weapon;

就会将falchion bean装入到weapon中。
如上所示,@Qualifier注解将尝试注入ID为falchion的Bean。
除了通过Bean的ID来限定,我们也可以给Bean添加一个qualifier属性,通过这个qualifier属性来获得限定,如:
我们给halberd bean添加一个qualifier,值为"weaponOfGuanYu":

<bean id="halberd" class="com.moonlit.myspring.Halberd">
<qualifier value="weaponOfGuanYu" />
</bean>

然后对GuanYu类weapon类的注解如下:

@Autowired
@Qualifier("weaponOfGuanYu")
private Weapon weapon;

输出如下:

Guan Yu pick up his weapon.
halberd is attacking!!!

可以看出,@qualifier降低了@Autowired的匹配范围,最终筛选得到了halberd bean装入weapon属性。
这里的<qualifier>元素限定了方天画戟(halberd)Bean是关羽使用的武器(weaponOgGuanYu)。除了可以在XML中指定qualifier,还可以使用Qualifier类来标注Halberd类:

package com.moonlit.myspring;

import org.springframework.beans.factory.annotation.Qualifier;

@Qualifier("weaponOfGuanYu")
public class Halberd implements Weapon {
public void attack() {
System.out.println("halberd is attacking!!!");
}
}

程序运行将得到相同的结果。

创建自定义的限定器(Qualifier)

为了创建一个自定义的限定器,我们需要定义一个注解,使用@Qualifier注解来充当他的元注解。例如,让我们创建一个attack注解来充当一个限定器。

package com.moonlit.myspring;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target; import org.springframework.beans.factory.annotation.Qualifier; @Target({ElementType.FIELD, ElementType.PARAMETER, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Qualifier
public @interface attack {
}

这个类我用来限定是攻击性武器。
然后我们在方天画戟前面标注一下他是一个攻击性武器(@attack)如下:

package com.moonlit.myspring;

@attack
public class Halberd implements Weapon {
public void attack() {
System.out.println("halberd is attacking!!!");
}
}

最后我们使用@attack限定符来对GuanYu的weapon属性进行限定:

package com.moonlit.myspring;

import org.springframework.beans.factory.annotation.Autowired;

public class GuanYu implements Hero {
@Autowired
@attack
private Weapon weapon; public void perform() {
System.out.println("Guan Yu pick up his weapon.");
weapon.attack();
}
}

当Spring尝试装配weapon属性时,Spring会把所有可选择的武器Bean缩小到只有@attack注解所标注的Bean。如果只有一个武器Bean使用@attack注解,那么该Bean将会被装配到instrument属性中。
可以通过使用多个自定义的限定器来起到进一步的限定的作用。(比如再声明一个先定义@defence,将@attack和@defence一起使用),相当于一个“与”的效果。

借助@Inject实现基于标准的自动装配

为了统一各种依赖注入框架的编程模型,JCP(Java Community Process)最近(也不知道啥时候的事了,应该是Sring实战英文版第三版发布之前)发布了Java依赖注入规范,JCP将其称为JSR-330,更常见的叫法是at inject。
在JSR-330中:

  • @Inject 相当于 @Autowired
  • @Named 相当于 @Qualifier
  • JSR-330中也具有一个@Qualifier注解

需要注意的一点是原文中的这段内容:“Spring的@Qualifier与JSR-330的@Named的关键区别在于语义层面。@qualifier注解帮助我们缩小所匹配Bean的选择范围(默认使用Bean的ID),而@Named通过Bean的ID来标识可选择的Bean。”。
我对这段话的理解是:@qualifier之间是“与”的关系;@Named之间是“或”的关系。(不知道对不对,有待日后检验)

在注解中使用表达式

Spring3.0引入了@Value,他是一个新的装配注解,可以让我们使用注解来装配String类型的值和基本类型的值,如int、boolean。
我们可以通过@Value直接标注某个属性、方法或者方法参数,并传入一个String类型的表达式来装配属性。例如:

@Value("moonlit")
private String song;

这里,我们为String类型的属性装配了一个String类型的值。但是传入@Value的String类型的参数只是一个表达式——他的计算结果可以是任意类型,因此@Value可以标注任意类型的属性。
@Value可以结合SpEL一起使用。例如,与其为song属性硬编码为一个静态值,不如使用SpEL从系统属性中获取一个值:

@Value("#{systemProperties.myFavoriteSong}")
private String song;

Spring学习笔记--使用注解装配的更多相关文章

  1. Spring学习笔记(二)之装配Bean

    一,介绍Bean的装配机制 在Spring中,容器负责对象的创建并通过DI来协调对象之间的关系.但是我们要告诉Spring创建哪些Bean并且如何将其装配在一起.,装配wiring就是DI依赖注入的本 ...

  2. Spring学习笔记(三)之装配Bean

    除了组件扫描与自动装配之外还有基于Java代码的装配与基于XML的装配. 有一些场景是我们不能用自动装配的,比如我们要给第三方库中的组件装配到我们的应用中,这时自动装配无效,因为自动装配只能扫描本应用 ...

  3. spring学习笔记二 注解及AOP

    本节需要导入spring-aop包 注解 使用注解的目的是为了代替配置,在使用注解时,省略键时,则是为value赋值. 扫描某个包下的所有类中的注解 <?xml version="1. ...

  4. Spring学习笔记6——注解方式测试

    需要下载junit-4.12.jar和hamcrest-all-1.3.jar,将下载好的包导入到项目当中. 修改TestSpring, 并运行1. @RunWith(SpringJUnit4Clas ...

  5. Spring学习笔记5——注解方式AOP

    第一步:注解配置业务类 使用@Component("Pservice")注解ProductService 类 package com.spring.service; import ...

  6. Spring学习笔记之依赖的注解(2)

    Spring学习笔记之依赖的注解(2) 1.0 注解,不能单独存在,是Java中的一种类型 1.1 写注解 1.2 注解反射 2.0 spring的注解 spring的 @Controller@Com ...

  7. 不错的Spring学习笔记(转)

    Spring学习笔记(1)----简单的实例 ---------------------------------   首先需要准备Spring包,可从官方网站上下载.   下载解压后,必须的两个包是s ...

  8. 【Spring学习笔记-MVC-9】SpringMVC数据格式化之日期转换@DateTimeFormat

    作者:ssslinppp       1. 摘要 本文主要讲解Spring mvc数据格式化的具体步骤: 并讲解前台日期格式如何转换为java对象: 在之前的文章<[Spring学习笔记-MVC ...

  9. Spring学习笔记(一)

    Spring学习笔记(一) 这是一个沉淀的过程,大概第一次接触Spring是在去年的这个时候,当初在实训,初次接触Java web,直接学习SSM框架(当是Servlet都没有学),于是,养成了一个很 ...

随机推荐

  1. HTML5 学习笔记 应用程序缓存

    使用html5 通过创建cache manifest文件,可以轻松地创建web应用的离线版本. html5引入了应用程序缓存,这意味着web应用可进行缓存,并可在没有因特网连接时进行访问. 应用程序缓 ...

  2. C#指南,重温基础,展望远方!(7)C#结构

    结构是可以包含数据成员和函数成员的数据结构,这一点与类一样:与类不同的是,结构是值类型,无需进行堆分配. 结构类型的变量直接存储结构数据,而类类型的变量存储对动态分配的对象的引用. 结构类型不支持用户 ...

  3. Python 实现小数和百分数的相互转换

    # -*- coding: utf-8 -*- #百分比转换位小数 # -*- coding: utf-8 -*- s = '20%' # 默认要转换的百分比是字符串aa = float(s.stri ...

  4. jquery获取tr并更改tr内容

    jquery获取tr并更改tr内容示例代码. 例子: $(document).ready(function() { $("#Email tr").each(function(){ ...

  5. Atitit. 状态模式(State)attilax 总结 跟个策 略模式的区别

    Atitit. 状态模式(State)attilax 总结 跟个策 略模式的区别 1. 状态模式(State)概览 1 2. 状态的维护和转换:① 在Context 中.② 在状态的处理类中.2 3. ...

  6. nginx在用户使用ie的使用重定向到/nginx-MSIE目录下

    [root@web01 ]# cat /app/server/nginx/conf/rewrite/default.conf #rewrite ^/index\.html /index.php las ...

  7. CentOS7 安装 mplayer

    我google找到这个方法可以简单快速安装 mplayer 和 vlc,centos 7 only. Please google the latest release for the followin ...

  8. 219. Insert Node in Sorted Linked List【Naive】

    Insert a node in a sorted linked list. Example Given list = 1->4->6->8 and val = 5. Return  ...

  9. 孙源即将分享 DynamicCocoa 实现细节

    孙源即将分享 DynamicCocoa 实现细节   我的公众号之前发的一文中提到滴滴做了一个很牛逼的动态化方案 DynamicCocoa.该方案设计得非常精巧,解决了两种不同的语言在代码上如何等价生 ...

  10. jquery 情况form表单的所有内容

    #project_file_upload 为表单的id $(':input','#project_file_upload') .not(':button, :submit, :reset, :hidd ...