我想知道是否有人有一种模式可以帮助我实现以下目标:
我们有一个名为Employee的JPA实体,并且有一个setLineManager方法。我们还有一个单独的updateLineStructureService,它是一个Spring管理的服务bean。我们想要尝试确保只能从updateLineStructureService调用此setLineManager方法,而不能直接从任何其他类调用。
有没有办法允许服务访问此方法而不将其暴露给任何其他类?我知道我可以给方法包级别访问并将服务放在与Employee相同的包中,但这不适合我们的包结构,所以我宁愿不这样做。我也知道我可以将这个方法设为私有,只需通过这一方面的反射来访问它,但我根本不喜欢这个解决方案。
有什么想法吗?
答案 0 :(得分:1)
您可以检查堆栈跟踪(使用Throwable#getStackTrace())并查看它是否在指定位置包含允许的方法。
答案 1 :(得分:1)
在以下代码段中,System.PrivateEmployee
在System类外部不可见。因此,有效privateMethod
是私有的,只能在System
类中调用。由于System.PrivateEmployee
扩展System.PublicEmployee
,因此可以在System
类之外使用System.PublicEmployee
public class System
{
public static interface PublicEmployee { void publicMethod ( ) ; }
private static interface PrivateEmployee extends PublicEmployee { void privateMethod ( ) ; }
}
答案 2 :(得分:1)
使用仅适用于其他服务类的内部类:
public class Employee
{
static {
LineStructureService.registerEmployeeHelper(new EmployeeHelper() {
@Override
public void setLineManager(Employee emp, Object foo) {
emp.setLineManager(foo);
}
});
}
public static void init() {}
private void setLineManager(Object foo) { }
}
public class LineStructureService
{
private static volatile EmployeeHelper _helper;
static {
// ensure that Employee class is loaded and helper registered
Employee.init();
}
public static synchronized void registerEmployeeHelper(EmployeeHelper helper) {
_helper = helper;
}
public void doSomething(Employee emp)
{
// now this class can call setLineManager on Employee
_helper.setLineManager(emp, blah);
}
public interface EmployeeHelper {
public void setLineManager(Employee emp, Object foo);
}
}
答案 3 :(得分:0)
类可以访问其他类的私有方法的唯一方法是使用内部类。如果这不是一个选项,则无法做到这一点。
答案 4 :(得分:0)
一种方法是制作两种形式的员工。
“BasicEmployee”具有除setLineManager()之外的所有方法。 “ExtendedEmployee”扩展了BasicEmployee并添加了public void setLineManager()
。 (我假设这些是类,但它们也可以是接口)在幕后,一切都是FullEmployee(为了清楚起见,你可以使BasicEmployee抽象)。但是,在代码中,除了UpdateLineStructureService之外的所有类中,都将它声明为BasicEmployee。仅在UpdateLineStructureService中它被声明为FullEmployee。因此,只有UpdateLineStructureService可以轻松访问setLineManager()
现在,一个流氓编码器总是可以将他们的BasicEmployee转换为ExtendedEmployee来访问setLineManager(),所以这不是完全安全的。但这是限制访问的合理模式。
答案 5 :(得分:0)
您可以使用AOP(例如AspectJ或CDI)拦截对setLineManager()的调用;如果调用者是updateLineStructureService()调用该方法;如果不做什么,或提出异常或其他什么。