You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Kotlin/Android:如何自动为类所有方法添加通用代码包裹?

自动包裹对象方法的实现方案

针对调用Foo类任意方法时自动执行startAccess()→目标方法→stopAccess()的需求,以下是几种无需手动逐个包裹的实现方案:

方案1:动态代理(Java环境)

通过运行时生成代理类,拦截所有方法调用并统一处理包裹逻辑,无需修改原有Foo类代码。

JDK动态代理(需Foo实现接口)

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

public class FooInvocationHandler implements InvocationHandler {
    private final Foo target;

    public FooInvocationHandler(Foo target) {
        this.target = target;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        target.startAccess();
        try {
            return method.invoke(target, args);
        } finally {
            target.stopAccess();
        }
    }

    public static Foo createProxy(Foo target) {
        return (Foo) Proxy.newProxyInstance(
                target.getClass().getClassLoader(),
                target.getClass().getInterfaces(),
                new FooInvocationHandler(target)
        );
    }
}

使用方式:

Foo originalFoo = new FooImpl();
Foo proxiedFoo = FooInvocationHandler.createProxy(originalFoo);

// 调用任意方法自动触发包裹逻辑
proxiedFoo.doA();
proxiedFoo.getA();

CGLIB动态代理(无需Foo实现接口)

若Foo未实现接口,可使用CGLIB生成子类代理:

import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;

public class FooCglibInterceptor implements MethodInterceptor {
    private final Foo target;

    public FooCglibInterceptor(Foo target) {
        this.target = target;
    }

    @Override
    public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
        target.startAccess();
        try {
            return proxy.invokeSuper(obj, args);
        } finally {
            target.stopAccess();
        }
    }

    public static Foo createProxy(Foo target) {
        Enhancer enhancer = new Enhancer();
        enhancer.setSuperclass(Foo.class);
        enhancer.setCallback(new FooCglibInterceptor(target));
        return (Foo) enhancer.create();
    }
}

方案2:装饰器模式(多语言通用)

手动实现一个装饰类,持有原Foo实例,统一封装所有方法的包裹逻辑,编译期即可确定行为。

Java示例:

public class FooDecorator implements Foo {
    private final Foo delegate;

    public FooDecorator(Foo delegate) {
        this.delegate = delegate;
    }

    @Override
    public void doA() {
        wrapCall(delegate::doA);
    }

    @Override
    public String getA() {
        return wrapCall(delegate::getA);
    }

    private <T> T wrapCall(Supplier<T> supplier) {
        delegate.startAccess();
        try {
            return supplier.get();
        } finally {
            delegate.stopAccess();
        }
    }

    private void wrapCall(Runnable runnable) {
        delegate.startAccess();
        try {
            runnable.run();
        } finally {
            delegate.stopAccess();
        }
    }
}

使用方式:

Foo originalFoo = new FooImpl();
Foo decoratedFoo = new FooDecorator(originalFoo);
decoratedFoo.doA();
decoratedFoo.getA();

方案3:Kotlin扩展函数+委托

利用Kotlin的委托特性,实现简洁的自动包裹:

class FooDelegator(private val original: Foo) : Foo by original {
    override fun doA() {
        wrapCall { original.doA() }
    }

    override fun getA(): String {
        return wrapCall { original.getA() }
    }

    private inline fun <T> wrapCall(block: () -> T): T {
        original.startAccess()
        return try {
            block()
        } finally {
            original.stopAccess()
        }
    }
}

// 扩展函数快速创建包裹实例
fun Foo.wrap(): Foo = FooDelegator(this)

使用方式:

val originalFoo = FooImpl()
val wrappedFoo = originalFoo.wrap()
wrappedFoo.doA()
wrappedFoo.getA()

方案4:切面编程(AspectJ/Spring AOP)

通过切面拦截所有Foo类的方法调用,统一注入包裹逻辑,适合Spring或支持AspectJ织入的环境。

AspectJ切面示例:

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;

@Aspect
public class FooAccessAspect {
    @Around("execution(* com.example.Foo.*(..))")
    public Object wrapFooMethods(ProceedingJoinPoint joinPoint) throws Throwable {
        Foo target = (Foo) joinPoint.getTarget();
        target.startAccess();
        try {
            return joinPoint.proceed();
        } finally {
            target.stopAccess();
        }
    }
}

配置织入后,所有Foo实例的方法调用都会自动触发包裹逻辑。

内容的提问来源于stack exchange,提问作者Marco Zielbauer

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.10 04:31:12