获取接口的所有实现

一、获取接口所有实现类

方法1:JDK自带的ServiceLoader实现
ServiceLoader是JDK自带的一个类加载器,位于java.util包当中,作为 A simple service-provider loading facility。

(1)创建接口

package com.example.demo.service;

import java.text.ParseException;

public interface UserService{

    void register() throws ParseException;
}

(2)创建实现类
第一个实现类UserServiceImpl

package com.example.demo.service.impl;

import com.example.demo.common.HfiTrace;
import com.example.demo.service.UserService;
import org.springframework.stereotype.Service;

@Service
public class UserServiceImpl implements UserService {

    public UserServiceImpl(UserServiceImpl2 userServiceImpl2) { //由于构造函数先于依赖注入执行,所以这里执行的时候postConstructTest2还没有注入,所以报错
        userServiceImpl2.register();
    }

    @Override
    @HfiTrace
    public void register(){
        System.out.println("register user");
    }
}

第二个实现类 UserServiceImpl2

package com.example.demo.service.impl;

import com.example.demo.service.UserService;
import org.springframework.stereotype.Service;

@Service
public class UserServiceImpl2 implements UserService {

    @Override
    public void register(){
        System.out.println("register user");
    }
}

第三个实现类 UserServiceImpl3

package com.example.demo.service.impl;

import com.example.demo.service.UserService;
import org.springframework.stereotype.Service;

@Service
public class UserServiceImpl3 implements UserService {

    @Override
    public void register(){
        System.out.println("register user 3");
    }
}

(3)在resources目录下添加:META-INF/services/目录,新增一个文件:用你的接口全路径名称命名一个文件(不加后缀),然后在该文件中一行一个添加你的接口实现类的全路径名。
获取接口的所有实现_第1张图片
(4)在第三步新增的文件中,添加接口所有实现类的全路径名,如:
获取接口的所有实现_第2张图片
(5)测试

ServiceLoader<UserService> load = ServiceLoader.load(UserService.class);

        Iterator<UserService> it = load.iterator();
        while (it.hasNext()) {
            UserService service = it.next();
            service.register();
        }

        //for(UserService userService : load){
        //    userService.register();
        //}

方法2:使用Spring自带的方法
Application.getBeansOfType();
Spring作为一个容器,管理着一个项目中所有经过配置的Java类(xml配置文件或Annotation方式)。如果某个接口的所有实现类均被Spring托管了,那么通过Spring就可以很简单的返回这些实现类。

@Component
public class userServiceLocator implements ApplicationContextAware {
	/**
	 * 存储 UserService接口的所有实现类
	 */
	private Map<String, UserService> userServiceMap;
	private List<UserService> userServiceList;
	@Override
	public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
		// 通过上下文,根据接口类型返回相应的所有实现类bean
		userServiceMap = applicationContext.getBeansOfType(UserService.class);
		userServiceList = new ArrayList<>(userServiceMap.values());
	}
	
	/**
	 * 获取所有实现类
	 *
	 * @return
	 */
	public Map<String, UserService> getAllMap() {
		return userServiceMap;
	}

	/**
	 * 通过名称获取某个实现类
	 *
	 * @param beanName
	 *            bean名字
	 * @return
	 */
	private UserService getByName(String beanName) {
		return userServiceMap.get(beanName);
	}

	/**
	 * 获取所有实现类
	 *
	 * @return
	 */
	public List<UserService> getAllList() {
		return userServiceList;
	}

	/**
	 * 根据枚举获取某个实现类
	 *
	 * @param xxxTypeEnum
	 * @return
	 */
	public UserService get(XxxTypeEnum xxxTypeEnum) {
		UserService xxxService = userServiceList.stream().filter(s -> s.isSupport(xxxTypeEnum))
				.collect(Collectors.toList()).get(0);
		return xxxService;
	}

}

二、策略模式典型应用

spring自动注入接口的多个实现类(结合策略设计模式)
在使用spring开发的时候,有时候会出现一个接口多个实现类的情况,但是有没有有时候有这样一种情况,就是你的逻辑代码里面还不知道你需要使用哪个实现类,就是比如说:你去按摩,按摩店里面有几种会员打折,比如有,vip、svip和普通用户,那按摩店里面是不是需要对这些会员定义好不同的折扣,然后根据每个用户不同的会员计算出不同的消费情况

虽然这样的情况,对于一般人来说,第一眼肯定就是说,直接加 if else 去判断就可以了

这样做,对于实现功能而言,肯定是没问题,如果以后这个按摩店又增加一种会员,那你是不是又要去修改你的逻辑代码去在加一个 if else ,这样就违反了系统架构设计的开闭原则,这样写if else 也使你的代码看起来不优雅。

在代码里面,我们可以先定义一个DiscountStrategy接口类

//顶层会员接口,这个接口的实现类有多个

public interface DiscountStrategy {
    public String getType();
    public double disCount(double fee);
 
}

然后在写他的几个实现类

/**
普通用户实现类
*/
@Service
public class NormalDisCountService implements  DiscountStrategy {
 
    public String getType(){
        return "normal";
    }
 
    public double disCount(double fee){
        return fee * 1;
    }
 
}
/**
会员实现类
*/
@service
public class VipDisCountService  implements  DiscountStrategy{
 
    public String getType(){
        return "vip";
    }
 
    public double disCount(double fee){
        return fee * 0.8;
    }
 
}
/**
svip超级会员实现类
*/
@Service
public class SVipDisCountService  implements  DiscountStrategy {
 
    public String getType(){
        return "svip";
    }
 
    public double disCount(double fee){
        return fee * 0.5;
    }
 
}

解决方案
然后当一个用户进来消费的时候,根据你当前的身份去打折扣

定义一个map集合,然后把所有的实现类都放入到这个集合中,然后根据当前的会员类型去进行不同的操作

@Service
public class DisCountStrageService {
    Map<String,DiscountStrategy> discountStrategyMap = new HashMap<>();
    // 构造函数,如果你是集合接口对象,那么久会把spring容器中所有关于该接口的子类,全部抓出来放入到集合中
    @Authwired 
    public DisCountStrageService(List<DiscountStrategy> discountStrategys){
        for (DiscountStrategy discountStrategy: discountStrategys) {
            discountStrategyMap.put(discountStrategy.getType(),discountStrategy);
        }
    }
 
    public double disCount(String type,Double fee){
        DiscountStrategy discountStrategy =discountStrategyMap.get(type);
        return discountStrategy.disCount(fee);
    }
}

测试类

@RunWith(SpringRunner.class)
@SpringBootTest
public class MzySpringModeApplicationTests {
 
    @Autowired
    OrderService orderService;
 
    @Autowired
    DisCountStrageService disCountStrageService;
 
    @Test
    public void contextLoads() {
        //orderService.saveOrder();
        double vipresult = disCountStrageService.disCount("vip",100d);
        double svipresult = disCountStrageService.disCount("svip",100d);
        double normalresult = disCountStrageService.disCount("normal",100d);
        System.out.println(vipresult);
        System.out.println(svipresult);
        System.out.println(normalresult);
    }
}

其实这就是java设计模式的策略模式,只不过就是用构造函数注入到list集合中

你可能感兴趣的:(java,数据库,开发语言)