Fading Coder

One Final Commit for the Last Sprint

Home > Tech > Content

Implementing Before and After Notifications with CGLIB Dynamic Proxy

Tech May 15 12

Dynamic Proxy Implementtaion


/**
 * @author Li Yajie
 * @date 2024/4/7 10:57
 * @description ProxyUtil
 */
public class ProxyUtil {
    /**
     * JDK Dynamic Proxy
     *
     * @param target   Target object to be proxied
     * @param <T>
     * @return
     */
    @SuppressWarnings("unchecked")
    public static <T> T createJDKProxy(@NotNull T target) {
        return (T) Proxy.newProxyInstance(target.getClass().getClassLoader(),
                target.getClass().getInterfaces(),
                (proxy, method, args) -> method.invoke(target, args)
        );
    }

   /**
     *
     * @param target   Target object for proxy
     * @param before   Before notification action
     * @param after    After notification action
     * @return         Proxied instance
     * @param <T>
     */
    @SuppressWarnings("unchecked")
    public static <T> T createCglibProxy(@NotNull T target, Runnable before, Runnable after) {
        Enhancer enhancer = new Enhancer();
        enhancer.setSuperclass(target.getClass());
        enhancer.setCallback((MethodInterceptor) (obj, method, args, proxy) -> {
            before.run();
            Object result = proxy.invokeSuper(obj, args);
            after.run();
            return result;
        });
        return (T) enhancer.create();
    }

}

Test method

@Test
    public void test02(){
        UserServiceImpl service = new UserServiceImpl();
        UserServiceImpl proxy = ProxyUtil.createCglibProxy(service,
                ()-> System.out.println("Before notification"),
                () -> System.out.println("After notification")
        );
        proxy.insert(new User());
    }

Output

The function interface can also be changed to Function<T,R> to achieve pre-interception.

Code example:

@SuppressWarnings("unchecked")
    public static <T> T createCglibProxy(@NotNull T target, Function<Object[],Boolean> before, Runnable after) {
        Enhancer enhancer = new Enhancer();
        enhancer.setSuperclass(target.getClass());
        enhancer.setCallback((MethodInterceptor) (obj, method, args, proxy) -> {
            if (!before.apply(args)) {
                return null;
            }
            Object result = proxy.invokeSuper(obj, args);
            after.run();
            return result;
        });
        return (T) enhancer.create();
    }

Test code

@Test
    public void test02() {
        UserServiceImpl service = new UserServiceImpl();
        UserServiceImpl proxy = ProxyUtil.createCglibProxy(service,
                (args) -> {
                    System.out.println("Pre-interception");
                    User user = (User) args[0];
                    return user != null;
                },
                () -> System.out.println("After notification")
        );
        proxy.insert(null);
        System.out.println("_________");
        proxy.insert(new User());
    }

Test output

Interception behavior achieved through a functioanl itnerface returning a value

Tags: Java

Related Articles

Understanding Strong and Weak References in Java

Strong References Strong reference are the most prevalent type of object referencing in Java. When an object has a strong reference pointing to it, the garbage collector will not reclaim its memory. F...

Comprehensive Guide to SSTI Explained with Payload Bypass Techniques

Introduction Server-Side Template Injection (SSTI) is a vulnerability in web applications where user input is improper handled within the template engine and executed on the server. This exploit can r...

Implement Image Upload Functionality for Django Integrated TinyMCE Editor

Django’s Admin panel is highly user-friendly, and pairing it with TinyMCE, an effective rich text editor, simplifies content management significantly. Combining the two is particular useful for bloggi...

Leave a Comment

Anonymous

◎Feel free to join the discussion and share your thoughts.