In business development, sometimes it is necessary to obtain all the implementation methods of an interface or abstract class, and then centrally process them in a certain class. What are the methods?
1. If it is an ordinary Java application, you can use the ServiceLoader, a class loader that comes with the JDK, which is actually the SPI mechanism.
ServiceLoaderloader = ServiceLoader.load(IWork.class);
Because during ServiceLoader.load, based on the incoming interface class, all classes in the file named after the class in the META-INF/services directory are traversed, and instantiated and returned. Therefore, it does not apply to abstract classes.
2. If in the Springboot project, the implementation of the interface can be hosted by the IOC container, it is very simple to obtain the implementation class collection from the Spring container. Specifically, it includes 2 channels.
-
Directly use Spring annotation @Autowired
-
Implement the ApplicationContextAware interface to obtain and manage all implementation classes. You can easily use @Autowired to get the list or map collection of the implementation class.
3. Explanation of specific implementation examples of Springboot
1) Interface class
IWorkService.java
public interface IWorkService {
String workPlace();
}
2) Implementation class
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 implementation class
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 entry class
@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");
}
}
4. Summary
For ordinary Java projects, all implementation classes need to use the SPI mechanism to obtain the interface, and are limited to interfaces; for Spring projects, there are two types: @Autowired automatic acquisition and ApplicationContextAware manual acquisition, which supports both interface implementation classes and abstract classes. Implementation class.
5. Scan the QR code to follow, the article is first published, and the public account platform