• 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;
  • 相关阅读:
    洛谷P1196银河英雄传说
    NOIP2011普及组第三题瑞士轮(洛谷P1309)
    Dijkstra算法
    10.13做题——洛谷1449后缀表达式
    NOI题库(1.12.T3)甲流病人初筛
    10.12做题——NOI题库(1.13.T30)1的个数
    NOIP考试必备——随机数
    10.10做题——USACO1.2/洛谷1207回文平方数(Dual Palindromes)
    10.9做题——洛谷P1927防护伞
    10.9做题——USACO1.2/洛谷1206回文平方数(Palindromic Squares)
  • 原文地址:https://www.cnblogs.com/moonlightpoet/p/5572523.html
Copyright © 2020-2023  润新知