说明

将策略放到自定义注解的成员变量上,这样避免了以策略命名实例,也避免了单独维护套策略与实现的关系。

创建自定义注解

import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface UserServiceAnnotation {
    
    String value() default "";

    /**
     * 策略
     */
    String strategy();
}

创建接口

public interface UserService {
    String getName();
}

策略收集和策略匹配

mport com.test.boot.annotation.UserServiceAnnotation;
import com.test.boot.service.UserService;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.core.annotation.AnnotationUtils;
import org.springframework.stereotype.Component;

import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * 策略收集和策略匹配
 */
@Component
public final class StrategyBeanContext implements BeanPostProcessor {

    /**
     * 用户相关策略容器
     */
    private final Map<String, UserService> userServiceStrategy = new ConcurrentHashMap<>();

    /**
     * 策略收集
     * 
     * @param bean  实例
     * @param beanName 实例名
     */
    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        UserServiceAnnotation annotation = AnnotationUtils.findAnnotation(bean.getClass(), UserServiceAnnotation.class);
        if (annotation != null) {
            userServiceStrategy.put(annotation.strategy(), (UserService) bean);
        }
        return bean;
    }

    /**
     * 匹配用户相关策略
     * 
     * @param strategy 策略
     */
    public UserService getUserServiceStrategy(String strategy) {
        UserService userService = userServiceStrategy.get(strategy);
        if (userService != null) {
            return userService;
        }
        return userServiceStrategy.get("default");
    }
}

创建多个类实现上面的接口

实现一

import com.boot.service.UserService;
import org.springframework.stereotype.Service;

@Service
@UserServiceAnnotation("zhangsan")
public class ZhangsanUserServiceImpl implements UserService {
    @Override
    public String getName() {
        return "My name is zhangsan.";
    }
}

实现二


import com.boot.service.UserService;
import org.springframework.stereotype.Service;

@Service
@UserServiceAnnotation("lisi")
public class LisiUserServiceImpl implements UserService {
    
    @Override
    public String getName() {
        return "Hi my name is lisi.";
    }
}

实现三

import com.test.boot.annotation.UserServiceAnnotation;
import com.test.boot.service.UserService;
import org.springframework.stereotype.Service;

@Service
@UserServiceAnnotation(strategy = "default")
public class DefaultUserServiceImpl implements UserService {
    @Override
    public String getName() {
        return "未匹配到指定实现类使用默认实现类";
    }
}

提供接口

@Autowired
private StrategyBeanContext strategyBeanContext;

@GetMapping("userTest")
public String getName(@RequestParam String name) {
    UserService userServiceStrategy = strategyBeanContext.getUserServiceStrategy(name);
    if (userServiceStrategy == null) {
        return "提示未匹配到策略实现";
    }
    String say = userServiceStrategy.getName();
    System.out.println(say);
    return say;
}

调接口

GET http://localhost:8080/userTest?name=zhangsan 结果:My name is zhangsan.
GET http://localhost:8080/userTest?name=lisi  结果:Hi my name is lisi.
GET http://localhost:8080/userTest?name=wangwu  结果:未匹配到指定实现类使用通用实现类