使用自定义注解通过BeanPostProcessor实现策略模式
说明
将策略放到自定义注解的成员变量上,这样避免了以策略命名实例,也避免了单独维护套策略与实现的关系。
创建自定义注解
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 结果:未匹配到指定实现类使用通用实现类
纸上得来终觉浅,绝知此事要躬行。