Copyright notice: This article is the original article of CSDN blogger "Emine Wang", which follows the CC 4.0 BY-SA copyright agreement. Please attach the original source link and this notice for reprint.
Original link: https://blog.csdn.net/a718515028/article/details/72457436
Raising questions
In practice, we often encounter one interface and multiple implementation classes, and different implementation classes will be used under different conditions. In terms of usage, it is similar to SPI,
However, since the use of SPI is not very convenient, what should we do? We can use getBeansOfType of ApplicationContext to achieve the results we need.
First, let's look at the signature of this method
<T> Map<String, T> getBeansOfType(Class<T> type) throws BeansException;
From the above code, we can see that this method can return all implementation classes of an interface (provided that all implementation classes must be managed by the Spring IoC container).
org.springframework.beans and org.springframework.context are the foundation of Spring IoC container,
One of the important classes is BeanFactory. BeanFactory is the core interface of IoC container, and its responsibilities include instantiating, locating and configuring applications
Objects and establishing dependencies between these objects.
As a subclass of BeanFactory, ApplicationContext has been greatly enhanced in the function of Bean management and is easier to integrate with Spring AOP.
ApplicationContext is a practical application method.
example
The design is as follows: there is an interface for traffic mode. The interface has two modes: one is to query the cost and the other is to query the type of the traffic mode. At the same time, we can use an enumeration type class to identify the traffic type.
We also need a factory class to find the Bean instance of the traffic type according to the traffic type ID, so as to use the instance to obtain the details of the traffic type and the operation of the traffic type.
The code is as follows:
Interface:
/** * mode of transportation */ public interface TrafficMode { /** * Query traffic mode code * @return code */ TrafficCode getCode(); /** * Query the cost of transportation mode, unit: minute * @return cost */ Integer getFee(); }
/** * Traffic type enumeration */ public enum TrafficCode { TRAIN, BUS }
Interface has two implementation classes:
/** * Automobile mode */ @Component public class BusMode implements TrafficMode { @Override public TrafficCode getCode() { return TrafficCode.BUS; } @Override public Integer getFee() { return 10000; } }
/** * Train mode */ @Component public class TrainMode implements TrafficMode { @Override public TrafficCode getCode() { return TrafficCode.TRAIN; } @Override public Integer getFee() { return 9000; } }
Factory type:
/** * Transportation mode factory */ @Component public class TrafficModeFactory implements ApplicationContextAware { private static Map<TrafficCode, TrafficMode> trafficBeanMap; @Override public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { Map<String, TrafficMode> map = applicationContext.getBeansOfType(TrafficMode.class); trafficBeanMap = new HashMap<>(); map.forEach((key, value) -> trafficBeanMap.put(value.getCode(), value)); } public static <T extends TrafficMode> T getTrafficMode(TrafficCode code) { return (T)trafficBeanMap.get(code); } }
verification
After having the above code, let's see the effect through unit test. The code fragment of unit test is as follows:
@Test public void testGetTrafficMode() { TrafficMode mode = TrafficModeFactory.getTrafficMode(TrafficCode.BUS); Assert.assertEquals(mode.getFee().intValue(), 10000); mode = TrafficModeFactory.getTrafficMode(TrafficCode.TRAIN); Assert.assertEquals(mode.getFee().intValue(), 9000); }