Spring二次学习——7、注解方式,注入依赖,这篇跟上一篇不同,有补充

https://blog.csdn.net/gavin_john/article/details/81051343

Spring注解配置

从 Spring 2.5 开始就可以使用注解来配置依赖注入。使用注解的方式使我们无需在XML中配置一个Bean引用,更加简单和方便。

注解配置默认情况下在Spring中是关闭的,我们需要在配置文件中使用<context:annotation-config/>激活它。

如下spring-config.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="http://www.springframework.org/schema/context"
       xsi:schemaLocation="
       http://www.springframework.org/schema/beans
       http://www.springframework.org/schema/beans/spring-beans.xsd
       http://www.springframework.org/schema/context
       http://www.springframework.org/schema/context/spring-context-3.0.xsd">

    <context:annotation-config/>

</beans>

  

一旦激活注解配置后,我们就可以在代码中使用注解来进行依赖注入。其中下面是几个重要的注解:

    @Required注解应用于bean属性的setter方法
    @Autowired注解可以应用到bean属性的setter方法,非setter方法,构造函数和属性
    @Qualifier,通过指定确切的将被引用的bean,@Autowired和@Qualifier注解可以用来删除混乱
    JSR-250 Annotations,Spring支持JSR-250的基础的注解,其中包括了@Resource,@PostContruct和@PreDestory注解

0.@Required注解

@Required注解应用于bean属性的setter方法,它表示受影响的bean属性在配置时必须放在XML配置文件中,否则容器就会抛出一个BeanInitializationException异常。

下面我们举一个例子来说明。我们在IDEA中创建Maven工程,并且引入Spring的几个核心库,包括:spring-core,spring-beans和spring-context。最后的项目工程如下:

这里写图片描述

