Spring获取实现某接口所有Bean实例方法

在项目中使用策略者模式、工厂模式等面向接口设计时,有时会遇到要获取实现某接口所有实现类的bean实例。

实现方式

有三种可实现的方法,分别是:

  1. 将所有的bean实例注入在List中
@Autowired
private List<T> serverList;
  1. 将所有的bean实例以beanName:bean的形式注入在Map中
@Autowired
private Map<String, T> serverMap
  1. 从ApplicationContext中获取
@Autowired
ApplicationContext applicationContext;

//  beanName:bean 
applicationContext.getBeansOfType(T.class)

测试代码:

接口:

public interface InterfaceDemo {
}

注解:

import java.lang.annotation.*;

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface InterfaceDemoAn {
    String[] values();
}

接口的实现类们:
interfaceA

import org.springframework.stereotype.Service;

@Service(value = "interfaceDemoA")
@InterfaceDemoAn(values = {"A", "a"})
public class InterfaceDemoA implements InterfaceDemo{
}

intetfaceB

import org.springframework.stereotype.Service;

@Service(value = "interfaceDemoB")
@InterfaceDemoAn(values = {"B", "b"})
public class InterfaceDemoB implements InterfaceDemo{
}

interfaceC

import org.springframework.stereotype.Service;

@Service(value = "interfaceDemoC")
@InterfaceDemoAn(values = {"C", "c"})
public class InterfaceDemoC implements InterfaceDemo{
}

通用抽象工厂:

import lombok.extern.slf4j.Slf4j;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.lang.reflect.ParameterizedType;
import java.util.*;
/**
* 实现InitializingBean,会Spring启动后,初始化Bean时,会自动调用afterPropertiesSet方法
* 工具类不适合用@Resource注解注入,Spring在处理@Resource注解时,如果存在通用泛型,擦除不如@Autowired灵活
*/
@Slf4j
public abstract class CommonFactory<T> implements InitializingBean {

    private static final Logger LOGGER = LoggerFactory.getLogger(CommonFactory.class);

    @Autowired
    private List<T> interfaceDemoList;

    @Autowired
    ApplicationContext applicationContext;

    @Autowired
    private Map<String, T> interfaceDemoMap;

    /**
     * 使用interfaceDemoList组装的只读MAP
     */
    private Map<String, T> interfaceDemoMapFromList;

    /**
     * 使用applicationContext组装的只读MAP
     */
    private Map<String, T> interfaceDemoMapFromAC;



    public void getInstance(String beanName){
        T t1 = interfaceDemoMap.get(beanName);
        LOGGER.info("interfaceDemoMap : annoValues:{}",
                Arrays.asList(t1.getClass().getAnnotation(InterfaceDemoAn.class).values()));
        T t2 = interfaceDemoMapFromList.get(beanName);
        LOGGER.info("interfaceDemoMapFromList : annoValues:{}",
                Arrays.asList(t2.getClass().getAnnotation(InterfaceDemoAn.class).values()));
        T t3 = interfaceDemoMapFromAC.get(beanName);
        LOGGER.info("interfaceDemoMapFromAC : annoValues:{}",
                Arrays.asList(t3.getClass().getAnnotation(InterfaceDemoAn.class).values()));
    }


    @Override
    public void afterPropertiesSet() throws Exception {
        // 使用applicationContext获取所有的bean实例
        // 获取父类的ParameterizedType类型
        ParameterizedType parameterizedType = (ParameterizedType) this.getClass().getGenericSuperclass();
        //  获取父类上所有的泛型类型
        Class tClass = (Class) parameterizedType.getActualTypeArguments()[0];
        this.interfaceDemoMapFromAC = Collections.unmodifiableMap(applicationContext.getBeansOfType(tClass));


        Map<String, T> tempMap = new HashMap<>();
        // 使用List获取所有的bean实例
        interfaceDemoList.forEach(t -> {
            String beanName = t.getClass().getAnnotation(Service.class).value();
            tempMap.put(beanName, t);
        });
        this.interfaceDemoMapFromList = Collections.unmodifiableMap(tempMap);


    }
}

工厂实现类:

import org.springframework.stereotype.Component;

@Component
public class InterfaceFactory extends CommonFactory<InterfaceDemo> {
}

controller:

import com.example.springbootdemo.factory.InterfaceFactory;
import lombok.extern.slf4j.Slf4j;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;


@RestController
@RequestMapping("/test")
@Slf4j
public class TestController {

    private static final Logger LOGGER = LoggerFactory.getLogger(TestController.class);

    @Autowired
    private InterfaceFactory interfaceFactory;


    @RequestMapping(value = "/interface", method = RequestMethod.POST)
    public void getInterfaceEntity() {
        interfaceFactory.getInstance("interfaceDemoB");
    }
}

Console输出

INFO 5105 --- [nio-8080-exec-2] c.e.s.factory.CommonFactory              : interfaceDemoMap : annoValues:[B, b]
INFO 5105 --- [nio-8080-exec-2] c.e.s.factory.CommonFactory              : interfaceDemoMapFromList : annoValues:[B, b]
INFO 5105 --- [nio-8080-exec-2] c.e.s.factory.CommonFactory              : interfaceDemoMapFromAC : annoValues:[B, b]
  • 1
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值