欧美一区二区三区老妇人-欧美做爰猛烈大尺度电-99久久夜色精品国产亚洲a-亚洲福利视频一区二区

Spring使用BeanPostProcessor實現(xiàn)AB測試的方法

這篇文章主要講解了“Spring使用BeanPostProcessor實現(xiàn)AB測試的方法”,文中的講解內(nèi)容簡單清晰,易于學(xué)習(xí)與理解,下面請大家跟著小編的思路慢慢深入,一起來研究和學(xué)習(xí)“Spring使用BeanPostProcessor實現(xiàn)AB測試的方法”吧!

創(chuàng)新互聯(lián)長期為成百上千家客戶提供的網(wǎng)站建設(shè)服務(wù),團隊從業(yè)經(jīng)驗10年,關(guān)注不同地域、不同群體,并針對不同對象提供差異化的產(chǎn)品和服務(wù);打造開放共贏平臺,與合作伙伴共同營造健康的互聯(lián)網(wǎng)生態(tài)環(huán)境。為上林企業(yè)提供專業(yè)的做網(wǎng)站、網(wǎng)站建設(shè),上林網(wǎng)站改版等技術(shù)服務(wù)。擁有十多年豐富建站經(jīng)驗和眾多成功案例,為您定制開發(fā)。

第一步:

創(chuàng)建要實現(xiàn)AB測試的接口、實現(xiàn)類、controller

@RoutingSwitch("hello.switch")
public interface HelloService {

    @RoutingSwitch("B")
    String sayHello();
    @RoutingSwitch("A")
    String sayHi();
}
@Service
public class HelloServiceImplV1 implements HelloService {

    @Override
    public String sayHello() {
        String helloV1= "hello from V1";
        System.out.println("hello from V1");
        return helloV1;
    }

    @Override
    public String sayHi() {
        String hiV1= "hi from V1";
        System.out.println("hi from V1");
        return hiV1;
    }
}
@Service
public class HelloServiceImplV2 implements HelloService {
    @Override
    public String sayHello() {
        String helloV2 = "hello from V2";
        System.out.println("hello from V2");
        return helloV2;
    }

    @Override
    public String sayHi() {
        String hiV2 = "hi from V2";
        System.out.println("hi from V2");
        return hiV2;
    }
}
@RestController
@RequestMapping("/test")
public class HelloControllerV2 {
    @RoutingInject
    private HelloService helloService;

    @GetMapping("/hello")
    public String sayHello() {
       return helloService.sayHello();
    }

    @GetMapping("/hi")
    public String sayHi() {
        return helloService.sayHi();
    }
}

第二步:

創(chuàng)建RoutingBeanPostProcessor類實現(xiàn)接口BeanPostProcessor。注冊controller的bean時,對使用@RoutingInject注解的接口,創(chuàng)建動態(tài)代理類實現(xiàn)類。在使用該接口時,通過invoke方法創(chuàng)建接口實現(xiàn)類。

對接口設(shè)置動態(tài)代理類注解:

