In addition to Weibo, there is also WeChat
Please pay attention
WeChat public account
Shulou
2025-04-02 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Internet Technology >
Share
Shulou(Shulou.com)06/02 Report--
This article mainly explains "Spring uses BeanPostProcessor to achieve AB testing". The content of the article is simple and clear, and it is easy to learn and understand. Please follow the editor's train of thought to study and learn "Spring uses BeanPostProcessor to achieve AB testing".
Step one:
Create the interface, implementation class, controller to implement the AB test
RoutingSwitch ("hello.switch") public interface HelloService {@ RoutingSwitch ("B") String sayHello (); @ RoutingSwitch ("A") String sayHi ();} @ Servicepublic 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;}} @ Servicepublic 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 ();}}
Step 2:
Create the RoutingBeanPostProcessor class to implement the interface BeanPostProcessor. When registering controller's bean, create a dynamic proxy class implementation class for the interface annotated with @ RoutingInject. When using this interface, create the interface implementation class through the invoke method.
Set dynamic proxy class comments on the interface:
@ Target ({ElementType.FIELD}) @ Retention (RetentionPolicy.RUNTIME) @ Documented@Componentpublic @ interface RoutingInject {}
Switch setting notes:
Target ({ElementType.FIELD, ElementType.METHOD, ElementType.TYPE}) @ Retention (RetentionPolicy.RUNTIME) @ Documented@Componentpublic @ interface RoutingSwitch {String value ();}
After initialization of bean, post-processing is performed for annotation classes that use RoutingInject
@ Componentpublic 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 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);}
Agent engineering implementation class:
Public class RoutingBeanProxyFactory {public static Object createProxy (Class targetClass, Map 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 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}}
Step 3:
The test interface is normal.
Thank you for your reading, the above is the content of "Spring uses BeanPostProcessor to achieve AB testing". After the study of this article, I believe you have a deeper understanding of the problem of Spring using BeanPostProcessor to achieve AB testing, and the specific use needs to be verified in practice. Here is, the editor will push for you more related knowledge points of the article, welcome to follow!
Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.
Views: 0
*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.
Continue with the installation of the previous hadoop.First, install zookooper1. Decompress zookoope
"Every 5-10 years, there's a rare product, a really special, very unusual product that's the most un
© 2024 shulou.com SLNews company. All rights reserved.