调用入口
@Resource(name = "ServiceB")
// 或者
//@Autowired
//@Qualifier("ServiceB")
private Service service;
public void main(String[] args) throws Exception {
service.myTestAction("interfaceC");
}
抽象类里面的抽象方法
package service;
public abstract class Service {
public void myTestAction(String param) throws Exception {
myActionDoSomething(param); // 调用myActionDoSomething这个抽象方法
}
// 定义了抽象方法,另外有两个实现类来完成抽象方法的细节逻辑
public abstract void myActionDoSomething(String param) throws Exception;
}
抽象方法的两个实现类
package service;
import org.springframework.stereotype.Component;
@Component("serviceA")
public class ServiceA extends Service {
@Override
public void myActionDoSomething(String param) {
// do thing 1
System.out.println("这里是执行 Service A");
System.out.println(param);
}
}
第1个实现类serviceA 直接处理业务逻辑(即打印一行日志,当然大家实际项目中肯不是打印一行日志这么简单)
第2个实现类serviceB 它还调用了一个接口,这个接口也是多实现的,这个接口的两个实现类里面的业务逻辑也是打印一行日志。
package service;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.context.ApplicationContext;
import java.util.Map;
@Component("serviceB")
public class ServiceB extends Service {
@Autowired
private ApplicationContext applicationContext;
@Override
public void myActionDoSomething(String param) throws Exception {
// do thing 1
System.out.println("这里是执行 Service B");
// 获取接口myTestInterface的全部实现类放进Map
Map<String, MyTestInterface> map = applicationContext.getBeansOfType(MyTestInterface.class);
// 从Map中选本次执行需要的那一个
MyTestInterface myTestInterface = map.get(param); // param = interfaceC 或 interfaceD 决定执行下面哪一个接口实现类
String text = "tttt";
myTestInterface.myInterfaceDoSomething(text);
}
// 定义一个接口 myTestInterface
interface MyTestInterface {
void myInterfaceDoSomething(String text);
}
// 接口 myTestInterface 的实现类之一
@Component("interfaceC")
class myTestInterfaceC implements MyTestInterface {
@Override
public void myInterfaceDoSomething(String text) {
System.out.println("这里是执行 myTestInterface C ");
}
}
// 接口 myTestInterface 的实现类之一
@Component("interfaceD")
class myTestInterfaceD implements MyTestInterface {
@Override
public void myInterfaceDoSomething(String text) {
System.out.println("这里是执行 myTestInterface D ");
}
}
}
以上是抽象类和接口的多继承多实现例子,在调用的类里面注入的时候,通过注解的形式注入指定name从而决定走的是哪个一个具体的实现类。子实现通过@Component或@Service表明自己唯一的name。
可以用来处理,不同地方调用统一的入口却走的是不一样的逻辑。
注意点:
- 关于
MyTestInterface myTestInterface = map.get(param);
这里的param参数, 调用入口是写死的"interfaceC",而实际中大可能是查询配置表再传递。 class myTestInterfaceC implements MyTestInterface
可以写很多个每个里面的逻辑都不一样,但@Component("interfaceC")
注解里面的值interfaceC切不可重复,因为bean无法重复注入。即使启动项目不报错,也只会生效一个。- 假如要做多套
class myTestInterfaceC implements MyTestInterface
代码每套里面的逻辑不一样, 因为是同一个项目中@Component里面的值必须不一样,比如第一套是interfaceC,那第二套可以是interfaceC2,…以此类推。至于传参的时候,弄两张配置表独立开(一张配的interfaceC一张配置的是interfaceC2),两套各用一张表,互不影响。如果一定要公用一张,则第二套在调用处读取配置值后自动给它拼接字符串2成为interfaceC2再进行传递即可,或者在map.get(param+“2”)这里统一拼接。这样第二套就是找注解值为interfaceC2来执行,并不会影响注解值为interfaceC的,两个注解值不一致了也就不会造成重复注入。