Spring学习笔记--使用注解装配

使用@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;
时间: 2024-12-22 21:52:03

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

spring学习笔记之——注解

spring注解可以很大的减少xml的配置,spring.xml文件的声明为: <?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

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

除了组件扫描与自动装配之外还有基于Java代码的装配与基于XML的装配. 有一些场景是我们不能用自动装配的,比如我们要给第三方库中的组件装配到我们的应用中,这时自动装配无效,因为自动装配只能扫描本应用中的包. 这时我们就要在基于代码代码的装配和基于XML的装配中进行选择,前面我们说到了JavaConfig相比XML更强大更安全. 一.基于Java代码的装配Bean(JavaConfig) 但是JavaConfig又与Java有所区别. 概念上  JavaConfig是配置 与应用的其他代码业务逻

不错的Spring学习笔记(转)

Spring学习笔记(1)----简单的实例 ---------------------------------   首先需要准备Spring包,可从官方网站上下载.   下载解压后,必须的两个包是spring.jar和commons-logging.jar.此外为了便于测试加入了JUnit包.   在Myeclipse中创建Java项目.   编写一个接口类,为了简单,只加入了一个方法.   Java代码   1.package com.szy.spring.interfacebean;  

Spring实战笔记2---Bean的装配

创建应用对象之间协作关系的行为通常成为装配,该篇的主要内容有两个,一个Spring装配Bean的几种方式以及Spring表达式,其实这两者是分不开的,在Spring中,对象无需自己负责查找或者创建与其关联的其他对象,相反容器负责把需要相互协作的对象一引用赋予各个对象,目前我们先说声明式的装配,注解式的装配等溜到下篇再详细记录,在声明用的xml配置文件中,可以使用表达式来完成一些简单的逻辑处理,和方法调用或者对象引用,在有些特殊的需求当中非它莫属,首先是装配Bean 声明Bean <bean id

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

作者:ssslinppp       1. 摘要 本文主要讲解Spring mvc数据格式化的具体步骤: 并讲解前台日期格式如何转换为java对象: 在之前的文章<[Spring学习笔记-MVC-8]SpringMVC之类型转换Converter>(对应链接: http://www.cnblogs.com/ssslinppp/p/4598102.html ) 中讲解了Spring MVC的类型转换,在此回顾下. 数据格式化,从本质上讲属于数据转换的范畴.Spring就是基于数据转换框架植入&q

Spring学习笔记(一)

Spring学习笔记(一) Spring核心思想: IOC:  Inversion Of Control (控制反转) / DI: Dependency Injection (依赖注入) AOP: Aspect Oriented Programming (面向切面编程) IOC 1. 简单的应用 Model package com.wangj.spring.model; public class User { private String username; private String pas

《Spring学习笔记》:Spring、Hibernate、struts2的整合(以例子来慢慢讲解,篇幅较长)

<Spring学习笔记>:Spring.Hibernate.struts2的整合(以例子来慢慢讲解,篇幅较长) 最近在看马士兵老师的关于Spring方面的视频,讲解的挺好的,到了Spring.Hibernate.struts2整合这里,由于是以例子的形式来对Spring+Hibernate+struts2这3大框架进行整合,因此,自己还跟着写代码的过程中,发现还是遇到了很多问题,因此,就记录下. 特此说明:本篇博文完全参考于马士兵老师的<Spring视频教程>. 本篇博文均以如下这

spring学习笔记(19)mysql读写分离后端AOP控制实例

在这里,我们接上一篇文章,利用JNDI访问应用服务器配置的两个数据源来模拟同时操作不同的数据库如同时操作mysql和oracle等.实际上,上个例子可能用来模拟mysql数据库主从配置读写分离更贴切些.既然如此,在本例中,我们就完成读写分离的模拟在web端的配置实例. 续上次的例子,关于JNDI数据源的配置和spring datasource的配置这里不再重复.下面着重加入AOP实现DAO层动态分库调用.可先看上篇文章<spring学习笔记(18)使用JNDI模拟访问应用服务器多数据源实例 >

Spring学习笔记(三)

Spring学习笔记(三) AOP 一.使用Annotation方式实现AOP.步骤: xml里加入配置:<aop:aspectj-autoproxy /> <?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org