有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java如何从Spring服务访问私有方法?

我有一个带有公共方法的服务,用于数据库操作,标记为org.springframework.transaction.annotation.Transactional注释

我想通过Java反射来访问私有方法(不带事务性注释):service.getClass().getDeclaredMethod('privateMethod', args)

当我调用它时,我获取java.lang.NoSuchMethodException。当我删除所有带@Transactional注释的方法时,它就起作用了。这种行为有什么原因吗?我该如何解决

public class MyService {

    @Transactional(readOnly = true)
    public Integer publicMethodMarkedWithTransactional(int a, int b) {
        //couple of database requests
        return privateMethod(b, a);
    }

    private Integer privateMethod(int a, int b) {
        return a + b;
    }

}

public class MyServiceTest {

    @Autowired
    private MyService service;

    @Test
    public void test() throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
        Method privateMethod = service.getClass().getDeclaredMethod("privateMethod", int.class, int.class);
        privateMethod.setAccessible(true);
        int res = (int) privateMethod.invoke(service, 5, 10);
        assertEquals(5 + 10, res);
    }

}

共 (2) 个答案

  1. # 1 楼答案

    您可以导入^{}

    import org.springframework.data.util.ReflectionUtils;
    

    测试结果如下所示:

    @Test
    public void test() throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
       Method privateMethod = ReflectionUtils.findRequiredMethod(MyService.class, "privateMethod", int.class, int.class);
        int res = (int) privateMethod.invoke(service, 5, 10);
        assertEquals(5 + 10, res);
    }
    

    但是,我建议不要以这种方式编写测试—您应该找到一种测试API的方法。私有方法不是API的一部分,这样的测试会使您的测试更加脆弱

  2. # 2 楼答案

    是的,这是有原因的:事务处理是基于代理的。您试图在事务代理上调用私有方法

    代理只实现服务的公共方法,因为您不应该使用反射和调用私有方法。他们是私人的是有原因的

    如果需要从此服务外部调用服务的方法,请将其公开