Java 如何从Spring服务访问私有方法?
我有一个带有用于数据库操作的公共方法的服务,标记为org.springframework.transaction.annotation.Transactional annotation 我想通过Java反射访问不带事务性注释的私有方法:service.getClass.getDeclaredMethod'privateMethod',args 当我调用它时,我获取java.lang.NoSuchMethodException。当我删除所有带@Transactional注释的方法时,它就起作用了。这种行为有什么原因吗?我该如何解决Java 如何从Spring服务访问私有方法?,java,spring,reflection,Java,Spring,Reflection,我有一个带有用于数据库操作的公共方法的服务,标记为org.springframework.transaction.annotation.Transactional annotation 我想通过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);
}
}
您可以导入:
测试结果如下所示:
@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的一部分,这样的测试会使您的测试更加脆弱。是的,这是有原因的:事务处理是基于代理的。您试图在事务代理上调用私有方法 代理只实现服务的公共方法,因为您不应该使用反射和调用私有方法。他们是私人的是有原因的
如果您需要从服务外部调用服务的方法,请将其公开。您真的需要在测试内部使用spring吗?你可以用Mockito模拟所有必要的调用。这将允许您直接调用publicMethodMarkedWithTransactional是的,原因是:事务处理基于代理。您试图在事务代理上调用私有方法。代理只实现服务的公共方法,因为您不应该使用反射和调用私有方法。他们是私人的是有原因的。如果您需要从服务外部调用服务的方法,请将其公开。理想情况下,您应该使用Mockito的@InjectMocks注释MyService,然后调用服务。publicMethodMarkedWithTransactional传递参数。这将使您能够在内部测试privateMethod。@Michael是的,没关系。thanx为了解释,我只需要这个方法进行测试purposes@AlexanderMakeev依赖于实现细节的测试几乎总是一个糟糕的测试
@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);
}