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
相关产品推荐
相关产品推荐