@Target({ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Component
public @interface RoutingInject {
}

開關(guān)設(shè)置注解:

@Target({ElementType.FIELD, ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Component
public @interface RoutingSwitch {
    String value();
}

bean初始化后,對使用RoutingInject的注解類,進行處理后置處理

@Component
public class RoutingBeanPostProcessor implements BeanPostProcessor {
    @Autowired
    private ApplicationContext applicationContext;

    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        return bean;
    }

    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        Class clazz = bean.getClass();
        Field[] fields = clazz.getDeclaredFields();
        for (Field f : fields) {
            if(f.isAnnotationPresent(RoutingInject.class)) {
                if(!f.getType().isInterface()) {
                    throw new BeanCreationException("RoutingInject field must be declared as an interface:" + "@Class" + clazz.getName());
                }
                try {
                    this.handleRoutingInjected(f, bean, f.getType());
                } catch (IllegalAccessException e) {
                    throw new BeanCreationException("Exception thrown when handleAutowiredRouting", e);
                }
            }
        }
        return bean;
    }

    private void handleRoutingInjected(Field field, Object bean, Class type) throws IllegalAccessException {
        Map<String, Object> candidates = applicationContext.getBeansOfType(type);
        field.setAccessible(true);
        if(candidates.size() == 1) {
            field.set(bean, candidates.entrySet().iterator().next());
        }else if(candidates.size() == 2) {
            Object proxy = RoutingBeanProxyFactory.createProxy(type, candidates);
            field.set(bean, proxy);
        }else{
            throw new IllegalAccessException("Find more bean 2 bean for type: " + type);
        }
    }
}

代理工程實現(xiàn)類:

public class RoutingBeanProxyFactory {
    public static Object createProxy(Class targetClass, Map<String, Object> beans) {
        ProxyFactory proxyFactory = new ProxyFactory();
        proxyFactory.setInterfaces(new Class[]{targetClass});
        proxyFactory.addAdvice(new VersionRoutingMethodInterceptor(targetClass, beans));
        return proxyFactory.getProxy();
    }

    static class VersionRoutingMethodInterceptor implements MethodInterceptor {
        private String classSwitch;
        private Object beanSwitchOn;
        private Object beanSwitchOff;

        public VersionRoutingMethodInterceptor(Class targetClass, Map<String, Object> beans) {
            String interfaceName = StringUtils.uncapitalize(targetClass.getSimpleName());
            if(targetClass.isAnnotationPresent(RoutingSwitch.class)) {
                this.classSwitch = ((RoutingSwitch) targetClass.getAnnotation(RoutingSwitch.class)).value();
            }
            this.beanSwitchOn = beans.get(this.buildBeanName(interfaceName, true));
            this.beanSwitchOff = beans.get(this.buildBeanName(interfaceName, false));
        }

        private String buildBeanName(String interfaceName, boolean isSwitchOn) {
            return interfaceName + "Impl" + (isSwitchOn ? "V2" : "V1");
        }

        @Override
        public Object invoke(MethodInvocation invocation) throws Throwable {
            Method method = invocation.getMethod();
            String switchName = this.classSwitch;
            if(method.isAnnotationPresent(RoutingSwitch.class)) {
                switchName = method.getAnnotation(RoutingSwitch.class).value();
            }

            if(StringUtils.isBlank(switchName)) {
                throw new IllegalStateException("RoutingSwitch's value is blank, method:" + method.getName());
            }
            return invocation.getMethod().invoke(getTargetName(switchName), invocation.getArguments());
        }

        public Object getTargetName(String switchName) {
            boolean switchOn;
            if(RoutingVersion.A.name().equals(switchName)) {
                switchOn = false;
            }else{
                switchOn = true;
            }

            return switchOn ? beanSwitchOn : beanSwitchOff;
        }
    }

    enum RoutingVersion{
        A,B
    }
}

第三步:

測試接口正常

Spring使用BeanPostProcessor實現(xiàn)AB測試的方法

Spring使用BeanPostProcessor實現(xiàn)AB測試的方法

感謝各位的閱讀,以上就是“Spring使用BeanPostProcessor實現(xiàn)AB測試的方法”的內(nèi)容了,經(jīng)過本文的學(xué)習(xí)后,相信大家對Spring使用BeanPostProcessor實現(xiàn)AB測試的方法這一問題有了更深刻的體會,具體使用情況還需要大家實踐驗證。這里是創(chuàng)新互聯(lián),小編將為大家推送更多相關(guān)知識點的文章,歡迎關(guān)注!

當(dāng)前名稱:Spring使用BeanPostProcessor實現(xiàn)AB測試的方法
本文來源:http://chinadenli.net/article10/pooigo.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供網(wǎng)站導(dǎo)航、App開發(fā)、App設(shè)計、虛擬主機網(wǎng)站改版、外貿(mào)網(wǎng)站建設(shè)

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時需注明來源: 創(chuàng)新互聯(lián)

手機網(wǎng)站建設(shè)