如何在Spring中拦截静态方法?

如何在Spring中拦截静态方法?,第1张

如何在Spring中拦截静态方法

使用Spring AOP不能做到这一点,因为它是基于代理的。你必须使用AspectJ

在看到我的一些同事开发的MockME之后,我开始思考如何以通用的方式来制作它。例如,我们将如何模拟以下课程?看一个简单的例子

public class StupidSingleton {    public static String doStatic(int i) {        throw new UnsupportedOperationException("method not implemented yet...");    }    public static void sayHello() {        System.out.println("Hello");    }    public static native void nativeMethod();}

我们想写这样的东西:

public void testMocking() {  mock(StupidSingleton.class);  expect(StupidSingleton.doStatic(17)).andReturn("17");  StupidSingleton.sayHello();  StupidSingleton.nativeMethod();  replay(StupidSingleton.class);  assertEquals("17", StupidSingleton.doStatic(17));  StupidSingleton.sayHello();  StupidSingleton.nativeMethod();  verify(StupidSingleton.class);}

在玩过AspectJ之后,我发现这实际上是可行的!需要两件事:

  • 使我们能够捕获对静态方法的调用的方面!
  • 模拟,重播,验证类的实现

事实证明,这真的很容易!以下方面捕获对所有静态方法的所有调用。可能会有些攻击性,但是可以!如果需要,可以使用更专业的切入点实现自己的方面。

@Aspectpublic class StaticMockAll extends StaticMockAspect {    @Pointcut("call(static * *(..))")    public void anyStaticOperation() {}    @Around("anyStaticOperation()")    public Object aroundStaticMethods(ProceedingJoinPoint jp) throws Throwable {        return super.aroundStaticMethods(jp);    }}

模拟,重播,验证方法非常简单:

public class StaticMock {    static Map mocks = new HashMap();    public static synchronized void mock(Class type) {        MockInvocationHandler h = new MockInvocationHandler((MocksControl) EasyMock.createControl());        mocks.put(type, h);    }    public static synchronized void replay(Class type) {        mocks.get(type).getControl().replay();    }    public static synchronized void verify(Class type) {        mocks.remove(type).getControl().verify();    }}

最后,进行实际工作的方面的基类也非常简单:

public class StaticMockAspect {    public Object aroundStaticMethods(ProceedingJoinPoint jp) throws Throwable {        Class type = jp.getSignature().getDeclaringType();        InvocationHandler h = getInvocationHandler(type);        if (h == null) { return jp.proceed();        }        MethodSignature methodSignature = ((MethodSignature)jp.getSignature());        return h.invoke(type, methodSignature.getMethod(), jp.getArgs());    }    private MockInvocationHandler getInvocationHandler(Class type) {        synchronized (StaticMock.class) { return StaticMock.mocks.get(type);        }    }}

h3。笔记

需要注意和考虑的事情:
- 可以模拟静态方法和本机方法!通过使用“调用”切入点,我们可以更改所有试图调用本机方法而不是本机方法本身的代码。
- 要完成这项工作,必须使用AspectJ。我一直在使用Eclipse AJDT
- 应该可以用“普通”字节代码 *** 作替换Aspect并“重新”加载类。




欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/zaji/4916640.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-11-12
下一篇 2022-11-13

发表评论

登录后才能评论

评论列表(0条)

保存