Spring 基于注解的配置(二)(@Required,@Autowired, @Qualifier)

来源:互联网 发布:网络常见的拓扑形式有 编辑:程序博客网 时间:2024/06/07 17:42

@Required

应用范围:bean属性的setter方法

作用:检查注解的Bean属性是否在XML中进行配置,若未进行配置则容器会抛出一个BeanInitializationException异常

使用方法:

方法一:

包函 <context:annotation-config />

<context:annotation-config />
<bean id="Hello"class="com.spring.demo.Hello">
    <!-- <property name="name" value="ruanjianlin"/> -->
    <propertyname="id"value="12"/>
</bean>

 

Hello.java

package com.spring.demo;

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

/**
 * Created by ruanjianlin on 2017/9/27.
 */
public class Hello {
    privateString name;
    private int id;

    public Hello() {
    }

    publicHello(String name, intid) {
        this.name= name;
        this.id= id;
    }

    publicString getName() {
        returnname;
    }

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

    public intgetId() {
        returnid;
    }

    public voidsetId(intid) {
        this.id= id;
    }
    public voidsay(){
        System.out.println("hello");
    }

    @Override
    publicString toString() {
        return"Hello{" +
                "name='"+ name+ '\''+
                ", id="+ id+
                '}';
    }
}

 

运行的结果:

Property 'name' is required for bean 'Hello'

 

方法二:

 bean 配置文件包函“RequiredAnnotationBeanPostProcessor

<bean class="org.springframework.beans.factory.annotation.RequiredAnnotationBeanPostProcessor"/>
<bean id="Hello"class="com.spring.demo.Hello">
    <!-- <property name="name" value="ruanjianlin"/> -->
    <propertyname="id"value="12"/>
</bean>

 

@Autowired的联系:

1.@Autowired 的必要属性,建议使用@Required注解

2.每个类只能有一个构造器被标记为required=true(每个类有很多的构造器,默认的required=false)

3.如果因为找不到合适的bean或者含有多个Bean将会导致autowiring失败抛出异常,使用@Autowired(required=false)解决(主要用于构造方法和Bean setter方法上,也可以用于属性上)


Autowired是一种函数,可以对成员变量方法构造函数进行标注,来完成自动装配的工作,@Autowired标注可以放在成员变量上,也可以放在成员变量的set方法上。

这里必须明确:@Autowired根据类型进行自动装配的,如果需要按名称进行装配,则需要配合@Qualifier使用

Spring 2.5 引入了 @Autowired注释,它可以对类成员变量、方法及构造函数进行标注,完成自动装配的工作。 通过@Autowired的使用来消除setget方法。

 Spring遇到一个在 setter方法中使用的@Autowired注释,setter方法会在方法中视图执行 byType 自动连接

 

Setter方法中的@Autowired

Computer.java

package com.spring.Autowire;

/**
 * Created by ruanjianlin on 2017/10/6.
 */
public class Computer {
    publicComputer() {
        System.out.println("You get a new computer");
    }

    public voidplay(){
        System.out.println("The computer is working! ");
    }
}

 

Human.java

package com.spring.Autowire;

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

/**
 * Created by ruanjianlin on 2017/10/6.
 */
public class Human {

    privateComputercomputer;

    public Human() {
        System.out.println("The function of  Human constructor is working!");
    }

    publicHuman(Computer computer) {
        this.computer= computer;
        System.out.println("The function of  Human which has a parameter is working!");
    }

    publicComputergetComputer() {
        returncomputer;
    }

    @Autowired
    public voidsetComputer(Computer computer) {
        this.computer= computer;
        System.out.println("The function of setComputer is working!");
    }

    public voidplay(){
        computer.play();
    }
}

 

 

 

Autowired_Demo.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.xsd">

    <context:annotation-config/>
    <bean id="human"class="com.spring.Autowire.Human">

    </bean>
    <bean id="computer"class="com.spring.Autowire.Computer">

    </bean>
</beans>

 


输出结果:

The function of  Human constructor is working!

You get a new computer

The function of setComputer is working!

The computer is working!

 

调用的方法:

Human()

Computer()

setComputer(Computer computer)

play()

 

构造函数中的@Autowired

package com.spring.Autowire;

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

/**
 * Created by ruanjianlin on 2017/10/6.
 */
public class Human {

    privateComputercomputer;


    public Human() {
        System.out.println("The function of  Human constructor is working!");
    }

    @Autowired
    publicHuman(Computer computer) {
        this.computer= computer;
        System.out.println("The function of  Human which has a parameter is working!");
    }

    publicComputergetComputer() {
        returncomputer;
    }


    public voidsetComputer(Computer computer) {
        this.computer= computer;
        System.out.println("The function of setComputer is working!");
    }

    public voidplay(){
        computer.play();
    }
}

 

输出结果:

You get a new computer

The function of  Human which has a parameter is working!

The computer is working!

 

运行的方法:

Human(Computer computer)

Computer()

play()

 

 

属性中的@Autowired

Human.java

package com.spring.Autowire;

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

/**
 * Created by ruanjianlin on 2017/10/6.
 */
