是否有可能创建一个可以为任何具体类添加功能的动态代理?

时间:2013-01-17 18:45:58

标签: java netty shiro javassist dynamic-proxy

我将在下面简要介绍一下我的目标,以防万一有更好的,替代的方式来实现我想要的。 This question与我的需求非常相似,但并不完全符合我的需要。我的问题......

我有一个界面:

public interface Command<T> extends Serializable {}

..加上一个实现:

public class EchoCommand implements Command<String> {
    private final String stringToEcho;

    public EchoCommand(String stringToEcho) {
        this.stringToEcho = stringToEcho;
    }

    public String getStringToEcho() {
        return stringToEcho;
    }
}

如果我创建另一个界面:

public interface AuthorizedCommand {
    String getAuthorizedUser();
}

..有没有办法在运行时在EchoCommand上实现AuthorizedCommand接口而不知道子类类型?

public <C extends Command<T>,T> C authorize(C command) {
    // can this be done so the returned Command is also an
    // instance of AuthorizedCommand?
    return (C) theDecoratedCommand;
}

为什么......我使用Netty构建了一个基于命令的非常简单的概念验证客户端/服务器框架。在客户端和服务器之间共享的命令与命令处理程序之间存在一对一的关系。处理程序仅在服务器上,并且它们实现起来非常简单。这是界面。

public interface CommandHandler<C extends Command<T>,T> {
    public T execute(C command);
}

在客户端,事情也非常简单。在客户端保持简单是我决定尝试基于命令的API的主要原因。客户端调度命令并返回Future。很明显,呼叫是异步的,而且客户端没有处理诸如SwingWorker中的呼叫之类的事情。为什么要构建针对异步调用(网络上的任何东西)的同步API,只是为了将异步调用包装在异步辅助方法中?我正在使用番石榴。

public <T> ListenableFuture<T> dispatch(Command<T> command)

现在我想添加身份验证和授权。我不想强迫我的命令处理程序知道授权,但是,在某些情况下,我希望它们能够查询某些事情关于执行命令的用户。主要是我希望能够在某些数据上使用lastModifiedBy属性。

我正在考虑使用Apache Shiro,所以明显的答案似乎是使用他们的SubjectAwareExecutor将授权信息传递到ThreadLocal,但是我的处理人员需要知道Shiro或者我需要通过找到一些方法将命令映射到Shiro中的身份验证/授权信息来抽象它。

由于每个Command已经携带状态并通过我的整个管道传递,如果我可以装饰已经授权的命令以便它们实现AuthorizedCommand接口,那么事情就会简单得多。然后我的命令处理程序可以使用已经装饰的信息,但它完全是可选的。

if(command instanceof AuthorizedCommand) {
    // We can interrogate the command for the extra meta data
    // we're interested in.
}

这样我也可以开发与身份验证/授权相关的所有内容,而不依赖于我的应用程序的核心业务逻辑。它(我认为)还允许我将会话信息与Netty ChannelChannelGroup相关联,我认为这对于NIO框架更有意义,对吧?我认为Netty 4甚至可以允许在Channel上设置类型属性,这听起来非常适合跟踪会话信息等事情(虽然我还没看过)。

我想要完成的主要任务是能够非常快速地构建应用程序的原型。我想从一个客户端调度程序开始,它是一个简单的命令类型映射来命令处理程序,完全忽略了网络和安全方面的事情。一旦我对我的原型感到满意,我将交换我的基于Netty的调度员(使用Guice),然后,在开发周期的最后阶段,我将添加Shiro。

我非常感谢任何评论或建设性的批评。如果我所解释的内容是有意义的,并且在普通的旧Java中是不可能的,那么我可以考虑用另一种JVM语言构建该特定功能。也许斯卡拉?

1 个答案:

答案 0 :(得分:0)

您可以尝试这样做:

Java: Extending Class At Runtime

在运行时,您的代码将扩展要实例化的Command类,并实现AuthorizedCommand接口。这将使该类成为AuthorizedCommand的一个实例,同时保留原始的Command类结构。

要注意的一件事是,您无法使用“final”关键字扩展任何类。