diff --git a/build.gradle b/build.gradle
index 52bf70f38..2c2371e99 100644
--- a/build.gradle
+++ b/build.gradle
@@ -51,7 +51,6 @@ dependencies {
         }
     }
     implementation 'com.google.code.gson:gson:2.10.1'
-    implementation 'cglib:cglib:3.3.0'
     implementation 'commons-validator:commons-validator:1.7'
     implementation 'org.apache.commons:commons-lang3:3.12.0'
     implementation 'commons-io:commons-io:2.12.0'
diff --git a/src/main/java/io/appium/java_client/pagefactory/AppiumFieldDecorator.java b/src/main/java/io/appium/java_client/pagefactory/AppiumFieldDecorator.java
index 8bb282859..b1119f34e 100644
--- a/src/main/java/io/appium/java_client/pagefactory/AppiumFieldDecorator.java
+++ b/src/main/java/io/appium/java_client/pagefactory/AppiumFieldDecorator.java
@@ -32,6 +32,7 @@
 import org.openqa.selenium.support.pagefactory.ElementLocator;
 import org.openqa.selenium.support.pagefactory.FieldDecorator;
 
+import javax.annotation.Nullable;
 import java.lang.reflect.Constructor;
 import java.lang.reflect.Field;
 import java.lang.reflect.ParameterizedType;
