您的位置:首页 > 编程语言 > Java开发

Spring 实战-第三章-处理自动装配的歧义性

2017-09-07 16:42 453 查看
profile解决了不同环境配置切换的问题,但是对于同一个接口,当有多个实现的时候,Spring无法判断应该使用何种实现,这个可以通过@Primary和@Qualifier注解解决。

@Primary注解标示首选使用的bean,但是当存在多个有@Primary注解bean时,依然有无法判断的问题;

@Qualifier注解,可以通过自定义、组合的方式标示使用哪个bean。

1.接口

package main.java.soundsystem;
public interface CompactDisc {
void play();
}


2.声明2个bean

package main.java.soundsystem;

import org.springframework.context.annotation.Condition;
import org.springframework.context.annotation.ConditionContext;
import org.springframework.core.type.AnnotatedTypeMetadata;

public class SgtPepperCondition implements Condition {

@Override
public boolean matches(ConditionContext conditionContext, AnnotatedTypeMetadata annotatedTypeMetadata) {
return true;
}
}


package main.java.soundsystem;

import org.springframework.stereotype.Component;

@Component
public class YellowSubmarine implements CompactDisc{
private String title ="Yellow Submarine";
private String artist="The Beatles";
@Override
public void play() {
System.out.println("Playing "+ title +" by "+artist);
}{
}
}


3.配置文件

package main.java.soundsystem;
import org.springframework.context.annotation.*;

@Configuration
public class CDPlayerConfig {

@Bean
@Primary
public CompactDisc sgtPeppers() {
return new SgtPepper();
}

@Bean
public CompactDisc yellowSubmarine(){
return new YellowSubmarine();
}

}


4.测试

package main.java.soundsystem;

import static org.junit.Assert.*;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ActiveProfiles;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = {CDPlayerConfig.class})
public class CDPlayerTest {
@Autowired
private CompactDisc cd;

@Test
public void cdShouldNotBeNull() {
assertNotNull(cd);
cd.play();
}
}


在配置文件中,sgtPeppers上增加了@Primary注解,标示这是首选bean,若没有增加这个注解,编译时不会报错,但是运行是会有如下异常

org.springframework.beans.factory.NoUniqueBeanDefinitionException:
  No qualifying bean of type 'main.java.soundsystem.CompactDisc' available:
    expected single matching bean but found 2: sgtPeppers,yellowSubmarine


若不使用@Primary注解,可以使用@Qualifier注解

将3.配置文件中的SgtPeppers上增加@Qualifier注解

package main.java.soundsystem;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.*;

@Configuration
public class CDPlayerConfig {

@Bean
@Qualifier("peppers")
public CompactDisc sgtPeppers() {
return new SgtPepper();
}

@Bean
public CompactDisc yellowSubmarine(){
return new YellowSubmarine();
}

}


在4.测试中,CompactDisc上增加相同的@Qualifier注解

package main.java.soundsystem;

import static org.junit.Assert.*;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.test.context.ActiveProfiles;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = {CDPlayerConfig.class})
public class CDPlayerTest {
@Autowired
@Qualifier("peppers")
private CompactDisc cd;

@Test
public void cdShouldNotBeNull() {
assertNotNull(cd);
cd.play();
}
}


在初始化cd的时候,会自动寻找带有相同@Qualifier注解的bean,不过如果相同有多个,还是会异常。

为了更好的找到bean,可以创建自定义的限定符注解,借助这样的注解来表达bean所希望限定的特性。

自定义限定符

package main.java.soundsystem;

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

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Target({ElementType.CONSTRUCTOR,ElementType.FIELD,ElementType.METHOD,ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Qualifier
public @interface  ManualQualifier {
}


配置文件使用自定限定符

package main.java.soundsystem;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.*;

@Configuration
public class CDPlayerConfig {

@Bean
@ManualQualifier
public CompactDisc sgtPeppers() {
return new SgtPepper();
}

@Bean
public CompactDisc yellowSubmarine(){
return new YellowSubmarine();
}

}


使用自定义限定符

package main.java.soundsystem;

import static org.junit.Assert.*;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.test.context.ActiveProfiles;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = {CDPlayerConfig.class})
public class CDPlayerTest {
@Autowired
@ManualQualifier
private CompactDisc cd;

@Test
public void cdShouldNotBeNull() {
assertNotNull(cd);
cd.play();
}
}


对于限定符,是可以使用多个的,通过不同的组合,从根本上解决了使用哪个bean的问题。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: