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

时间:2019-03-18 15:06:54

标签: java spring reflection

我有一个带有公开方法的服务,该方法带有标记为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 个答案:

答案 0 :(得分:3)

您可以导入ReflectionUtils

import { timeout } from 'rxjs/operators';
...


this.contratService.update(lineSelected.id)
  .pipe(
     timeout(30000)
   )
  .subscribe(response => {
     if (response.status === 201) {
         ....
     }
  }, error => {
   console.log('Error in contrat update');
});

测试将如下所示:

import org.springframework.data.util.ReflectionUtils;

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

答案 1 :(得分:2)

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

代理仅实现服务的公共方法,因为您不应使用反射并调用私有方法。由于某种原因,它们是私人的。

如果您需要从该服务之外调用服务的方法,请将其公开。