@@ -92,17 +93,17 @@ public AppiumFieldDecorator(SearchContext context, Duration duration) {
         this.duration = duration;
 
         defaultElementFieldDecoracor = new DefaultFieldDecorator(
-                new AppiumElementLocatorFactory(context, duration,
-                        new DefaultElementByBuilder(platform, automation))) {
+                new AppiumElementLocatorFactory(context, duration, new DefaultElementByBuilder(platform, automation))
+        ) {
             @Override
             protected WebElement proxyForLocator(ClassLoader ignored, ElementLocator locator) {
                 return proxyForAnElement(locator);
             }
 
             @Override
-            @SuppressWarnings("unchecked")
             protected List<WebElement> proxyForListLocator(ClassLoader ignored, ElementLocator locator) {
                 ElementListInterceptor elementInterceptor = new ElementListInterceptor(locator);
+                //noinspection unchecked
                 return getEnhancedProxy(ArrayList.class, elementInterceptor);
             }
 
@@ -121,14 +122,14 @@ protected boolean isDecoratableList(Field field) {
                 List<Type> bounds = (listType instanceof TypeVariable)
                         ? Arrays.asList(((TypeVariable<?>) listType).getBounds())
                         : Collections.emptyList();
-
                 return availableElementClasses.stream()
                         .anyMatch((webElClass) -> webElClass.equals(listType) || bounds.contains(webElClass));
             }
         };
 
-        widgetLocatorFactory =
-                new AppiumElementLocatorFactory(context, duration, new WidgetByBuilder(platform, automation));
+        widgetLocatorFactory = new AppiumElementLocatorFactory(
+                context, duration, new WidgetByBuilder(platform, automation)
+        );
     }
 
     public AppiumFieldDecorator(SearchContext context) {
@@ -144,14 +145,10 @@ public AppiumFieldDecorator(SearchContext context) {
      */
     public Object decorate(ClassLoader ignored, Field field) {
         Object result = defaultElementFieldDecoracor.decorate(ignored, field);
-        if (result != null) {
-            return result;
-        }
-
-        return decorateWidget(field);
+        return result == null ? decorateWidget(field) : result;
     }
 
-    @SuppressWarnings("unchecked")
+    @Nullable
     private Object decorateWidget(Field field) {
         Class<?> type = field.getType();
         if (!Widget.class.isAssignableFrom(type) && !List.class.isAssignableFrom(type)) {
@@ -177,30 +174,34 @@ private Object decorateWidget(Field field) {
                 if (!Widget.class.isAssignableFrom((Class<?>) listType)) {
                     return null;
                 }
+                //noinspection unchecked
                 widgetType = (Class<? extends Widget>) listType;
             } else {
                 return null;
             }
 
         } else {
+            //noinspection unchecked
             widgetType = (Class<? extends Widget>) field.getType();
         }
 
         CacheableLocator locator = widgetLocatorFactory.createLocator(field);
-        Map<ContentType, Constructor<? extends Widget>> map =
-                OverrideWidgetReader.read(widgetType, field, platform);
+        Map<ContentType, Constructor<? extends Widget>> map = OverrideWidgetReader.read(widgetType, field, platform);
 
         if (isAlist) {
-            return getEnhancedProxy(ArrayList.class,
-                    new WidgetListInterceptor(locator, webDriver, map, widgetType,
-                            duration));
+            return getEnhancedProxy(
+                    ArrayList.class,
+                    new WidgetListInterceptor(locator, webDriver, map, widgetType, duration)
+            );
         }
 
-        Constructor<? extends Widget> constructor =
-                WidgetConstructorUtil.findConvenientConstructor(widgetType);
-        return getEnhancedProxy(widgetType, new Class[]{constructor.getParameterTypes()[0]},
+        Constructor<? extends Widget> constructor = WidgetConstructorUtil.findConvenientConstructor(widgetType);
+        return getEnhancedProxy(
+                widgetType,
+                new Class[]{constructor.getParameterTypes()[0]},
                 new Object[]{proxyForAnElement(locator)},
-                new WidgetInterceptor(locator, webDriver, null, map, duration));
+                new WidgetInterceptor(locator, webDriver, null, map, duration)
+        );
     }
 
     private WebElement proxyForAnElement(ElementLocator locator) {
diff --git a/src/main/java/io/appium/java_client/pagefactory/ElementInterceptor.java b/src/main/java/io/appium/java_client/pagefactory/ElementInterceptor.java
index efe7bd95f..5047fcc11 100644
--- a/src/main/java/io/appium/java_client/pagefactory/ElementInterceptor.java
+++ b/src/main/java/io/appium/java_client/pagefactory/ElementInterceptor.java
@@ -28,13 +28,14 @@
 /**
  * Intercepts requests to {@link WebElement}.
  */
-class ElementInterceptor extends InterceptorOfASingleElement {
+public class ElementInterceptor extends InterceptorOfASingleElement {
 
-    ElementInterceptor(ElementLocator locator, WebDriver driver) {
+    public ElementInterceptor(ElementLocator locator, WebDriver driver) {
         super(locator, driver);
     }
 
-    @Override protected Object getObject(WebElement element, Method method, Object[] args)
+    @Override
+    protected Object getObject(WebElement element, Method method, Object[] args)
         throws Throwable {
         try {
             return method.invoke(element, args);
diff --git a/src/main/java/io/appium/java_client/pagefactory/ElementListInterceptor.java b/src/main/java/io/appium/java_client/pagefactory/ElementListInterceptor.java
index fc7164533..adeec4455 100644
--- a/src/main/java/io/appium/java_client/pagefactory/ElementListInterceptor.java
+++ b/src/main/java/io/appium/java_client/pagefactory/ElementListInterceptor.java
@@ -28,13 +28,14 @@
 /**
  * Intercepts requests to the list of {@link WebElement}.
  */
-class ElementListInterceptor extends InterceptorOfAListOfElements {
+public class ElementListInterceptor extends InterceptorOfAListOfElements {
 
-    ElementListInterceptor(ElementLocator locator) {
+    public ElementListInterceptor(ElementLocator locator) {
         super(locator);
     }
 
-    @Override protected Object getObject(List<WebElement> elements, Method method, Object[] args)
+    @Override
+    protected Object getObject(List<WebElement> elements, Method method, Object[] args)
         throws Throwable {
         try {
             return method.invoke(elements, args);
diff --git a/src/main/java/io/appium/java_client/pagefactory/ThrowableUtil.java b/src/main/java/io/appium/java_client/pagefactory/ThrowableUtil.java
index ca65e9e24..c025a53dd 100644
--- a/src/main/java/io/appium/java_client/pagefactory/ThrowableUtil.java
+++ b/src/main/java/io/appium/java_client/pagefactory/ThrowableUtil.java
@@ -33,8 +33,8 @@ protected static boolean isInvalidSelectorRootCause(Throwable e) {
             return true;
         }
 
-        if (String.valueOf(e.getMessage()).contains(INVALID_SELECTOR_PATTERN) || String
-            .valueOf(e.getMessage()).contains("Locator Strategy \\w+ is not supported")) {
+        if (String.valueOf(e.getMessage()).contains(INVALID_SELECTOR_PATTERN)
+                || String.valueOf(e.getMessage()).contains("Locator Strategy \\w+ is not supported")) {
             return true;
         }
 
@@ -54,8 +54,8 @@ protected static boolean isStaleElementReferenceException(Throwable e) {
     }
 
     protected static Throwable extractReadableException(Throwable e) {
-        if (!RuntimeException.class.equals(e.getClass()) && !InvocationTargetException.class
-            .equals(e.getClass())) {
+        if (!RuntimeException.class.equals(e.getClass())
+                && !InvocationTargetException.class.equals(e.getClass())) {
             return e;
         }
 
diff --git a/src/main/java/io/appium/java_client/pagefactory/WidgetInterceptor.java b/src/main/java/io/appium/java_client/pagefactory/WidgetInterceptor.java
index 2c3296d35..1155fc7cc 100644
--- a/src/main/java/io/appium/java_client/pagefactory/WidgetInterceptor.java
+++ b/src/main/java/io/appium/java_client/pagefactory/WidgetInterceptor.java
@@ -19,17 +19,18 @@
 import io.appium.java_client.pagefactory.bys.ContentType;
 import io.appium.java_client.pagefactory.interceptors.InterceptorOfASingleElement;
 import io.appium.java_client.pagefactory.locator.CacheableLocator;
-import net.sf.cglib.proxy.MethodProxy;
 import org.openqa.selenium.WebDriver;
 import org.openqa.selenium.WebElement;
 import org.openqa.selenium.support.PageFactory;
 
+import javax.annotation.Nullable;
 import java.lang.reflect.Constructor;
 import java.lang.reflect.Method;
 import java.lang.reflect.Modifier;
 import java.time.Duration;
 import java.util.HashMap;
 import java.util.Map;
+import java.util.concurrent.Callable;
 
 import static io.appium.java_client.pagefactory.ThrowableUtil.extractReadableException;
 import static io.appium.java_client.pagefactory.utils.WebDriverUnpackUtility.getCurrentContentType;
@@ -41,33 +42,35 @@ class WidgetInterceptor extends InterceptorOfASingleElement {
     private final Duration duration;
     private WebElement cachedElement;
 
-    WidgetInterceptor(CacheableLocator locator, WebDriver driver, WebElement cachedElement,
-        Map<ContentType, Constructor<? extends Widget>> instantiationMap,
-        Duration duration) {
+    WidgetInterceptor(
+            CacheableLocator locator,
+            WebDriver driver,
+            @Nullable
+            WebElement cachedElement,
+            Map<ContentType, Constructor<? extends Widget>> instantiationMap,
+            Duration duration
+    ) {
         super(locator, driver);
         this.cachedElement = cachedElement;
         this.instantiationMap = instantiationMap;
         this.duration = duration;
     }
 
-
-    @Override protected Object getObject(WebElement element, Method method, Object[] args)
-        throws Throwable {
+    @Override protected Object getObject(WebElement element, Method method, Object[] args) throws Throwable {
         ContentType type = getCurrentContentType(element);
         if (cachedElement == null
-            || (locator != null && !((CacheableLocator) locator)
-            .isLookUpCached())
-            || cachedInstances.size() == 0) {
+            || (locator != null && !((CacheableLocator) locator).isLookUpCached())
+            || cachedInstances.isEmpty()
+        ) {
             cachedElement = element;
 
             Constructor<? extends Widget> constructor = instantiationMap.get(type);
             Class<? extends Widget> clazz = constructor.getDeclaringClass();
 
-            int modifiers = clazz.getModifiers();
-            if (Modifier.isAbstract(modifiers)) {
-                throw new InstantiationException(clazz.getName()
-                        + " is abstract so "
-                        + "it can't be instantiated");
+            if (Modifier.isAbstract(clazz.getModifiers())) {
+                throw new InstantiationException(
+                        String.format("%s  is abstract so it cannot be instantiated", clazz.getName())
+                );
             }
 
             Widget widget = constructor.newInstance(cachedElement);
@@ -82,11 +85,10 @@ class WidgetInterceptor extends InterceptorOfASingleElement {
         }
     }
 
-    public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy)
-        throws Throwable {
-        if (locator != null) {
-            return super.intercept(obj, method, args, proxy);
-        }
-        return getObject(cachedElement, method, args);
+    @Override
+    public Object call(Object obj, Method method, Object[] args, Callable<?> original) throws Throwable {
+        return locator == null
+                ? getObject(cachedElement, method, args)
+                : super.call(obj, method, args, original);
     }
 }
diff --git a/src/main/java/io/appium/java_client/pagefactory/WidgetListInterceptor.java b/src/main/java/io/appium/java_client/pagefactory/WidgetListInterceptor.java
index 04115aaa9..c48b7b3ac 100644
--- a/src/main/java/io/appium/java_client/pagefactory/WidgetListInterceptor.java
+++ b/src/main/java/io/appium/java_client/pagefactory/WidgetListInterceptor.java
@@ -19,7 +19,6 @@
 import io.appium.java_client.pagefactory.bys.ContentType;
 import io.appium.java_client.pagefactory.interceptors.InterceptorOfAListOfElements;
 import io.appium.java_client.pagefactory.locator.CacheableLocator;
-import io.appium.java_client.pagefactory.utils.ProxyFactory;
 import org.openqa.selenium.WebDriver;
 import org.openqa.selenium.WebElement;
 
@@ -31,11 +30,11 @@
 import java.util.Map;
 
 import static io.appium.java_client.pagefactory.ThrowableUtil.extractReadableException;
+import static io.appium.java_client.pagefactory.utils.ProxyFactory.getEnhancedProxy;
 import static io.appium.java_client.pagefactory.utils.WebDriverUnpackUtility.getCurrentContentType;
 import static java.util.Optional.ofNullable;
 
-class WidgetListInterceptor extends InterceptorOfAListOfElements {
-
+public class WidgetListInterceptor extends InterceptorOfAListOfElements {
     private final Map<ContentType, Constructor<? extends Widget>> instantiationMap;
     private final List<Widget> cachedWidgets = new ArrayList<>();
     private final Class<? extends Widget> declaredType;
@@ -43,7 +42,7 @@ class WidgetListInterceptor extends InterceptorOfAListOfElements {
     private final WebDriver driver;
     private List<WebElement> cachedElements;
 
-    WidgetListInterceptor(CacheableLocator locator, WebDriver driver,
+    public WidgetListInterceptor(CacheableLocator locator, WebDriver driver,
         Map<ContentType, Constructor<? extends Widget>> instantiationMap,
         Class<? extends Widget> declaredType, Duration duration) {
         super(locator);
@@ -53,22 +52,22 @@ class WidgetListInterceptor extends InterceptorOfAListOfElements {
         this.driver = driver;
     }
 
-
-    @Override protected Object getObject(List<WebElement> elements, Method method, Object[] args)
-        throws Throwable {
-        if (cachedElements == null || (locator != null && !((CacheableLocator) locator)
-            .isLookUpCached())) {
+    @Override
+    protected Object getObject(List<WebElement> elements, Method method, Object[] args) throws Throwable {
+        if (cachedElements == null || (locator != null && !((CacheableLocator) locator).isLookUpCached())) {
             cachedElements = elements;
             cachedWidgets.clear();
 
             ContentType type = null;
             for (WebElement element : cachedElements) {
                 type = ofNullable(type).orElseGet(() -> getCurrentContentType(element));
-                Class<?>[] params =
-                    new Class<?>[] {instantiationMap.get(type).getParameterTypes()[0]};
-                cachedWidgets.add(ProxyFactory
-                    .getEnhancedProxy(declaredType, params, new Object[] {element},
-                        new WidgetInterceptor(null, driver, element, instantiationMap, duration)));
+                Class<?>[] params = new Class<?>[] {instantiationMap.get(type).getParameterTypes()[0]};
+                cachedWidgets.add(
+                        getEnhancedProxy(
+                                declaredType, params, new Object[] {element},
+                                new WidgetInterceptor(null, driver, element, instantiationMap, duration)
+                        )
+                );
             }
         }
         try {
diff --git a/src/main/java/io/appium/java_client/pagefactory/interceptors/InterceptorOfAListOfElements.java b/src/main/java/io/appium/java_client/pagefactory/interceptors/InterceptorOfAListOfElements.java
index 8b96c6c68..d276ce616 100644
--- a/src/main/java/io/appium/java_client/pagefactory/interceptors/InterceptorOfAListOfElements.java
+++ b/src/main/java/io/appium/java_client/pagefactory/interceptors/InterceptorOfAListOfElements.java
@@ -16,33 +16,30 @@
 
 package io.appium.java_client.pagefactory.interceptors;
 
-import net.sf.cglib.proxy.MethodInterceptor;
-import net.sf.cglib.proxy.MethodProxy;
+import io.appium.java_client.proxy.MethodCallListener;
 import org.openqa.selenium.WebElement;
 import org.openqa.selenium.support.pagefactory.ElementLocator;
 
-import java.lang.reflect.InvocationTargetException;
 import java.lang.reflect.Method;
 import java.util.ArrayList;
 import java.util.List;
+import java.util.concurrent.Callable;
 
-public abstract class InterceptorOfAListOfElements implements MethodInterceptor {
+public abstract class InterceptorOfAListOfElements implements MethodCallListener {
     protected final ElementLocator locator;
 
     public InterceptorOfAListOfElements(ElementLocator locator) {
         this.locator = locator;
     }
 
-    protected abstract Object getObject(List<WebElement> elements, Method method, Object[] args)
-        throws InvocationTargetException, IllegalAccessException, InstantiationException, Throwable;
+    protected abstract Object getObject(
+            List<WebElement> elements, Method method, Object[] args
+    ) throws Throwable;
 
-    /**
-     * Look at {@link MethodInterceptor#intercept(Object, Method, Object[], MethodProxy)}.
-     */
-    public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy)
-        throws Throwable {
+    @Override
+    public Object call(Object obj, Method method, Object[] args, Callable<?> original) throws Throwable {
         if (Object.class.equals(method.getDeclaringClass())) {
-            return proxy.invokeSuper(obj, args);
+            return original.call();
         }
 
         List<WebElement> realElements = new ArrayList<>(locator.findElements());
diff --git a/src/main/java/io/appium/java_client/pagefactory/interceptors/InterceptorOfASingleElement.java b/src/main/java/io/appium/java_client/pagefactory/interceptors/InterceptorOfASingleElement.java
index d06555eaf..c457353ae 100644
--- a/src/main/java/io/appium/java_client/pagefactory/interceptors/InterceptorOfASingleElement.java
+++ b/src/main/java/io/appium/java_client/pagefactory/interceptors/InterceptorOfASingleElement.java
@@ -16,16 +16,16 @@
 
 package io.appium.java_client.pagefactory.interceptors;
 
-import net.sf.cglib.proxy.MethodInterceptor;
-import net.sf.cglib.proxy.MethodProxy;
+import io.appium.java_client.proxy.MethodCallListener;
 import org.openqa.selenium.WebDriver;
 import org.openqa.selenium.WebElement;
 import org.openqa.selenium.WrapsDriver;
 import org.openqa.selenium.support.pagefactory.ElementLocator;
 
 import java.lang.reflect.Method;
+import java.util.concurrent.Callable;
 
-public abstract class InterceptorOfASingleElement implements MethodInterceptor {
+public abstract class InterceptorOfASingleElement implements MethodCallListener {
     protected final ElementLocator locator;
     protected final WebDriver driver;
 
@@ -37,22 +37,18 @@ public InterceptorOfASingleElement(ElementLocator locator, WebDriver driver) {
     protected abstract Object getObject(WebElement element, Method method, Object[] args)
         throws Throwable;
 
-    /**
-     * Look at {@link MethodInterceptor#intercept(Object, Method, Object[], MethodProxy)}.
-     */
-    public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy)
-        throws Throwable {
-
+    @Override
+    public Object call(Object obj, Method method, Object[] args, Callable<?> original) throws Throwable {
         if (method.getName().equals("toString") && args.length == 0) {
             return locator.toString();
         }
 
         if (Object.class.equals(method.getDeclaringClass())) {
-            return proxy.invokeSuper(obj, args);
+            return original.call();
         }
 
-        if (WrapsDriver.class.isAssignableFrom(method.getDeclaringClass()) && method.getName()
-            .equals("getWrappedDriver")) {
+        if (WrapsDriver.class.isAssignableFrom(method.getDeclaringClass())
+                && method.getName().equals("getWrappedDriver")) {
             return driver;
         }
 
diff --git a/src/main/java/io/appium/java_client/pagefactory/utils/ProxyFactory.java b/src/main/java/io/appium/java_client/pagefactory/utils/ProxyFactory.java
index 390ebcd92..18242a5fd 100644
--- a/src/main/java/io/appium/java_client/pagefactory/utils/ProxyFactory.java
+++ b/src/main/java/io/appium/java_client/pagefactory/utils/ProxyFactory.java
@@ -16,8 +16,21 @@
 
 package io.appium.java_client.pagefactory.utils;
 
-import net.sf.cglib.proxy.Enhancer;
-import net.sf.cglib.proxy.MethodInterceptor;
+import io.appium.java_client.proxy.MethodCallListener;
+import net.bytebuddy.description.method.MethodDescription;
+import net.bytebuddy.matcher.ElementMatcher;
+import net.bytebuddy.matcher.ElementMatchers;
+import org.openqa.selenium.remote.RemoteWebElement;
+
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Set;
+import java.util.UUID;
+import java.util.function.Consumer;
+
+import static io.appium.java_client.proxy.Helpers.OBJECT_METHOD_NAMES;
+import static io.appium.java_client.proxy.Helpers.createProxy;
+import static net.bytebuddy.matcher.ElementMatchers.namedOneOf;
 
 /**
  * Original class is a super class of a
@@ -29,30 +42,55 @@ private ProxyFactory() {
         super();
     }
 
-    public static <T> T getEnhancedProxy(Class<T> requiredClazz, MethodInterceptor interceptor) {
-        return getEnhancedProxy(requiredClazz, new Class<?>[] {}, new Object[] {}, interceptor);
+    /**
+     * Creates a proxy instance for the given class with an empty constructor.
+     *
+     * @param <T> The proxy object class.
+     * @param requiredClazz is a {@link java.lang.Class} whose instance should be created
+     * @param listener is the instance of a method listener class
+     * @return a proxied instance of the desired class
+     */
+    public static <T> T getEnhancedProxy(Class<T> requiredClazz, MethodCallListener listener) {
+        return getEnhancedProxy(requiredClazz, new Class<?>[] {}, new Object[] {}, listener);
     }
 
     /**
-     * It returns some proxies created by CGLIB.
+     * Creates a proxy instance for the given class.
      *
      * @param <T> The proxy object class.
-     * @param requiredClazz is a {@link java.lang.Class} whose instance should be created
+     * @param cls is a {@link java.lang.Class} whose instance should be created
      * @param params is an array of @link java.lang.Class}. It should be convenient to
      *               parameter types of some declared constructor which belongs to desired
      *               class.
      * @param values is an array of @link java.lang.Object}. It should be convenient to
      *               parameter types of some declared constructor which belongs to desired
      *               class.
-     * @param interceptor is the instance of {@link net.sf.cglib.proxy.MethodInterceptor}
+     * @param listener is the instance of a method listener class
      * @return a proxied instance of the desired class
      */
-    @SuppressWarnings("unchecked")
-    public static <T> T getEnhancedProxy(Class<T> requiredClazz, Class<?>[] params, Object[] values,
-        MethodInterceptor interceptor) {
-        Enhancer enhancer = new Enhancer();
-        enhancer.setSuperclass(requiredClazz);
-        enhancer.setCallback(interceptor);
-        return (T) enhancer.create(params, values);
+    public static <T> T getEnhancedProxy(
+            Class<T> cls, Class<?>[] params, Object[] values, MethodCallListener listener
+    ) {
+        // This is an ugly hack that ensures a newly created instance of
+        // RemoteWebElement could be put into a map.
+        // By default, it cannot because
+        //  @Override
+        //  public int hashCode() {
+        //    return id.hashCode();
+        //  }
+        // and, guess what the `id` property equals to for a newly created instance
+        Consumer<T> onInstanceCreated = cls.isAssignableFrom(RemoteWebElement.class)
+                ? (instance) -> ((RemoteWebElement) instance).setId(UUID.randomUUID().toString())
+                : null;
+        Set<String> skippedMethods = new HashSet<>(OBJECT_METHOD_NAMES);
+        skippedMethods.add("iterator");
+        skippedMethods.add("listIterator");
+        skippedMethods.remove("toString");
+        ElementMatcher<MethodDescription> extraMatcher = ElementMatchers.not(namedOneOf(
+                skippedMethods.toArray(new String[0])
+        ));
+        return createProxy(
+                cls, values, params, Collections.singletonList(listener), onInstanceCreated, extraMatcher
+        );
     }
 }
diff --git a/src/main/java/io/appium/java_client/pagefactory/utils/WebDriverUnpackUtility.java b/src/main/java/io/appium/java_client/pagefactory/utils/WebDriverUnpackUtility.java
index e6bb6f6d6..53ba1506c 100644
--- a/src/main/java/io/appium/java_client/pagefactory/utils/WebDriverUnpackUtility.java
+++ b/src/main/java/io/appium/java_client/pagefactory/utils/WebDriverUnpackUtility.java
@@ -24,6 +24,8 @@
 import org.openqa.selenium.WrapsDriver;
 import org.openqa.selenium.WrapsElement;
 
+import javax.annotation.Nullable;
+
 import static io.appium.java_client.pagefactory.bys.ContentType.HTML_OR_DEFAULT;
 import static io.appium.java_client.pagefactory.bys.ContentType.NATIVE_MOBILE_SPECIFIC;
 import static java.util.Optional.ofNullable;
@@ -45,21 +47,20 @@ public final class WebDriverUnpackUtility {
      *         {@link WrapsDriver} or {@link WrapsElement} then this method returns null.
      *
      */
+    @Nullable
     public static WebDriver unpackWebDriverFromSearchContext(SearchContext searchContext) {
         if (searchContext instanceof WebDriver) {
             return (WebDriver) searchContext;
         }
 
         if (searchContext instanceof WrapsDriver) {
-            return unpackWebDriverFromSearchContext(
-                    ((WrapsDriver) searchContext).getWrappedDriver());
+            return unpackWebDriverFromSearchContext(((WrapsDriver) searchContext).getWrappedDriver());
         }
 
         // Search context it is not only WebDriver. WebElement is search context too.
         // RemoteWebElement implements WrapsDriver
         if (searchContext instanceof WrapsElement) {
-            return unpackWebDriverFromSearchContext(
-                    ((WrapsElement) searchContext).getWrappedElement());
+            return unpackWebDriverFromSearchContext(((WrapsElement) searchContext).getWrappedElement());
         }
 
         return null;
diff --git a/src/main/java/io/appium/java_client/proxy/Helpers.java b/src/main/java/io/appium/java_client/proxy/Helpers.java
index 286d7fc31..1722480ef 100644
--- a/src/main/java/io/appium/java_client/proxy/Helpers.java
+++ b/src/main/java/io/appium/java_client/proxy/Helpers.java
@@ -18,16 +18,30 @@
 
 import com.google.common.base.Preconditions;
 import net.bytebuddy.ByteBuddy;
+import net.bytebuddy.description.method.MethodDescription;
 import net.bytebuddy.dynamic.loading.ClassLoadingStrategy;
 import net.bytebuddy.implementation.MethodDelegation;
+import net.bytebuddy.matcher.ElementMatcher;
 import net.bytebuddy.matcher.ElementMatchers;
 
+import javax.annotation.Nullable;
+import java.lang.reflect.Method;
 import java.util.Collection;
 import java.util.Collections;
+import java.util.Set;
+import java.util.function.Consumer;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+
+import static net.bytebuddy.matcher.ElementMatchers.namedOneOf;
 
 public class Helpers {
-    private Helpers() {
-    }
+
+    public static final Set<String> OBJECT_METHOD_NAMES = Stream.of(Object.class.getMethods())
+            .map(Method::getName)
+            .collect(Collectors.toSet());
+
+    private Helpers() {}
 
     /**
      * Creates a transparent proxy instance for the given class.
@@ -53,6 +67,42 @@ public static <T> T createProxy(
             Object[] constructorArgs,
             Class<?>[] constructorArgTypes,
             Collection<MethodCallListener> listeners
+    ) {
+        ElementMatcher<MethodDescription> extraMatcher = ElementMatchers.not(namedOneOf(
+                OBJECT_METHOD_NAMES.toArray(new String[0])
+        ));
+        return createProxy(cls, constructorArgs, constructorArgTypes, listeners, null, extraMatcher);
+    }
+
+    /**
+     * Creates a transparent proxy instance for the given class.
+     * It is possible to provide one or more method execution listeners
+     * or replace particular method calls completely. Callbacks
+     * defined in these listeners are going to be called when any
+     * **public** method of the given class is invoked. Overridden callbacks
+     * are expected to be skipped if they throw
+     * {@link io.appium.java_client.proxy.NotImplementedException}.
+     * !!! This API is designed for private usage.
+     *
+     * @param cls                    The class to which the proxy should be created.
+     *                               Must not be an interface.
+     * @param constructorArgs        Array of constructor arguments. Could be an
+     *                               empty array if the class provides a constructor without arguments.
+     * @param constructorArgTypes    Array of constructor argument types. Must
+     *                               represent types of constructorArgs.
+     * @param listeners              One or more method invocation listeners.
+     * @param onInstanceCreated      Optional proxy instance postprocessor
+     * @param extraMethodMatcher     Optional additional method proxy conditions
+     * @param <T>                    Any class derived from Object
+     * @return Proxy instance
+     */
+    public static <T> T createProxy(
+            Class<T> cls,
+            Object[] constructorArgs,
+            Class<?>[] constructorArgTypes,
+            Collection<MethodCallListener> listeners,
+            @Nullable Consumer<T> onInstanceCreated,
+            @Nullable ElementMatcher<MethodDescription> extraMethodMatcher
     ) {
         Preconditions.checkArgument(constructorArgs.length == constructorArgTypes.length,
                 String.format(
@@ -64,17 +114,18 @@ public static <T> T createProxy(
         Preconditions.checkArgument(cls != null, "Class must not be null");
         Preconditions.checkArgument(!cls.isInterface(), "Class must not be an interface");
 
+        ElementMatcher.Junction<MethodDescription> matcher = ElementMatchers.isPublic();
+        if (extraMethodMatcher != null) {
+            matcher = matcher.and(extraMethodMatcher);
+        }
+
         //noinspection resource
         Class<?> proxy = new ByteBuddy()
                 .subclass(cls)
-                .method(ElementMatchers.isPublic()
-                        .and(ElementMatchers.not(
-                                ElementMatchers.isDeclaredBy(Object.class)
-                                        .or(ElementMatchers.isOverriddenFrom(Object.class))
-                        )))
+                .method(matcher)
                 .intercept(MethodDelegation.to(Interceptor.class))
                 .make()
-                .load(cls.getClassLoader(), ClassLoadingStrategy.Default.WRAPPER)
+                .load(ClassLoader.getSystemClassLoader(), ClassLoadingStrategy.Default.WRAPPER)
                 .getLoaded()
                 .asSubclass(cls);
 
@@ -83,6 +134,9 @@ public static <T> T createProxy(
             T instance = (T) proxy
                     .getConstructor(constructorArgTypes)
                     .newInstance(constructorArgs);
+            if (onInstanceCreated != null) {
+                onInstanceCreated.accept(instance);
+            }
             Interceptor.LISTENERS.put(instance, listeners);
             return instance;
         } catch (SecurityException | ReflectiveOperationException e) {
diff --git a/src/main/java/io/appium/java_client/proxy/Interceptor.java b/src/main/java/io/appium/java_client/proxy/Interceptor.java
index d343fc9c1..b27f50470 100644
--- a/src/main/java/io/appium/java_client/proxy/Interceptor.java
+++ b/src/main/java/io/appium/java_client/proxy/Interceptor.java
@@ -27,19 +27,13 @@
 import java.lang.reflect.Method;
 import java.util.Collection;
 import java.util.Map;
-import java.util.Set;
 import java.util.UUID;
 import java.util.WeakHashMap;
 import java.util.concurrent.Callable;
-import java.util.stream.Collectors;
-import java.util.stream.Stream;
 
 public class Interceptor {
     private static final Logger logger = LoggerFactory.getLogger(Interceptor.class);
     public static final Map<Object, Collection<MethodCallListener>> LISTENERS = new WeakHashMap<>();
-    private static final Set<String> OBJECT_METHOD_NAMES = Stream.of(Object.class.getMethods())
-            .map(Method::getName)
-            .collect(Collectors.toSet());
 
     /**
      * A magic method used to wrap public method calls in classes
@@ -51,6 +45,7 @@ public class Interceptor {
      * @param callable The reference to the non-patched callable to avoid call recursion.
      * @return Either the original method result or the patched one.
      */
+    @SuppressWarnings("unused")
     @RuntimeType
     public static Object intercept(
             @This Object self,
@@ -58,11 +53,17 @@ public static Object intercept(
             @AllArguments Object[] args,
             @SuperCall Callable<?> callable
     ) throws Throwable {
-        if (OBJECT_METHOD_NAMES.contains(method.getName())) {
+        boolean hasListeners = false;
+        try {
+            hasListeners = LISTENERS.containsKey(self);
+        } catch (RuntimeException e) {
+            // ignore
+        }
+        if (!hasListeners) {
             return callable.call();
         }
         Collection<MethodCallListener> listeners = LISTENERS.get(self);
-        if (listeners == null || listeners.isEmpty()) {
+        if (listeners.isEmpty()) {
             return callable.call();
         }
 
diff --git a/src/test/java/io/appium/java_client/pagefactory_tests/widget/tests/WidgetTest.java b/src/test/java/io/appium/java_client/pagefactory_tests/widget/tests/WidgetTest.java
index 6e1f4ab2b..2f8e2d60d 100644
--- a/src/test/java/io/appium/java_client/pagefactory_tests/widget/tests/WidgetTest.java
+++ b/src/test/java/io/appium/java_client/pagefactory_tests/widget/tests/WidgetTest.java
@@ -37,7 +37,6 @@ protected WidgetTest(AbstractApp app, WebDriver driver) {
     protected static void checkThatLocatorsAreCreatedCorrectly(DefaultStubWidget single,
                                                                List<DefaultStubWidget> multiple, By rootLocator,
                                                                By subLocator) {
-
         assertThat(single.toString(), containsString(rootLocator.toString()));
         assertThat(multiple.stream().map(DefaultStubWidget::toString).collect(toList()),
                 contains(containsString(rootLocator.toString()),
diff --git a/src/test/java/io/appium/java_client/pagefactory_tests/widget/tests/combined/CombinedAppTest.java b/src/test/java/io/appium/java_client/pagefactory_tests/widget/tests/combined/CombinedAppTest.java
index 2a453c2d9..c3ee905fb 100644
--- a/src/test/java/io/appium/java_client/pagefactory_tests/widget/tests/combined/CombinedAppTest.java
+++ b/src/test/java/io/appium/java_client/pagefactory_tests/widget/tests/combined/CombinedAppTest.java
@@ -6,7 +6,6 @@
 import io.appium.java_client.pagefactory_tests.widget.tests.AbstractStubWebDriver;
 import io.appium.java_client.pagefactory_tests.widget.tests.DefaultStubWidget;
 import io.appium.java_client.pagefactory_tests.widget.tests.android.DefaultAndroidWidget;
-import io.appium.java_client.pagefactory_tests.widget.tests.windows.DefaultWindowsWidget;
 import org.junit.jupiter.params.ParameterizedTest;
 import org.junit.jupiter.params.provider.Arguments;
 import org.junit.jupiter.params.provider.MethodSource;
@@ -35,7 +34,6 @@ public static Stream<Arguments> data() {
                 arguments(new CombinedApp(), new AbstractStubWebDriver.StubAndroidDriver(), DefaultAndroidWidget.class),
                 arguments(new CombinedApp(), new AbstractStubWebDriver.StubIOSXCUITDriver(),
                         DefaultIosXCUITWidget.class),
-                arguments(new CombinedApp(), new AbstractStubWebDriver.StubWindowsDriver(), DefaultWindowsWidget.class),
                 arguments(new CombinedApp(), new AbstractStubWebDriver.StubBrowserDriver(), DefaultFindByWidget.class),
                 arguments(new CombinedApp(), new AbstractStubWebDriver.StubAndroidBrowserOrWebViewDriver(),
                     DefaultFindByWidget.class),
@@ -72,14 +70,12 @@ public static class CombinedApp implements AbstractApp {
 
         @OverrideWidget(html = DefaultFindByWidget.class,
                 androidUIAutomator = DefaultAndroidWidget.class,
-                iOSXCUITAutomation = DefaultIosXCUITWidget.class,
-                windowsAutomation = DefaultWindowsWidget.class)
+                iOSXCUITAutomation = DefaultIosXCUITWidget.class)
         private DefaultStubWidget singleWidget;
 
         @OverrideWidget(html = DefaultFindByWidget.class,
                 androidUIAutomator = DefaultAndroidWidget.class,
-                iOSXCUITAutomation = DefaultIosXCUITWidget.class,
-                windowsAutomation = DefaultWindowsWidget.class)
+                iOSXCUITAutomation = DefaultIosXCUITWidget.class)
         private List<DefaultStubWidget> multipleWidget;
 
         @Override
diff --git a/src/test/java/io/appium/java_client/pagefactory_tests/widget/tests/combined/CombinedWidgetTest.java b/src/test/java/io/appium/java_client/pagefactory_tests/widget/tests/combined/CombinedWidgetTest.java
index d54e3618c..3c1c9145d 100644
--- a/src/test/java/io/appium/java_client/pagefactory_tests/widget/tests/combined/CombinedWidgetTest.java
+++ b/src/test/java/io/appium/java_client/pagefactory_tests/widget/tests/combined/CombinedWidgetTest.java
@@ -6,7 +6,6 @@
 import io.appium.java_client.pagefactory_tests.widget.tests.AbstractStubWebDriver;
 import io.appium.java_client.pagefactory_tests.widget.tests.DefaultStubWidget;
 import io.appium.java_client.pagefactory_tests.widget.tests.android.DefaultAndroidWidget;
-import io.appium.java_client.pagefactory_tests.widget.tests.windows.DefaultWindowsWidget;
 import org.junit.jupiter.params.ParameterizedTest;
 import org.junit.jupiter.params.provider.Arguments;
 import org.junit.jupiter.params.provider.MethodSource;
@@ -38,8 +37,6 @@ public static Stream<Arguments> data() {
                     new AbstractStubWebDriver.StubAndroidDriver(), DefaultAndroidWidget.class),
                 Arguments.of(new AppWithCombinedWidgets(),
                     new AbstractStubWebDriver.StubIOSXCUITDriver(), DefaultIosXCUITWidget.class),
-                Arguments.of(new AppWithCombinedWidgets(),
-                    new AbstractStubWebDriver.StubWindowsDriver(), DefaultWindowsWidget.class),
                 Arguments.of(new AppWithCombinedWidgets(),
                     new AbstractStubWebDriver.StubBrowserDriver(), DefaultFindByWidget.class),
                 Arguments.of(new AppWithCombinedWidgets(),
@@ -79,15 +76,13 @@ public static class CombinedWidget extends DefaultStubWidget {
 
         @OverrideWidget(html = DefaultFindByWidget.class,
                 androidUIAutomator = DefaultAndroidWidget.class,
-                iOSXCUITAutomation = DefaultIosXCUITWidget.class,
-                windowsAutomation = DefaultWindowsWidget.class
+                iOSXCUITAutomation = DefaultIosXCUITWidget.class
         )
         private DefaultStubWidget singleWidget;
 
         @OverrideWidget(html = DefaultFindByWidget.class,
                 androidUIAutomator = DefaultAndroidWidget.class,
-                iOSXCUITAutomation = DefaultIosXCUITWidget.class,
-                windowsAutomation = DefaultWindowsWidget.class
+                iOSXCUITAutomation = DefaultIosXCUITWidget.class
         )
         private List<DefaultStubWidget> multipleWidget;
 
diff --git a/src/test/java/io/appium/java_client/pagefactory_tests/widget/tests/windows/AnnotatedWindowsWidget.java b/src/test/java/io/appium/java_client/pagefactory_tests/widget/tests/windows/AnnotatedWindowsWidget.java
deleted file mode 100644
index 733d0db95..000000000
--- a/src/test/java/io/appium/java_client/pagefactory_tests/widget/tests/windows/AnnotatedWindowsWidget.java
+++ /dev/null
@@ -1,15 +0,0 @@
-package io.appium.java_client.pagefactory_tests.widget.tests.windows;
-
-import io.appium.java_client.pagefactory.WindowsFindBy;
-import io.appium.java_client.pagefactory.iOSXCUITFindBy;
-import org.openqa.selenium.WebElement;
-
-@WindowsFindBy(windowsAutomation = "SOME_ROOT_LOCATOR")
-@iOSXCUITFindBy(iOSNsPredicate = "XCUIT_SOME_ROOT_LOCATOR")
-public class AnnotatedWindowsWidget extends DefaultWindowsWidget {
-    public static String WINDOWS_ROOT_WIDGET_LOCATOR = "SOME_ROOT_LOCATOR";
-
-    protected AnnotatedWindowsWidget(WebElement element) {
-        super(element);
-    }
-}
diff --git a/src/test/java/io/appium/java_client/pagefactory_tests/widget/tests/windows/DefaultWindowsWidget.java b/src/test/java/io/appium/java_client/pagefactory_tests/widget/tests/windows/DefaultWindowsWidget.java
deleted file mode 100644
index ab7b81a41..000000000
--- a/src/test/java/io/appium/java_client/pagefactory_tests/widget/tests/windows/DefaultWindowsWidget.java
+++ /dev/null
@@ -1,35 +0,0 @@
-package io.appium.java_client.pagefactory_tests.widget.tests.windows;
-
-import io.appium.java_client.pagefactory.WindowsFindBy;
-import io.appium.java_client.pagefactory.iOSXCUITFindBy;
-import io.appium.java_client.pagefactory_tests.widget.tests.DefaultStubWidget;
-import org.openqa.selenium.WebElement;
-
-import java.util.List;
-
-public class DefaultWindowsWidget extends DefaultStubWidget {
-
-    public static String WINDOWS_SUB_WIDGET_LOCATOR = "SOME_SUB_LOCATOR";
-
-    @WindowsFindBy(windowsAutomation =  "SOME_SUB_LOCATOR")
-    @iOSXCUITFindBy(iOSNsPredicate = "XCUIT_SOME_SUB_LOCATOR")
-    private DefaultWindowsWidget singleWidget;
-
-    @WindowsFindBy(windowsAutomation =  "SOME_SUB_LOCATOR")
-    @iOSXCUITFindBy(iOSNsPredicate = "XCUIT_SOME_SUB_LOCATOR")
-    private List<DefaultWindowsWidget> multipleWidgets;
-
-    protected DefaultWindowsWidget(WebElement element) {
-        super(element);
-    }
-
-    @Override
-    public DefaultWindowsWidget getSubWidget() {
-        return singleWidget;
-    }
-
-    @Override
-    public List<DefaultWindowsWidget> getSubWidgets() {
-        return multipleWidgets;
-    }
-}
diff --git a/src/test/java/io/appium/java_client/pagefactory_tests/widget/tests/windows/ExtendedWindowsWidget.java b/src/test/java/io/appium/java_client/pagefactory_tests/widget/tests/windows/ExtendedWindowsWidget.java
deleted file mode 100644
index 14cc95f65..000000000
--- a/src/test/java/io/appium/java_client/pagefactory_tests/widget/tests/windows/ExtendedWindowsWidget.java
+++ /dev/null
@@ -1,9 +0,0 @@
-package io.appium.java_client.pagefactory_tests.widget.tests.windows;
-
-import org.openqa.selenium.WebElement;
-
-public class ExtendedWindowsWidget extends AnnotatedWindowsWidget {
-    protected ExtendedWindowsWidget(WebElement element) {
-        super(element);
-    }
-}
diff --git a/src/test/java/io/appium/java_client/pagefactory_tests/widget/tests/windows/WindowsApp.java b/src/test/java/io/appium/java_client/pagefactory_tests/widget/tests/windows/WindowsApp.java
deleted file mode 100644
index 07eb5784d..000000000
--- a/src/test/java/io/appium/java_client/pagefactory_tests/widget/tests/windows/WindowsApp.java
+++ /dev/null
@@ -1,125 +0,0 @@
-package io.appium.java_client.pagefactory_tests.widget.tests.windows;
-
-import io.appium.java_client.AppiumBy;
-import io.appium.java_client.pagefactory.WindowsFindBy;
-import io.appium.java_client.pagefactory.iOSXCUITFindBy;
-import io.appium.java_client.pagefactory_tests.widget.tests.ExtendedApp;
-
-import java.util.List;
-
-public class WindowsApp implements ExtendedApp {
-
-    public static String WINDOWS_DEFAULT_WIDGET_LOCATOR = "SOME_WINDOWS_DEFAULT_LOCATOR";
-
-    public static String WINDOWS_EXTERNALLY_DEFINED_WIDGET_LOCATOR = "WINDOWS_EXTERNALLY_DEFINED_WIDGET_LOCATOR";
-
-    @WindowsFindBy(windowsAutomation = "SOME_WINDOWS_DEFAULT_LOCATOR")
-    @iOSXCUITFindBy(iOSNsPredicate = "SOME_XCUIT_DEFAULT_LOCATOR")
-    private DefaultWindowsWidget singleIosWidget;
-
-    @WindowsFindBy(windowsAutomation = "SOME_WINDOWS_DEFAULT_LOCATOR")
-    @iOSXCUITFindBy(iOSNsPredicate = "SOME_XCUIT_DEFAULT_LOCATOR")
-    private List<DefaultWindowsWidget> multipleIosWidgets;
-
-    /**
-     * This class is annotated by {@link WindowsFindBy} and
-     * {@link io.appium.java_client.pagefactory.iOSXCUITFindBy}.
-     * This field was added to check that locator is created correctly according to current platform.
-     * It is expected that the root element and sub-elements are found using
-     * {@link AppiumBy#windowsAutomation(String)}
-     */
-    private AnnotatedWindowsWidget singleAnnotatedIosWidget;
-
-    /**
-     * This class is annotated by {@link WindowsFindBy} and
-     * {@link io.appium.java_client.pagefactory.iOSXCUITFindBy}.
-     * This field was added to check that locator is created correctly according to current platform.
-     * It is expected that the root element and sub-elements are found using
-     * {@link AppiumBy#windowsAutomation(String)}.
-     */
-    private List<AnnotatedWindowsWidget> multipleIosIosWidgets;
-
-    /**
-     * This class is not annotated by {@link WindowsFindBy} and
-     * {@link io.appium.java_client.pagefactory.iOSXCUITFindBy}.
-     * But the superclass is annotated by these annotations. This field was added to check that locator is
-     * created correctly according to current platform.
-     * It is expected that the root element and sub-elements are found using
-     * {@link AppiumBy#windowsAutomation(String)}.
-     */
-    private ExtendedWindowsWidget singleExtendedIosWidget;
-
-    /**
-     * This class is not annotated by {@link WindowsFindBy} and
-     * {@link io.appium.java_client.pagefactory.iOSXCUITFindBy}.
-     * But the superclass is annotated by these annotations. This field was added to check that locator is
-     * created correctly according to current platform.
-     * It is expected that the root element and sub-elements are found using
-     * {@link AppiumBy#windowsAutomation(String)}.
-     */
-    private List<ExtendedWindowsWidget> multipleExtendedIosWidgets;
-
-    /**
-     * This class is not annotated by {@link WindowsFindBy} and
-     * {@link io.appium.java_client.pagefactory.iOSXCUITFindBy}.
-     * But the superclass is annotated by these annotations. This field was added to check that locator is
-     * created correctly according to current platform.
-     * It is expected that the root element and sub-elements are found using
-     * {@link AppiumBy#windowsAutomation(String)}.
-     */
-    @WindowsFindBy(windowsAutomation = "WINDOWS_EXTERNALLY_DEFINED_WIDGET_LOCATOR")
-    @iOSXCUITFindBy(iOSNsPredicate = "SOME_XCUIT_EXTERNALLY_DEFINED_LOCATOR")
-    private ExtendedWindowsWidget singleOverriddenIosWidget;
-
-    /**
-     * This class is not annotated by {@link WindowsFindBy} and
-     * {@link io.appium.java_client.pagefactory.iOSXCUITFindBy}.
-     * But the superclass is annotated by these annotations. This field was added to check that locator is
-     * created correctly according to current platform.
-     * It is expected that the root element and sub-elements are found using
-     * {@link AppiumBy#windowsAutomation(String)}.
-     */
-    @WindowsFindBy(windowsAutomation = "WINDOWS_EXTERNALLY_DEFINED_WIDGET_LOCATOR")
-    @iOSXCUITFindBy(iOSNsPredicate = "SOME_XCUIT_EXTERNALLY_DEFINED_LOCATOR")
-    private List<ExtendedWindowsWidget> multipleOverriddenIosWidgets;
-
-    @Override
-    public DefaultWindowsWidget getWidget() {
-        return singleIosWidget;
-    }
-
-    @Override
-    public List<DefaultWindowsWidget> getWidgets() {
-        return multipleIosWidgets;
-    }
-
-    @Override
-    public DefaultWindowsWidget getAnnotatedWidget() {
-        return singleAnnotatedIosWidget;
-    }
-
-    @Override
-    public List<AnnotatedWindowsWidget> getAnnotatedWidgets() {
-        return multipleIosIosWidgets;
-    }
-
-    @Override
-    public DefaultWindowsWidget getExtendedWidget() {
-        return singleExtendedIosWidget;
-    }
-
-    @Override
-    public List<ExtendedWindowsWidget> getExtendedWidgets() {
-        return multipleExtendedIosWidgets;
-    }
-
-    @Override
-    public DefaultWindowsWidget getExtendedWidgetWithOverriddenLocators() {
-        return singleOverriddenIosWidget;
-    }
-
-    @Override
-    public List<ExtendedWindowsWidget> getExtendedWidgetsWithOverriddenLocators() {
-        return multipleOverriddenIosWidgets;
-    }
-}
diff --git a/src/test/java/io/appium/java_client/pagefactory_tests/widget/tests/windows/WindowsWidgetTest.java b/src/test/java/io/appium/java_client/pagefactory_tests/widget/tests/windows/WindowsWidgetTest.java
deleted file mode 100644
index 023b24819..000000000
--- a/src/test/java/io/appium/java_client/pagefactory_tests/widget/tests/windows/WindowsWidgetTest.java
+++ /dev/null
@@ -1,51 +0,0 @@
-package io.appium.java_client.pagefactory_tests.widget.tests.windows;
-
-import io.appium.java_client.pagefactory_tests.widget.tests.AbstractStubWebDriver;
-import io.appium.java_client.pagefactory_tests.widget.tests.ExtendedApp;
-import io.appium.java_client.pagefactory_tests.widget.tests.WidgetTest;
-import org.junit.jupiter.api.Test;
-
-import static io.appium.java_client.MobileBy.windowsAutomation;
-import static io.appium.java_client.pagefactory_tests.widget.tests.windows.AnnotatedWindowsWidget.WINDOWS_ROOT_WIDGET_LOCATOR;
-import static io.appium.java_client.pagefactory_tests.widget.tests.windows.DefaultWindowsWidget.WINDOWS_SUB_WIDGET_LOCATOR;
-import static io.appium.java_client.pagefactory_tests.widget.tests.windows.WindowsApp.WINDOWS_DEFAULT_WIDGET_LOCATOR;
-import static io.appium.java_client.pagefactory_tests.widget.tests.windows.WindowsApp.WINDOWS_EXTERNALLY_DEFINED_WIDGET_LOCATOR;
-
-public class WindowsWidgetTest extends WidgetTest {
-
-    public WindowsWidgetTest() {
-        super(new WindowsApp(), new AbstractStubWebDriver.StubWindowsDriver());
-    }
-
-    @Test
-    @Override
-    public void checkThatWidgetsAreCreatedCorrectly() {
-        checkThatLocatorsAreCreatedCorrectly(app.getWidget(), app.getWidgets(),
-                windowsAutomation(WINDOWS_DEFAULT_WIDGET_LOCATOR), windowsAutomation(WINDOWS_SUB_WIDGET_LOCATOR));
-    }
-
-    @Test
-    @Override
-    public void checkCaseWhenWidgetClassHasDeclaredLocatorAnnotation() {
-        checkThatLocatorsAreCreatedCorrectly(((ExtendedApp) app).getAnnotatedWidget(),
-                ((ExtendedApp) app).getAnnotatedWidgets(),
-                windowsAutomation(WINDOWS_ROOT_WIDGET_LOCATOR), windowsAutomation(WINDOWS_SUB_WIDGET_LOCATOR));
-    }
-
-    @Test
-    @Override
-    public void checkCaseWhenWidgetClassHasNoDeclaredAnnotationButItHasSuperclass() {
-        checkThatLocatorsAreCreatedCorrectly(((ExtendedApp) app).getExtendedWidget(),
-                ((ExtendedApp) app).getExtendedWidgets(),
-                windowsAutomation(WINDOWS_ROOT_WIDGET_LOCATOR), windowsAutomation(WINDOWS_SUB_WIDGET_LOCATOR));
-    }
-
-    @Test
-    @Override
-    public void checkCaseWhenBothWidgetFieldAndClassHaveDeclaredAnnotations() {
-        checkThatLocatorsAreCreatedCorrectly(((ExtendedApp) app).getExtendedWidgetWithOverriddenLocators(),
-                ((ExtendedApp) app).getExtendedWidgetsWithOverriddenLocators(),
-                windowsAutomation(WINDOWS_EXTERNALLY_DEFINED_WIDGET_LOCATOR),
-                windowsAutomation(WINDOWS_SUB_WIDGET_LOCATOR));
-    }
-}
