spring容器一个接口多个实现类如何指定

一个接口在生成过程中难免会遇到场景变更等等需求 需要跟换实现类 或者有多个实现类,不同的实现类有各自的需求,如何在项目中实现根据不同项目,自由切换实现类呢?
1.方法一:使用@Autowired @Qualifier(value = “xxx”)
2.方法二:使用@Resource(name = “xxx”),没有指定bean注入名字的,使用该类首字符小写的bean的名字
3.方法三:使用@Resource(name = “xxx”),通过@Resource注入,根据@Service指定的名称区分
4.自定义TypeFilter指定过滤规则
5.@Primary注解
6.@ConditionalOnProperty通过配置文件来指定

实例1-3:
接口:

package com.cj.interfaces;

public interface ITestService {
    void test();
}


package com.cj.interfaces;
import org.springframework.stereotype.Service;

@Service("s1")
public class TestServiceImpl1 implements ITestService {
    @Override
    public void test() {
        System.out.println("接口1实现类 ...");
    }
}


package com.cj.interfaces;

import org.springframework.stereotype.Service;

@Service
public class TestServiceImpl2 implements ITestService {
    @Override
    public void test() {
        System.out.println("接口2实现类 ...");
    }
}


package com.cj.interfaces;

import org.springframework.stereotype.Service;

@Service("s3")
public class TestServiceImpl3 implements ITestService {
    @Override
    public void test() {
        System.out.println("接口3实现类 ...");
    }
}

package com.cj.interfaces;

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.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;

import javax.annotation.Resource;

import static org.junit.jupiter.api.Assertions.*;

@RunWith(SpringRunner.class)
@SpringBootTest
public class ITestServiceTest {

    //有指定bean注入名字的,使用bean的名字
    //qualifier的意思是合格者,通过这个标示,表明了哪个实现类才是我们所需要的,我们修改调用代码,添加@Qualifier注解,
    // 需要注意的是@Qualifier的参数名称必须为我们之前定义@Service注解的名称之一!
    @Autowired
    @Qualifier(value = "s1")
    ITestService testService;    //正常启动

    //没有指定bean注入名字的,使用该类首字符小写的bean的名字
    //使用默认的
    @Resource(name = "testServiceImpl2")
    ITestService testService2;    //正常启动

    //通过@Resource注入,根据@Service指定的名称区分
    @Resource(name = "s3")
    ITestService testService3;    //正常启动

    @Test
   public void test1() {
        testService.test();

        testService2.test();

        testService3.test();     
    }
}

结果如图:在这里插入图片描述

实例4:
实现TypeFilter接口

package com.gcxzflgl.filter;
 
import org.springframework.core.io.Resource;
import org.springframework.core.type.AnnotationMetadata;
import org.springframework.core.type.ClassMetadata;
import org.springframework.core.type.classreading.MetadataReader;
import org.springframework.core.type.classreading.MetadataReaderFactory;
import org.springframework.core.type.filter.TypeFilter;
 
import java.io.IOException;
 
public class MyTypeFilter implements TypeFilter {
 
    /**
     * metadataReader:读取到的当前正在扫描的类的信息
     * metadataReaderFactory:可以获取到其他任何类信息的
     */
    public boolean match(MetadataReader metadataReader, MetadataReaderFactory metadataReaderFactory)
            throws IOException {
        // TODO Auto-generated method stub
        //获取当前类注解的信息
        AnnotationMetadata annotationMetadata = metadataReader.getAnnotationMetadata();
        //获取当前正在扫描的类的类信息
        ClassMetadata classMetadata = metadataReader.getClassMetadata();
        //获取当前类资源(类的路径)
        Resource resource = metadataReader.getResource();
 
        String className = classMetadata.getClassName();
        System.out.println("--->"+className);
        if(className.contains("ll")){
            return true;
        }
        return false;
    }
}
@ComponentScan(basePackages={"com.ylz.ryjs"},excludeFilters = {@ComponentScan.Filter(type= FilterType.CUSTOM,classes = {ComponentScanFilter.class})})
public class YlzRyjsWebApplication {
//scanBasePackages="com.ylz.ryjs"
	public static void main(String[] args) {
		SpringApplication.run(YlzRyjsWebApplication.class, args);
		
	}

}

实例5:

package com.cj.interfaces;

public interface IPrimaryService {
    void test();
}


package com.cj.interfaces;

import org.springframework.context.annotation.Primary;
import org.springframework.stereotype.Service;

@Service
@Primary
public class TestPrimaryImpl1 implements IPrimaryService{
    @Override
    public void test() {
        System.out.println("Primary 1");
    }
}


package com.cj.interfaces;

import org.springframework.stereotype.Service;

@Service
public class TestPrimaryImpl2  implements IPrimaryService{
    @Override
    public void test() {
        System.out.println("Primary 2");
    }
}


     @Autowired
    IPrimaryService primaryService;

    @Test
   public void test1() {
        primaryService.test();
    }

结果如下:
在这里插入图片描述
实例6:

package com.cj.interfaces;

public interface ITestServiceConditional {
    void test();
}


package com.cj.interfaces;

import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.context.annotation.Configuration;
import org.springframework.stereotype.Service;

/**
 * 使用配置文件控制注入:
 * 我们需要在实现类上添加配置文件注解,使用配置文件控制该实现类是否生效
 */
@Service
@Configuration
@ConditionalOnProperty(prefix = "demo.test.service",name = "impl",havingValue = "one")
public class TestServiceImpl4 implements ITestServiceConditional {
    @Override
    public void test() {
        System.out.println("接口4实现类 ...");
    }
}

package com.cj.interfaces;

import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.context.annotation.Configuration;
import org.springframework.stereotype.Service;

@Service
@Configuration
@ConditionalOnProperty(prefix = "demo.test.service",name = "impl",havingValue = "two")
public class TestServiceImpl5 implements ITestServiceConditional {
    @Override
    public void test() {
        System.out.println("接口5实现类 ...");
    }
}

demo:
  test:
    service:
      impl: one



    @Autowired
    ITestServiceConditional testServiceConditional;

    @Test
   public void test1() {
        testServiceConditional.test();
    }

结果如下:
在这里插入图片描述

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值