使用自定義註解透過BeanPostProcessor實現策略模式

品书读茶發表於2024-03-12

說明

將策略放到自定義註解的成員變數上

建立自定義註解

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();
}

匹配策略

import 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 class UserServiceBeanContext implements BeanPostProcessor {

    private final Map<String, UserService> userServiceMap = new ConcurrentHashMap<>();
    
    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        UserServiceAnnotation annotation = AnnotationUtils.findAnnotation(bean.getClass(), UserServiceAnnotation.class);
        if (annotation != null) {
            userServiceMap.put(annotation.strategy(), (UserService) bean);
        }
        return bean;
    }

    public UserService getUserServiceMap(String strategy) {
        UserService userService = userServiceMap.get(strategy);
        if (userService != null) {
            return userService;
        }
        return userServiceMap.get("common");
    }
}

建立多個類實現上面的介面

實現一

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 = "common")
public class CommonUserServiceImpl implements UserService {
    @Override
    public String getName() {
        
        return "未匹配到指定實現類使用通用實現類";
    }
}

提供http請求介面

@Autowired
private UserServiceBeanContext userServiceBeanContext;

@GetMapping("userTest")
public String getName(@RequestParam String name) {
    UserService userServiceMap = userServiceBeanContext.getUserServiceMap(name);
    if (userServiceMap == null) {
        return "提示";
    }
    String say = userServiceMap.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  結果:未匹配到指定實現類使用通用實現類

相關文章