业务开发中,有时需要获取到某个接口或抽象类的所有实现方法,然后再某个类中集中进行处理,都有哪些方法呢?
一、 如果是普通的Java应用,可以使用JDK自带的一个类加载器ServiceLoader,其实就是SPI机制。
ServiceLoaderloader = ServiceLoader.load(IWork.class);
因为在ServiceLoader.load的时候,是根据传入的接口类,遍历META-INF/services目录下的以该类命名的文件中的所有类,并实例化返回。所以,不适用于抽象类。
二、如果在Springboot工程中,接口的实现可以由IOC容器来托管,就可以非常简单的从Spring容器中获取到实现类集合。具体包括2种渠道。
直接使用Spring注解@Autowired
实现ApplicationContextAware接口获取并管理所有实现类。 就可以很简单的利用@Autowired来获取到实现类的list或map集合。
三、Springboot具体实现实例讲解
1)接口类
IWorkService.java
public interface IWorkService {
String workPlace();
}
2)实现类
TeacherWorkService.java
@Service
public class TeacherWorkService implements IWorkService {
@Override
public String workPlace() {
return "school";
}
}
DoctorWorkService.java
@Service
public class DoctorWorkService implements IWorkService{
@Override
public String workPlace() {
return "hospital";
}
}
3)Aware实现类
WorkServiceLocator.java
@Component
public class WorkServiceLocator implements ApplicationContextAware {
//手动获取,key是bean的name,value是实现类
private Map<String, IWorkService> workServiceMap;
//手动获取,list是所有的实现类
private List<IWorkService> workServiceList;
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
workServiceMap = applicationContext.getBeansOfType(IWorkService.class);
workServiceList = new ArrayList<>(workServiceMap.values());
}
public Map<String, IWorkService> getAllMap() {
return workServiceMap;
}
public IWorkService getByName(String beanName) {
return workServiceMap.get(beanName);
}
public List<IWorkService> getAllList() {
return workServiceList;
}
}
3)Test入口类
@SpringBootTest(classes = {Application.class})
@RunWith(SpringRunner.class)
public class WorkServiceTest {
/**
* 方式1:直接使用spring依赖注入注解
*/
@Autowired
private Map<String, IWorkService> workServiceMap;
/**
* 方式2:直接使用spring的依赖注入注解
*/
@Autowired
private List<IWorkService> workServiceList;
/**
* 方式3:借助spring的ApplicationContextAware
*/
@Autowired
private WorkServiceLocator workServiceLocator;
@Test
public void testAll() {
Map<String, IWorkService> allMap = workServiceLocator.getAllMap();
List<IWorkService> allList = workServiceLocator.getAllList();
IWorkService iWorkService = workServiceLocator.getByName("teacherWorkService");
}
}
四、总结
对于普通的Java工程实现获取接口所有实现类需要借助SPI机制,且仅限于接口;对于Spring工程,则有@Autowired自动获取和实现ApplicationContextAware手动获取2种,既支持接口实现类、也支持抽象类的实现类。