pom.xml文件如下:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.gavin</groupId>
    <artifactId>spring-test</artifactId>
    <version>1.0-SNAPSHOT</version>

    <properties>
        <spring-version>5.0.4.RELEASE</spring-version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-core</artifactId>
            <version>${spring-version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-beans</artifactId>
            <version>${spring-version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>${spring-version}</version>
        </dependency>
    </dependencies>

</project>

  
  

我们在domain包下创建一个Person类,如下:

package com.gavin.domain;

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

public class Person {
    private String name;
    private int age;

    public String getName() {
        return name;
    }

    @Required
    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    @Required
    public void setAge(int age) {
        this.age = age;
    }

    public void sayHello() {
        System.out.println("Hello, my name is " + name + ", I'm " + age + " years old!");
    }
}

  

可以看到,我们使用@Required注解了属性name和age的两个setter方法setName()和setAge(),这表示我们在使用XML为Person类注入属性时必须注入这两个属性。

假如我们的spring-config.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="http://www.springframework.org/schema/context"
       xsi:schemaLocation="
       http://www.springframework.org/schema/beans
       http://www.springframework.org/schema/beans/spring-beans.xsd
       http://www.springframework.org/schema/context
       http://www.springframework.org/schema/context/spring-context-3.0.xsd">

    <context:annotation-config/>
    <bean id="person" class="com.gavin.domain.Person">
        <property name="age" value="20"/>
    </bean>

</beans>

    、

可以看到,我们在为Person注入属性时,只注入了age属性,那么创建Main类测试运行:

package com.gavin.test;

import com.gavin.domain.Person;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class Main {
    public static void main(String[] args) {
        ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring-config.xml");
        Person person = applicationContext.getBean("person", Person.class);
        person.sayHello();
    }
}

  

结果如下:

这里写图片描述

与我们预想的一致,报了BeanInitializationException异常。如果我们把name属性的@Required注解去掉再运行:

package com.gavin.domain;

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

public class Person {
    private String name;
    private int age;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    @Required
    public void setAge(int age) {
        this.age = age;
    }

    public void sayHello() {
        System.out.println("Hello, my name is " + name + ", I'm " + age + " years old!");
    }
}

这里写图片描述

程序不再报错了,但是name属性的值为null,因为我们没有在XML配置中为其注入值。

那么到这里就不难理解@Required注解的作用了。@Required注解用于注解属性的setter方法,如果一个属性的setter方法被@Required注解,则表示在XML配置中,该属性一定要注入值,否则会报异常。
1.@Autowired注解

@Autowired 注解对在哪里和如何完成自动连接提供了更多的细微的控制。
1.0 setter方法中的@Autowired

当Spring遇到一个在setter方法中使用的@Autowired注解,它会通过byType的方法自动为该属性注入值。不理解自动注入的,可以参考Spring——装配Bean。

我们在上例中进行扩充,首先新建domain对象Dog,如下:

package com.gavin.domain;

public class Dog {
    private String name;
    private String color;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getColor() {
        return color;
    }

    public void setColor(String color) {
        this.color = color;
    }

    @Override
    public String toString() {
        return "Dog{" +
                "name='" + name + '\'' +
                ", color='" + color + '\'' +
                '}';
    }
}

  

然后我们在Person类中添加Dog属性,表示Person拥有Dog,并添加setter方法,然后为setter方法添加@Autowired注解:

package com.gavin.domain;

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

public class Person {
    private String name;
    private int age;

    private Dog dog;

    @Autowired
    public void setDog(Dog dog) {
        this.dog = dog;
    }

    public String getName() {
        return name;
    }

    @Required
    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    @Required
    public void setAge(int age) {
        this.age = age;
    }

    public void sayHello() {
        System.out.println("Hello, my name is " + name + ", I'm " + age + " years old! I have a dog : " + dog);
    }
}

 

接着,我们在spring-config.xml中装配Dog对象,如下:

<?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.xsd
       http://www.springframework.org/schema/context
       http://www.springframework.org/schema/context/spring-context-3.0.xsd">

    <context:annotation-config/>
    <bean id="person" class="com.gavin.domain.Person">
        <property name="age" value="20"/>
        <property name="name" value="Gavin"/>
    </bean>

    <bean id="dog" class="com.gavin.domain.Dog">
        <property name="name" value="旺财"/>
        <property name="color" value="黄色"/>
    </bean>

</beans>

   

可以看到,我们在XML文件中,并没有为Person对象注入Dog的值,但是此时我们运行程序,得到结果:

这里写图片描述

运行结果完全正确,说明Spring自动为Person类注入了Dog属性,这正是@Autowired注解的作用。
1.1 属性中的@Autowired注解

我们可以直接在属性上运用@Autowired注解,这样我们可以无需为该属性写setter方法,Spring会自动为该属性注入值。所以如果我们在属性上运用@Autowired注解,那么Person类将变为:

package com.gavin.domain;

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

public class Person {
    private String name;
    private int age;
    @Autowired
    private Dog dog;

    public String getName() {
        return name;
    }

    @Required
    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    @Required
    public void setAge(int age) {
        this.age = age;
    }

    public void sayHello() {
        System.out.println("Hello, my name is " + name + ", I'm " + age + " years old! I have a dog : " + dog);
    }
}

  

此时再运行程序,我们可以发现如上面的例子一样,Spring会为我们自动装配Person类中的Dog属性的值。
1.2 构造方法中的@Autowired注解

此外,我们也可以在构造方法上使用@Autowired注解,假如我们在Person类添加构造方法,并为其添加Dog参数,在构造方法中初始化Dog属性,如下:

package com.gavin.domain;

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

public class Person {
    private String name;
    private int age;
    private Dog dog;

    @Autowired
    public Person(Dog dog) {
        this.dog = dog;
    }


    public String getName() {
        return name;
    }

    @Required
    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    @Required
    public void setAge(int age) {
        this.age = age;
    }

    public void sayHello() {
        System.out.println("Hello, my name is " + name + ", I'm " + age + " years old! I have a dog : " + dog);
    }
}

 

程序的运行结果依然是正确的。Spring为我们自动关联了Dog对象。
1.3 @Autowired属性的(required = false)选项

默认情况下,@Autowired注解意味着依赖是必须的,它类似于@Required注释,然而,你可以使用@Autowired的(required=false) 选项关闭默认行为。

假设我们在spring-config.xml中删除Dog的配置,如下:

<?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.xsd
       http://www.springframework.org/schema/context
       http://www.springframework.org/schema/context/spring-context-3.0.xsd">

    <context:annotation-config/>
    <bean id="person" class="com.gavin.domain.Person">
        <property name="age" value="20"/>
        <property name="name" value="Gavin"/>
    </bean>
</beans>

  

然后我们在Person类中使用@Autowired注解Dog属性,如下:

package com.gavin.domain;

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

public class Person {
    private String name;
    private int age;

    @Autowired
    private Dog dog;

    public String getName() {
        return name;
    }

    @Required
    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    @Required
    public void setAge(int age) {
        this.age = age;
    }

    public void sayHello() {
        System.out.println("Hello, my name is " + name + ", I'm " + age + " years old! I have a dog : " + dog);
    }
}

 

运行程序,得到异常结果:

这里写图片描述

此时如果我们为@Autowired加上(required = false)属性,则表示Dog属性不是必须的:

package com.gavin.domain;

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

public class Person {
    private String name;
    private int age;

    @Autowired(required = false)
    private Dog dog;

    public String getName() {
        return name;
    }

    @Required
    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    @Required
    public void setAge(int age) {
        this.age = age;
    }

    public void sayHello() {
        System.out.println("Hello, my name is " + name + ", I'm " + age + " years old! I have a dog : " + dog);
    }
}

 

再次运行程序,我们就可以得到正常的运行结果,只是Dog属性为null而已:

这里写图片描述

至此,@Autowired注解的用法就介绍完毕了。
2.@Qualifier注解

有时候会出现这样一种情况,当我们创建多个具有相同类型的bean时,并且想要用一个属性只为它们其中的一个进行装配,在这种情况下,我们可以结合使用@Qualifier和@Autowired注解通过指定哪一个真正的bean将会被装配来消除混乱。

我们依然使用上面的例子来介绍。

首先Dog类仍然如下:

package com.gavin.domain;

public class Dog {
    private String name;
    private String color;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getColor() {
        return color;
    }

    public void setColor(String color) {
        this.color = color;
    }

    @Override
    public String toString() {
        return "Dog{" +
                "name='" + name + '\'' +
                ", color='" + color + '\'' +
                '}';
    }
}

 

此时,我们在spring-config.xml文件中配置两个Dog,dog1和dog2,如下所示:

<?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.xsd
       http://www.springframework.org/schema/context
       http://www.springframework.org/schema/context/spring-context-3.0.xsd">

    <context:annotation-config/>
    <bean id="person" class="com.gavin.domain.Person">
        <property name="age" value="20"/>
        <property name="name" value="Gavin"/>
    </bean>

    <bean id="dog1" class="com.gavin.domain.Dog">
        <property name="name" value="大黄"/>
        <property name="color" value="黄色"/>
    </bean>

    <bean id="dog2" class="com.gavin.domain.Dog">
        <property name="name" value="小黑"/>
        <property name="color" value="黑色"/>
    </bean>

</beans>

  

假设我们Person类没变,其包含Dog属性,并且使用@Autowired指定其自动装配,那么此时编译器就会报错,因为我们配置了两个Dog对象,它不知道具体要装配哪个Dog对象。所以我们可以使用@Qualifier注解来指定装配的是具体哪一个对象。如下:

package com.gavin.domain;

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

public class Person {
    private String name;
    private int age;

    @Autowired
    @Qualifier("dog1")
    private Dog dog;

    public String getName() {
        return name;
    }

    @Required
    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    @Required
    public void setAge(int age) {
        this.age = age;
    }

    public void sayHello() {
        System.out.println("Hello, my name is " + name + ", I'm " + age + " years old! I have a dog : " + dog);
    }
}

我们指定了其装配的是dog1,所以程序运行结果如下:

这里写图片描述
3.JSR-250注解

在2.5版本中,Spring框架的核心(core)现在支持以下JSR-250注解:

    @PostContruct
    @PreDestory
    @Resource

3.0 @PostConstruct和@PreDestroy注解

在spring-config.xml文件配置中,为了定义一个bean的安装和卸载,我们可以使用init-method和destroy-method参数声明。init-method属性指定了一个方法,该方法在bean实例化之后会被立即调用。同样地,destroy-method指定了一个方法,该方法在一个bean从容器中删除之前被调用。

我们可以使用@PostConstruct注解作为初始化回调方法的一个替代,@PreDestroy注解作为销毁回调方法的一个替代。

我们在上例的基础上做扩充,首先我们创建HelloService类,如下:

package com.gavin.service;

import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;

public class HelloService {
    private String message;

    public HelloService() {
        System.out.println("Inside the constructor");
    }

    public void setMessage(String message) {
        this.message = message;
    }

    public String getMessage() {
        return message;
    }

    @PostConstruct
    public void init(){
        System.out.println("构造方法正在被执行...");
    }

    @PreDestroy
    public void destory(){
        System.out.println("Bean正在被销毁...");
    }
}

  

我们通过@PostConstruct注解和@PreDestory注解指定了初始化回调方法和销毁回调方法。

接着,我们在XML配置文件中装配HelloService,如下:

<bean id="helloService" class="com.gavin.service.HelloService">
    <property name="message" value="Hello, World!"/>
</bean>

  

将主方法更改如下:

package com.gavin.test;

import com.gavin.domain.Person;
import com.gavin.service.HelloService;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class Main {
    public static void main(String[] args) {
        ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring-config.xml");
        // Person person = applicationContext.getBean("person", Person.class);
        // person.sayHello();

        HelloService helloService = applicationContext.getBean("helloService", HelloService.class);
        System.out.println(helloService.getMessage());
        ((ClassPathXmlApplicationContext) applicationContext).registerShutdownHook();
    }
}

   

这里,我们需要注册一个关闭钩registerShutdownHook()方法,该方法在 AbstractApplicationContext类中被声明。这将确保一个完美的关闭并调用相关的销毁方法。

运行结果如下:

这里写图片描述
3.1 @Resource注解

我们可以在字段中或者setter方法中使用@Resource注解,它使用一个name属性,该属性以一个bean名称的形式被注入,也就是说,它遵循byName形式的自动装配。

比如我们在上面的例子中使用了@Autowired与@Qualifier注解的结合:

public class Person {
    private String name;
    private int age;

    @Autowired
    @Qualifier("dog1")
    private Dog dog;

    // ...
}

 

在这里,我们也可以使用@Resource注解,效果是一样的,写法如下:

public class Person {
    private String name;
    private int age;

    @Resource(name = "dog1")
    private Dog dog;

    // ...
}

   

@Resource与@Autowired注解的用法很类似,它们的区别如下:

    @Autowired注解为Spring提供的注解,只按照byType方式注入,默认情况下,它要求依赖对象必须存在,如果允许为null,可以设置它的required属性为false,如果我们想按照byName方式来装配,可以结合@Qualifier注解一起使用;
    @Resource为J2EE提供的注解,它有两个重要的属性:name和type。而默认情况下,@Resource注解按照byName的方式来装配。@Resource的装配顺序是这样的:
        如果同时指定了name和type,则从Spring上下文中找到唯一匹配的bean进行装配,找不到则抛出异常。
        如果指定了name,则从上下文中查找名称(id)匹配的bean进行装配,找不到则抛出异常。
        如果指定了type,则从上下文中找到类型匹配的唯一bean进行装配,找不到或是找到多个,都会抛出异常。
        如果既没有指定name,又没有指定type,则自动按照byName方式进行装配;如果没有匹配,则回退为一个原始类型进行匹配,如果匹配则自动装配。

    个人认为,统一使用Spring提供的注解比较好,也就是我们更偏向于使用@Autowired注解,特殊情况下使用@Autowired与@Qualifier注解的结合即可。
————————————————
版权声明:本文为CSDN博主「KLeonard」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/gavin_john/article/details/81051343

 

 

//以下内容中的@resouce貌似是有一些问题的

注解实现Bean依赖注入

12.2.1  概述

       注解实现Bean配置主要用来进行如依赖注入、生命周期回调方法定义等,不能消除XML文件中的Bean元数据定义,且基于XML配置中的依赖注入的数据将覆盖基于注解配置中的依赖注入的数据

 

Spring3的基于注解实现Bean依赖注入支持如下三种注解:

  • Spring自带依赖注入注解: Spring自带的一套依赖注入注解;
  • JSR-250注解:Java平台的公共注解,是Java EE 5规范之一,在JDK6中默认包含这些注解,从Spring2.5开始支持。
  • JSR-330注解:Java 依赖注入标准,Java EE 6规范之一,可能在加入到未来JDK版本,从Spring3开始支持;
  • JPA注解:用于注入持久化上下文和尸体管理器。

 

这三种类型的注解在Spring3中都支持,类似于注解事务支持,想要使用这些注解需要在Spring容器中开启注解驱动支持,即使用如下配置方式开启:

 

java代码:Java代码

 收藏代码

  1. <beans xmlns="http://www.springframework.org/schema/beans"  
  2.     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  
  3.     xmlns:context="http://www.springframework.org/schema/context"  
  4.     xsi:schemaLocation=" http://www.springframework.org/schema/beans  
  5.        http://www.springframework.org/schema/beans/spring-beans-3.0.xsd  
  6.        http://www.springframework.org/schema/context  
  7.        http://www.springframework.org/schema/context/spring-context-3.0.xsd">  
  8.   
  9.     <context:annotation-config/>  
  10.   
  11. </beans>  
  12.    
  13.    

   这样就能使用注解驱动依赖注入了,该配置文件位于“resources/ chapter12/dependecyInjectWithAnnotation.xml”。

 

12.2.2  Spring自带依赖注入注解

一、@Required:依赖检查;

对应于基于XML配置中的依赖检查,但XML配置的依赖检查将检查所有setter方法,详见【3.3.4  依赖检查】;

基于@Required的依赖检查表示注解的setter方法必须,即必须通过在XML配置中配置setter注入,如果没有配置在容器启动时会抛出异常从而保证在运行时不会遇到空指针异常,@Required只能放置在setter方法上,且通过XML配置的setter注入,可以使用如下方式来指定:

 

java代码:Java代码

 收藏代码

  1. @Requried  
  2. setter方法  

 

1、准备测试Bean

 

java代码:Java代码

 收藏代码

  1. package cn.javass.spring.chapter12;  
  2. public class TestBean {  
  3.     private String message;  
  4.     @Required  
  5.     public void setMessage(String message) {  
  6.         this.message = message;  
  7.     }  
  8.     public String getMessage() {  
  9.         return message;  
  10.     }  
  11. }  

 

 

2、在Spring配置文件(chapter12/dependecyInjectWithAnnotation.xml)添加如下Bean配置:

 

java代码:Java代码

 收藏代码

  1. <bean id="testBean" class="cn.javass.spring.chapter12.TestBean">  
  2. <property name="message" ref="message"/>  
  3. </bean>  
  4. <bean id="message" class="java.lang.String">  
  5.     <constructor-arg index="0" value="hello"/>  
  6. </bean>  

 

3、测试类和测试方法如下:

 

java代码:Java代码

 收藏代码

  1. package cn.javass.spring.chapter12;  
  2. //省略import  
  3. public class DependencyInjectWithAnnotationTest {  
  4.     private static String configLocation = "classpath:chapter12/dependecyInjectWithAnnotation.xml";  
  5.     private static ApplicationContext ctx = new ClassPathXmlApplicationContext(configLocation);  
  6.     //1、Spring自带依赖注入注解  
  7.      @Test  
  8.     public void testRequiredForXmlSetterInject() {  
  9.         TestBean testBean = ctx.getBean("testBean", TestBean.class);  
  10.         Assert.assertEquals("hello", testBean.getMessage());  
  11.     }  
  12. }  

 

在XML配置文件中必须指定setter注入,否则在Spring容器启动时将抛出如下异常:

 

java代码:Java代码

 收藏代码

  1. org.springframework.beans.factory.BeanCreationException:  
  2. Error creating bean with name 'testBean' defined in class path resource [chapter12/dependecyInjectWithAnnotation.xml]: Initialization of bean failed;  
  3. nested exception is org.springframework.beans.factory.BeanInitializationException: Property 'message' is required for bean 'testBean'  

 

 

 

 

二、@Autowired:自动装配

自动装配,用于替代基于XML配置的自动装配,详见【3.3.3  自动装配】。

 

基于@Autowired的自动装配,默认是根据类型注入,可以用于构造器、字段、方法注入,使用方式如下:

 

java代码:Java代码

 收藏代码

  1. @Autowired(required=true)  
  2. 构造器、字段、方法  

 

@Autowired默认是根据参数类型进行自动装配,且必须有一个Bean候选者注入,如果允许出现0个Bean候选者需要设置属性“required=false”,“required”属性含义和@Required一样,只是@Required只适用于基于XML配置的setter注入方式。

 

(1)、构造器注入:通过将@Autowired注解放在构造器上来完成构造器注入,默认构造器参数通过类型自动装配,如下所示:

 

1、准备测试Bean,在构造器上添加@AutoWired注解:

 

java代码:Java代码

 收藏代码

  1. package cn.javass.spring.chapter12;  
  2. import org.springframework.beans.factory.annotation.Autowired;  
  3. public class TestBean11 {  
  4.     private String message;  
  5.     @Autowired //构造器注入  
  6.     private TestBean11(String message) {  
  7.         this.message = message;  
  8.     }  
  9.     //省略message的getter和setter  
  10. }  

 

 

2、在Spring配置文件(chapter12/dependecyInjectWithAnnotation.xml)添加如下Bean配置:

 

java代码:Java代码

 收藏代码

  1. <bean id="testBean11" class="cn.javass.spring.chapter12.TestBean11"/>  

 

3、测试类如下:

 

java代码:Java代码

 收藏代码

  1. @Test  
  2. public void testAutowiredForConstructor() {  
  3.     TestBean11 testBean11 = ctx.getBean("testBean11", TestBean11.class);  
  4.     Assert.assertEquals("hello", testBean11.getMessage());  
  5. }  

    在Spring配置文件中没有对“testBean11”进行构造器注入和setter注入配置,而是通过在构造器上添加@ Autowired来完成根据参数类型完成构造器注入。

 

 

 

(2)、字段注入:通过将@Autowired注解放在构造器上来完成字段注入。

 

1、准备测试Bean,在字段上添加@AutoWired注解:

 

java代码:Java代码

 收藏代码

  1. package cn.javass.spring.chapter12;  
  2. import org.springframework.beans.factory.annotation.Autowired;  
  3. public class TestBean12 {  
  4.     @Autowired //字段注入  
  5.     private String message;  
  6.     //省略getter和setter  
  7. }  

 

 

2、在Spring配置文件(chapter12/dependecyInjectWithAnnotation.xml)添加如下Bean配置:

 

java代码:Java代码

 收藏代码

  1. <bean id="testBean12" class="cn.javass.spring.chapter12.TestBean12"/>  

 

3、测试方法如下:

 

java代码:Java代码

 收藏代码

  1. @Test  
  2. public void testAutowiredForField() {  
  3.     TestBean12 testBean12 = ctx.getBean("testBean12", TestBean12.class);  
  4.     Assert.assertEquals("hello", testBean12.getMessage());  
  5. }  

    字段注入在基于XML配置中无相应概念,字段注入不支持静态类型字段的注入。

 

 

(3)、方法参数注入:通过将@Autowired注解放在方法上来完成方法参数注入。

 

1、准备测试Bean,在方法上添加@AutoWired注解:

 

java代码:Java代码

 收藏代码

  1. package cn.javass.spring.chapter12;  
  2. import org.springframework.beans.factory.annotation.Autowired;  
  3. public class TestBean13 {  
  4.     private String message;  
  5.     @Autowired //setter方法注入  
  6.     public void setMessage(String message) {  
  7.         this.message = message;  
  8.     }  
  9.     public String getMessage() {  
  10.         return message;  
  11.     }  
  12. }  

 

 

 

java代码:Java代码

 收藏代码

  1. package cn.javass.spring.chapter12;  
  2. //省略import  
  3. public class TestBean14 {  
  4.     private String message;  
  5.     private List<String> list;  
  6.     @Autowired(required = true) //任意一个或多个参数方法注入  
  7.     private void initMessage(String message, ArrayList<String> list) {  
  8.         this.message = message;  
  9.         this.list = list;  
  10.     }  
  11.     //省略getter和setter  
  12. }  

 

2、在Spring配置文件(chapter12/dependecyInjectWithAnnotation.xml)添加如下Bean配置:

 

java代码:Java代码

 收藏代码

  1. <bean id="testBean13" class="cn.javass.spring.chapter12.TestBean13"/>  
  2. <bean id="testBean14" class="cn.javass.spring.chapter12.TestBean14"/>  
  3. <bean id="list" class="java.util.ArrayList">  
  4.     <constructor-arg index="0">  
  5.         <list>  
  6.             <ref bean="message"/>  
  7.             <ref bean="message"/>  
  8.         </list>  
  9.    </constructor-arg>          
  10. </bean>  

 

3、测试方法如下:

 

java代码:Java代码

 收藏代码

  1. @Test  
  2. public void testAutowiredForMethod() {  
  3.     TestBean13 testBean13 = ctx.getBean("testBean13", TestBean13.class);  
  4.     Assert.assertEquals("hello", testBean13.getMessage());  
  5.    
  6.     TestBean14 testBean14 = ctx.getBean("testBean14", TestBean14.class);  
  7.     Assert.assertEquals("hello", testBean14.getMessage());  
  8.     Assert.assertEquals(ctx.getBean("list", List.class), testBean14.getList());  
  9. }  
  10.    

 

方法参数注入除了支持setter方法注入,还支持1个或多个参数的普通方法注入,在基于XML配置中不支持1个或多个参数的普通方法注入,方法注入不支持静态类型方法的注入。

 

注意“initMessage(String message, ArrayList<String> list)”方法签名中为什么使用ArrayList而不是List呢?具体参考【3.3.3  自动装配】一节中的集合类型注入区别。

 

 

 

 

 

三、@Value:注入SpEL表达式;

 

用于注入SpEL表达式,可以放置在字段方法或参数上,使用方式如下:

 

java代码:Java代码

 收藏代码

  1. @Value(value = "SpEL表达式")  
  2. 字段、方法、参数  

 

1、可以在类字段上使用该注解:

 

java代码:Java代码

 收藏代码

  1. @Value(value = "#{message}")  
  2. private String message;  

 

2、可以放置在带@Autowired注解的方法的参数上:

 

java代码:Java代码

 收藏代码

  1. @Autowired  
  2. public void initMessage(@Value(value = "#{message}#{message}") String message) {  
  3.     this.message = message;  
  4. }  

 

3、还可以放置在带@Autowired注解的构造器的参数上:

 

java代码:Java代码

 收藏代码

  1. @Autowired  
  2. private TestBean43(@Value(value = "#{message}#{message}") String message) {  
  3.     this.message = message;  
  4. }  

    具体测试详见DependencyInjectWithAnnotationTest 类的testValueInject测试方法。

 

 

 

 

四、@Qualifier:限定描述符,用于细粒度选择候选者;

 

@Autowired默认是根据类型进行注入的,因此如果有多个类型一样的Bean候选者,则需要限定其中一个候选者,否则将抛出异常,详见【3.3.3  自动装配】中的根据类型进行注入;

 

@Qualifier限定描述符除了能根据名字进行注入,但能进行更细粒度的控制如何选择候选者,具体使用方式如下:

 

java代码:Java代码

 收藏代码

  1. @Qualifier(value = "限定标识符")  
  2. 字段、方法、参数  

 

(1)、根据基于XML配置中的<qualifier>标签指定的名字进行注入,使用如下方式指定名称:

 

java代码:Java代码

 收藏代码

  1. <qualifier  type="org.springframework.beans.factory.annotation.Qualifier"  value="限定标识符"/>  

 

其中type属性可选,指定类型,默认就是Qualifier注解类,name就是给Bean候选者指定限定标识符,一个Bean定义中只允许指定类型不同的<qualifier>,如果有多个相同type后面指定的将覆盖前面的。

 

 

1、准备测试Bean:

 

java代码:Java代码

 收藏代码

  1. package cn.javass.spring.chapter12;  
  2. import javax.sql.DataSource;  
  3. import org.springframework.beans.factory.annotation.Autowired;  
  4. import org.springframework.beans.factory.annotation.Qualifier;  
  5.   
  6. public class TestBean31 {  
  7.     private DataSource dataSource;  
  8.     @Autowired  
  9.     //根据<qualifier>标签指定Bean限定标识符  
  10.     public void initDataSource(@Qualifier("mysqlDataSource") DataSource dataSource) {  
  11.         this.dataSource = dataSource;  
  12.     }  
  13.     public DataSource getDataSource() {  
  14.         return dataSource;  
  15.     }  
  16. }  

 

2、在Spring配置文件(chapter12/dependecyInjectWithAnnotation.xml)添加如下Bean配置:

 

java代码:Java代码

 收藏代码

  1. <bean id="testBean31" class="cn.javass.spring.chapter12.TestBean31"/>  

 

我们使用@Qualifier("mysqlDataSource")来指定候选Bean的限定标识符,我们需要在配置文件中使用<qualifier>标签来指定候选Bean的限定标识符“mysqlDataSource”:

 

java代码:Java代码

 收藏代码

  1. <bean id="mysqlDataSourceBean" class="org.springframework.jdbc.datasource.DriverManagerDataSource">  
  2.      <qualifier value="mysqlDataSource"/>  
  3. </bean>  

 

3、测试方法如下:

 

java代码:Java代码

 收藏代码

  1. @Test  
  2. public void testQualifierInject1() {  
  3.     TestBean31 testBean31 = ctx.getBean("testBean31", TestBean31.class);  
  4.     try {  
  5.         //使用<qualifier>指定的标识符只能被@Qualifier使用  
  6.         ctx.getBean("mysqlDataSource");  
  7.         Assert.fail();  
  8.     } catch (Exception e) {  
  9.         //找不到该Bean  
  10.         Assert.assertTrue(e instanceof NoSuchBeanDefinitionException);  
  11.     }  
  12.      Assert.assertEquals(ctx.getBean("mysqlDataSourceBean"), testBean31.getDataSource());  
  13. }  

从测试可以看出使用<qualifier>标签指定的限定标识符只能被@Qualifier使用,不能作为Bean的标识符,如“ctx.getBean("mysqlDataSource")”是获取不到Bean的。

 

 

(2)、缺省的根据Bean名字注入:最基本方式,是在Bean上没有指定<qualifier>标签时一种容错机制,即缺省情况下使用Bean标识符注入,但如果你指定了<qualifier>标签将不会发生容错。

 

1、准备测试Bean:

 

java代码:Java代码

 收藏代码

  1. package cn.javass.spring.chapter12;  
  2. //省略import  
  3. public class TestBean32 {  
  4.     private DataSource dataSource;  
  5.     @Autowired  
  6.     @Qualifier(value = "mysqlDataSource2") //指定Bean限定标识符  
  7.     //@Qualifier(value = "mysqlDataSourceBean")  
  8.     //是错误的注入,不会发生回退容错,因为你指定了<qualifier>  
  9.     public void initDataSource(DataSource dataSource) {  
  10.         this.dataSource = dataSource;  
  11.     }  
  12.     public DataSource getDataSource() {  
  13.         return dataSource;  
  14.     }  
  15. }  
  16.    

 

 

2、在Spring配置文件(chapter12/dependecyInjectWithAnnotation.xml)添加如下Bean配置:

 

java代码:Java代码

 收藏代码

  1. <bean id="testBean32" class="cn.javass.spring.chapter12.TestBean32"/>  
  2. <bean id="oracleDataSource"  class="org.springframework.jdbc.datasource.DriverManagerDataSource"/>  

 

3、测试方法如下:

 

java代码:Java代码

 收藏代码

  1. @Test  
  2. public void testQualifierInject2() {  
  3.     TestBean32 testBean32 = ctx.getBean("testBean32", TestBean32.class);  
  4.     Assert.assertEquals(ctx.getBean("oracleDataSource"), testBean32.getDataSource());  
  5. }  

 

默认情况下(没指定<qualifier>标签)@Qualifier的value属性将匹配Bean 标识符。

 

 

(3)、扩展@Qualifier限定描述符注解:对@Qualifier的扩展来提供细粒度选择候选者;

 

具体使用方式就是自定义一个注解并使用@Qualifier注解其即可使用。

 

首先让我们考虑这样一个问题,如果我们有两个数据源,分别为Mysql和Oracle,因此注入两者相关资源时就牵扯到数据库相关,如在DAO层注入SessionFactory时,当然可以采用前边介绍的方式,但为了简单和直观我们希望采用自定义注解方式。

 

1、扩展@Qualifier限定描述符注解来分别表示Mysql和Oracle数据源

 

java代码:Java代码

 收藏代码

  1. package cn.javass.spring.chapter12.qualifier;  
  2. import org.springframework.beans.factory.annotation.Qualifier;  
  3. /** 表示注入Mysql相关 */  
  4. @Target({ElementType.TYPE, ElementType.FIELD, ElementType.PARAMETER})  
  5. @Retention(RetentionPolicy.RUNTIME)  
  6. @Qualifier  
  7. public @interface Mysql {  
  8. }  

 

 

java代码:Java代码

 收藏代码

  1. package cn.javass.spring.chapter12.qualifier;  
  2. import org.springframework.beans.factory.annotation.Qualifier;  
  3. /** 表示注入Oracle相关 */  
  4. @Target({ElementType.TYPE, ElementType.FIELD, ElementType.PARAMETER})  
  5. @Retention(RetentionPolicy.RUNTIME)  
  6. @Qualifier  
  7. public @interface Oracle {  
  8. }  

 

 

2、准备测试Bean:

 

java代码:Java代码

 收藏代码

  1. package cn.javass.spring.chapter12;  
  2. //省略import  
  3. public class TestBean33 {  
  4.     private DataSource mysqlDataSource;  
  5.     private DataSource oracleDataSource;  
  6.     @Autowired  
  7.     public void initDataSource(@Mysql DataSource mysqlDataSource, @Oracle DataSource oracleDataSource) {  
  8.         this.mysqlDataSource = mysqlDataSource;  
  9.         this.oracleDataSource = oracleDataSource;  
  10.     }  
  11.     public DataSource getMysqlDataSource() {  
  12.         return mysqlDataSource;  
  13.     }  
  14.     public DataSource getOracleDataSource() {  
  15.         return oracleDataSource;  
  16.     }  
  17. }  

 

 

3、在Spring配置文件(chapter12/dependecyInjectWithAnnotation.xml)添加如下Bean配置:

 

java代码:Java代码

 收藏代码

  1. <bean id="testBean33" class="cn.javass.spring.chapter12.TestBean33"/>  

 

4、在Spring修改定义的两个数据源:

 

java代码:Java代码

 收藏代码

  1. <bean id="mysqlDataSourceBean" class="org.springframework.jdbc.datasource.DriverManagerDataSource">  
  2.      <qualifier value="mysqlDataSource"/>  
  3.      <qualifier type="cn.javass.spring.chapter12.qualifier.Mysql"/>  
  4. </bean>  
  5. <bean id="oracleDataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">  
  6.       <qualifier type="cn.javass.spring.chapter12.qualifier.Oracle"/>  
  7. </bean>  

 

5、测试方法如下:

 

java代码:Java代码

 收藏代码

  1. @Test  
  2. public void testQualifierInject3() {  
  3.     TestBean33 testBean33 = ctx.getBean("testBean33", TestBean33.class);  
  4.     Assert.assertEquals(ctx.getBean("mysqlDataSourceBean"), testBean33.getMysqlDataSoruce());  
  5.     Assert.assertEquals(ctx.getBean("oracleDataSource"), testBean33.getOracleDataSoruce());  
  6. }  

 

测试也通过了,说明我们扩展的@Qualifier限定描述符注解也能很好工作。

 

 

前边演示了不带属性的注解,接下来演示一下带参数的注解:

 

1、首先定义数据库类型:

 

java代码:Java代码

 收藏代码

  1. package cn.javass.spring.chapter12.qualifier;  
  2. public enum DataBase {  
  3.     ORACLE, MYSQL;  
  4. }  

 

2、其次扩展@Qualifier限定描述符注解

 

java代码:Java代码

 收藏代码

  1. package cn.javass.spring.chapter12.qualifier;  
  2. //省略import  
  3. @Target({ElementType.TYPE, ElementType.FIELD, ElementType.PARAMETER})  
  4. @Retention(RetentionPolicy.RUNTIME)  
  5. @Qualifier  
  6. public @interface DataSourceType {  
  7.     String ip();      //指定ip,用于多数据源情况  
  8.     DataBase database();//指定数据库类型  
  9. }  

 

3、准备测试Bean:

 

java代码:Java代码

 收藏代码

  1. package cn.javass.spring.chapter12;  
  2. import javax.sql.DataSource;  
  3. import org.springframework.beans.factory.annotation.Autowired;  
  4. import cn.javass.spring.chapter12.qualifier.DataBase;  
  5. import cn.javass.spring.chapter12.qualifier.DataSourceType;  
  6. public class TestBean34 {  
  7.     private DataSource mysqlDataSource;  
  8.     private DataSource oracleDataSource;  
  9.     @Autowired  
  10.     public void initDataSource(  
  11.             @DataSourceType(ip="localhost", database=DataBase.MYSQL)  
  12.             DataSource mysqlDataSource,  
  13.             @DataSourceType(ip="localhost", database=DataBase.ORACLE)  
  14.             DataSource oracleDataSource) {  
  15.         this.mysqlDataSource = mysqlDataSource;  
  16.         this.oracleDataSource = oracleDataSource;  
  17.     }  
  18.       //省略getter方法    
  19. }  

 

4、在Spring配置文件(chapter12/dependecyInjectWithAnnotation.xml)添加如下Bean配置:

 

java代码:Java代码

 收藏代码

  1. <bean id="testBean34" class="cn.javass.spring.chapter12.TestBean34"/>  

 

5、在Spring修改定义的两个数据源:

 

java代码:Java代码

 收藏代码

  1. <bean id="mysqlDataSourceBean" class="org.springframework.jdbc.datasource.DriverManagerDataSource">  
  2.     <qualifier value="mysqlDataSource"/>  
  3.     <qualifier type="cn.javass.spring.chapter12.qualifier.Mysql"/>  
  4.     <qualifier type="cn.javass.spring.chapter12.qualifier.DataSourceType">  
  5.         <attribute key="ip" value="localhost"/>  
  6.         <attribute key="database" value="MYSQL"/>  
  7.     </qualifier>  
  8. </bean>  
  9. <bean id="oracleDataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">  
  10.     <qualifier type="cn.javass.spring.chapter12.qualifier.Oracle"/>  
  11.     <qualifier type="cn.javass.spring.chapter12.qualifier.DataSourceType">  
  12.         <attribute key="ip" value="localhost"/>  
  13.         <attribute key="database" value="ORACLE"/>  
  14.     </qualifier>  
  15. </bean>  

 

6、测试方法如下:

 

java代码:Java代码

 收藏代码

  1. @Test  
  2. public void testQualifierInject3() {  
  3.     TestBean34 testBean34 = ctx.getBean("testBean34", TestBean34.class);  
  4.     Assert.assertEquals(ctx.getBean("mysqlDataSourceBean"), testBean34.getMysqlDataSource());  
  5.     Assert.assertEquals(ctx.getBean("oracleDataSource"), testBean34.getOracleDataSoruce());  
  6. }  

  测试也通过了,说明我们扩展的@Qualifier限定描述符注解也能很好工作。

 

  

 

四、自定义注解限定描述符:完全不使用@Qualifier,而是自己定义一个独立的限定注解;

 

1、首先使用如下方式定义一个自定义注解限定描述符:

 

java代码:Java代码

 收藏代码

  1. package cn.javass.spring.chapter12.qualifier;  
  2. //省略import  
  3. @Target({ElementType.TYPE, ElementType.FIELD, ElementType.PARAMETER})  
  4. @Retention(RetentionPolicy.RUNTIME)  
  5. public @interface CustomQualifier {  
  6.     String value();  
  7. }  

 

 

2、准备测试Bean:

 

java代码:Java代码

 收藏代码

  1. package cn.javass.spring.chapter12;  
  2. //省略import  
  3. public class TestBean35 {  
  4.     private DataSource dataSoruce;  
  5.     @Autowired  
  6.     public TestBean35(@CustomQualifier("oracleDataSource") DataSource dataSource) {  
  7.         this.dataSoruce = dataSource;  
  8.     }  
  9.     public DataSource getDataSoruce() {  
  10.         return dataSoruce;  
  11.     }  
  12. }  

 

3、在Spring配置文件(chapter12/dependecyInjectWithAnnotation.xml)添加如下Bean配置:

 

java代码:Java代码

 收藏代码

  1. <bean id="testBean35" class="cn.javass.spring.chapter12.TestBean35"/>  

 

4、然后在Spring配置文件中注册CustomQualifier自定义注解限定描述符,只有注册了Spring才能识别:

 

java代码:Java代码

 收藏代码

  1. <bean id="customAutowireConfigurer" class="org.springframework.beans.factory.annotation.CustomAutowireConfigurer">  
  2.     <property name="customQualifierTypes">  
  3.         <set>  
  4.             <value>cn.javass.spring.chapter12.qualifier.CustomQualifier</value>  
  5.         </set>  
  6.    </property>  
  7. </bean>  

 

5、测试方法如下:

 

java代码:Java代码

 收藏代码

  1. @Test  
  2. public void testQualifierInject5() {  
  3.     TestBean35 testBean35 = ctx.getBean("testBean35", TestBean35.class);  
  4.     Assert.assertEquals(ctx.getBean("oracleDataSource"), testBean35.getDataSource());  
  5. }  

    从测试中可看出,自定义的和Spring自带的没什么区别,因此如果没有足够的理由请使用Spring自带的Qualifier注解。

 

    到此限定描述符介绍完毕,在此一定要注意以下几点:

  • 限定标识符和Bean的描述符是不一样的;
  • 多个Bean定义中可以使用相同的限定标识符;
  • 对于集合、数组、字典类型的限定描述符注入,将注入多个具有相同限定标识符的Bean。

 

 

 

 

12.2.3  JSR-250注解

一、@Resource:自动装配,默认根据类型装配,如果指定name属性将根据名字装配,可以使用如下方式来指定:

 

java代码:Java代码

 收藏代码

  1. @Resource(name = "标识符")  
  2. 字段或setter方法  

 

1、准备测试Bean:

 

java代码:Java代码

 收藏代码

  1. package cn.javass.spring.chapter12;  
  2. import javax.annotation.Resource;  
  3. public class TestBean41 {  
  4.     @Resource(name = "message")  
  5.     private String message;  
  6.     //省略getter和setter  
  7. }  

 

 

2、在Spring配置文件(chapter12/dependecyInjectWithAnnotation.xml)添加如下Bean配置:

 

java代码:Java代码

 收藏代码

  1. <bean id="testBean41" class="cn.javass.spring.chapter12.TestBean41"/>  

 

3、测试方法如下: 

 

java代码:Java代码

 收藏代码

  1. @Test  
  2. public void testResourceInject1() {  
  3.     TestBean41 testBean41 = ctx.getBean("testBean41", TestBean41.class);  
  4.     Assert.assertEquals("hello", testBean41.getMessage());  
  5. }  

    使用非常简单,和@Autowired不同的是可以指定name来根据名字注入。

 

    使用@Resource需要注意以下几点:

  • @Resource注解应该只用于setter方法注入,不能提供如@Autowired多参数方法注入;
  • @Resource在没有指定name属性的情况下首先将根据setter方法对于的字段名查找资源,如果找不到再根据类型查找;
  • @Resource首先将从JNDI环境中查找资源,如果没找到默认再到Spring容器中查找,因此如果JNDI环境中有和Spring容器同名的资源时需要注意。

 

 

二、@PostConstruct和PreDestroy:通过注解指定初始化和销毁方法定义;

 

1、在测试类TestBean41中添加如下代码:

 

java代码:Java代码

 收藏代码

  1. @PostConstruct  
  2. public void init() {  
  3.     System.out.println("==========init");  
  4. }  
  5. @PreDestroy  
  6. public void destroy() {  
  7.     System.out.println("==========destroy");  
  8. }  

 

2、修改测试方法如下:

 

java代码:Java代码

 收藏代码

  1. @Test  
  2. public void resourceInjectTest1() {  
  3.     ((ClassPathXmlApplicationContext) ctx).registerShutdownHook();  
  4.     TestBean41 testBean41 = ctx.getBean("testBean41", TestBean41.class);  
  5.     Assert.assertEquals("hello", testBean41.getMessage());  
  6. }  

    类似于通过<bean>标签的init-method和destroy-method属性指定的初始化和销毁方法,但具有更高优先级,即注解方式的初始化和销毁方法将先执行。

 

 

12.2.4  JSR-330注解

在测试之前需要准备JSR-330注解所需要的jar包,到spring-framework-3.0.5.RELEASE-dependencies.zip中拷贝如下jar包到类路径:

 

com.springsource.javax.inject-1.0.0.jar

 

       一、@Inject等价于默认的@Autowired,只是没有required属性;

       二、@Named指定Bean名字,对应于Spring自带@Qualifier中的缺省的根据Bean名字注入情况;

       三、@Qualifier只对应于Spring自带@Qualifier中的扩展@Qualifier限定描述符注解,即只能扩展使用,没有value属性。

 

 

1、首先扩展@Qualifier限定描述符注解来表示Mysql数据源

 

java代码:Java代码

 收藏代码

  1. package cn.javass.spring.chapter12.qualifier;  
  2. //省略部分import  
  3. import javax.inject.Qualifier;  
  4. @Target({ElementType.FIELD, ElementType.PARAMETER})  
  5. @Retention(RetentionPolicy.RUNTIME)  
  6. @Qualifier  
  7. public @interface JSR330Mysql {  
  8. }  
  9.    

 

 

2、准备测试Bean:

 

 

java代码:Java代码

 收藏代码

  1. package cn.javass.spring.chapter12;  
  2. import javax.inject.Inject;  
  3. import javax.inject.Named;  
  4. import javax.sql.DataSource;  
  5. import cn.javass.spring.chapter12.qualifier.JSR330Mysql;  
  6. public class TestBean51 {  
  7.     private DataSource mysqlDataSource;  
  8.     private DataSource oracleDataSource;  
  9.     @Inject  
  10.     public void initDataSoruce(  
  11.             @JSR330Mysql  DataSource mysqlDataSource,  
  12.             @Named("oracleDataSource") DataSource oracleDataSource) {  
  13.         this.mysqlDataSource = mysqlDataSource;  
  14.         this.oracleDataSource = oracleDataSource;  
  15.   
  16.     }  
  17.     //省略getter    
  18. }  

 

3、在Spring配置文件(chapter12/dependecyInjectWithAnnotation.xml)添加如下Bean配置:

 

java代码:Java代码

 收藏代码

  1. <bean id="testBean51" class="cn.javass.spring.chapter12.TestBean51"/>  

 

4、在Spring修改定义的mysqlDataSourceBean数据源:

 

java代码:Java代码

 收藏代码

  1. <bean id="mysqlDataSourceBean" class="org.springframework.jdbc.datasource.DriverManagerDataSource">  
  2.          <qualifier value="mysqlDataSource"/>  
  3.          <qualifier type="cn.javass.spring.chapter12.qualifier.Mysql"/>  
  4.          <qualifier type="cn.javass.spring.chapter12.qualifier.DataSourceType">  
  5.              <attribute key="ip" value="localhost"/>  
  6.              <attribute key="database" value="MYSQL"/>  
  7.          </qualifier>  
  8.          <qualifier type="cn.javass.spring.chapter12.qualifier.JSR330Mysql"/>  
  9. </bean>  

 

 

5、测试方法如下:

 

java代码:Java代码

 收藏代码

  1. @Test  
  2. public void testInject() {  
  3.     TestBean51 testBean51 = ctx.getBean("testBean51", TestBean51.class);  
  4.     Assert.assertEquals(ctx.getBean("mysqlDataSourceBean"), testBean51.getMysqlDataSource());  
  5.     Assert.assertEquals(ctx.getBean("oracleDataSource"), testBean51.getOracleDataSource());  
  6. }  

 

 

测试也通过了,说明JSR-330注解也能很好工作。

 

从测试中可以看出JSR-330注解和Spring自带注解依赖注入时主要有以下特点:

  • Spring自带的@Autowired的缺省情况等价于JSR-330的@Inject注解;
  • Spring自带的@Qualifier的缺省的根据Bean名字注入情况等价于JSR-330的@Named注解;
  • Spring自带的@Qualifier的扩展@Qualifier限定描述符注解情况等价于JSR-330的@Qualifier注解。

 

 

 

12.2.5  JPA注解

用于注入EntityManagerFactory和EntityManager。

      

1、准备测试Bean:

 

java代码:Java代码

 收藏代码

  1. package cn.javass.spring.chapter12;  
  2. //省略import  
  3. public class TestBean61 {  
  4.     @PersistenceContext(unitName = "entityManagerFactory")  
  5.     private EntityManager entityManager;  
  6.      
  7.     @PersistenceUnit(unitName = "entityManagerFactory")  
  8.     private EntityManagerFactory entityManagerFactory;  
  9.      
  10.     public EntityManager getEntityManager() {  
  11.         return entityManager;  
  12.     }  
  13.     public EntityManagerFactory getEntityManagerFactory() {  
  14.         return entityManagerFactory;  
  15.     }  
  16. }  

 

2、在Spring配置文件(chapter12/dependecyInjectWithAnnotation.xml)添加如下Bean配置:

 

java代码:Java代码

 收藏代码

  1. <import resource="classpath:chapter7/applicationContext-resources.xml"/>  
  2. <import resource="classpath:chapter8/applicationContext-jpa.xml"/>  
  3. <bean id="testBean61" class="cn.javass.spring.chapter12.TestBean61"/>  

    此处需要引用第七章和八章的配置文件,细节内容请参考七八两章。

 

 

3、测试方法如下:

 

java代码:Java代码

 收藏代码

  1. @Test  
  2. public void testJpaInject() {  
  3.     TestBean61 testBean61 = ctx.getBean("testBean61", TestBean61.class);  
  4.     Assert.assertNotNull(testBean61.getEntityManager());  
  5.     Assert.assertNotNull(testBean61.getEntityManagerFactory());  
  6. }  

    测试也通过了,说明JPA注解也能很好工作。

 

JPA注解类似于@Resource注解同样是先根据unitName属性去JNDI环境中查找,如果没找到在到Spring容器中查找。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值