public class Human {
    @Autowired
    privateComputercomputer;

    public Human() {
        System.out.println("The function of  Human constructor is working!");
    }

    publicHuman(Computer computer) {
        this.computer= computer;
        System.out.println("The function of  Human which has a parameter is working!");
    }

    publicComputergetComputer() {
        returncomputer;
    }


    public voidsetComputer(Computer computer) {
        this.computer= computer;
        System.out.println("The function of setComputer is working!");
    }

    public voidplay(){
        computer.play();
    }
}

 

 

输出结果:

The function of  Human constructor is working!

You get a new computer

The computer is working!

Disconnected from the target VM, address: '127.0.0.1:54693', transport: 'socket'

 

 

运行的方法:

Human()

Computer()

play()

 

属性上的添加@AutowiredgetBean时并没有调用setComputer(Computer computer)

 

原理解释:

(1)Spring 通过一个 BeanPostProcessor  @Autowired进行解析,所以要让@Autowired起作用必须事先在Spring容器中声明AutowiredAnnotationBeanPostProcessor Bean

@Autowired在成员上配置Spring将直接采用 Java反射机制Human中的computer 这个私有成员变量进行自动注入。所以对成员变量使用 @Autowired后,可将它的 setter方法(setComputer(Computer computer)

)从 Human中删除。 

 

(2) @Autowired对方法或构造函数进行标注:(按照本示例作解析)如果构造函数有一个形参,是computer@Autowired寻找和它类型匹配的Bean(byType),将它作为Human (Computer computer)参数来创建 Human Bean 此时不再调用setter方法,而@Autowiredsetter上时会通过上述方式进行Bean的注册,而不会调用带参数的构造函数

(3)在使用Spring框架中@Autowired标签时默认情况下使用@Autowired注释进行自动注入时,Spring容器中匹配的候选Bean数目必须有且仅有一个。当找不到一个匹配的 Bean时,Spring容器将抛BeanCreationException异常,并指出必须至少拥有一个匹配的 Bean因此可以使用 @Qualifier解除歧义

 


 @Qualifier的使用

@Autowired 可以对成员变量、方法以及构造函数进行注释,而 @Qualifier 的标注对象是成员变量方法入参构造函数入参

代码示例:

Sing接口类:

package com.spring.Autowire;

import org.springframework.stereotype.Component;

/**
 * Created by ruanjianlin on 2017/10/7.
 */
@Component("sing")
public interface Sing {
    public voidsing();
}

 

ManSing.java

package com.spring.Autowire;

import org.springframework.stereotype.Component;

/**
 * Created by ruanjianlin on 2017/10/7.
 */
@Component("manSing")
public class ManSingimplementsSing {
    public voidsing() {
        System.out.println("This is a man!");
    }
}

 

WomanSing.java

package com.spring.Autowire;

import org.springframework.stereotype.Component;

/**
 * Created by ruanjianlin on 2017/10/7.
 */
@Component("womanSing")
public class WomanSingimplementsSing {

    public voidsing() {
        System.out.println("This is a woman!");
    }
}

 

 

Human.java

package com.spring.Autowire;

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

/**
 * Created by ruanjianlin on 2017/10/6.
 */
public class Human {

    privateComputercomputer;
    @Autowired
    @Qualifier("manSing")
    privateSingsing;

    public Human() {
        System.out.println("The function of  Human constructor is working!");
    }

    @Autowired
    publicHuman(Computer computer) {
        this.computer= computer;
        System.out.println("The function of  Human which has a parameter is working!");
    }

    publicComputergetComputer() {
        returncomputer;
    }


    public voidsetComputer(Computer computer) {
        this.computer= computer;
        System.out.println("The function of setComputer is working!");
    }

    public voidsetSing(Sing sing) {
        this.sing= sing;
    }

    public voidplay(){
        computer.play();
        sing.sing();
    }
}

 

Autowired_Demo.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.xsd">

    <context:annotation-config/>
    <bean id="human"class="com.spring.Autowire.Human">

    </bean>
    <bean id="computer"class="com.spring.Autowire.Computer">

    </bean>
    <context:component-scanbase-package="com.spring"use-default-filters="false">
        <context:include-filtertype="regex"expression="com.spring.Autowire.*"/>
    </context:component-scan>
</beans>

 

上述为正确代码运行结果如下:

 

You get a new computer

The function of  Human which has a parameter is working!

The computer is working!

This is a man !

 

当我们不使用@Qualifier时报错情况主要如下所示:

org.springframework.beans.factory.BeanCreationException: Could not autowire field: private com.spring.Autowire.Sing com.spring.Autowire.Human.sing; nested exception is org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type [com.spring.Autowire.Sing] is defined: expected single matching bean but found 2: manSing,womanSing

 

错误解析:由报错信息可知产生了歧义,系统无法决定 manSing,womanSing

 

关于BeanPostProcessor接口相关的内容以及该接口的原理及工作机制,本人目前处于初级阶段,尚无法解析,在后期进行源码学习时将会重点探索,望感兴趣的猿们可以自行探索。

阅读全文
0 0
原创粉丝点击