【问题标题】:Execute code before and after method?在方法之前和之后执行代码?
【发布时间】:2010-09-27 15:27:43
【问题描述】:

在服务层我有一个看起来像这样的类:

class MyService {
    public doSomething() {
        TelnetSession session = new TelnetSession();
        session.open("username", "password");
        session.execute("blah");
        session.close();
    }
}

在许多课程中,我必须声明并打开会话,然后在最后关闭它。我宁愿用注释做一些事情,但我不知道从哪里开始。其他人如何做这样的事情:

class MyService {
    @TelnetTransaction
    public doSomething() {
        session.execute("blah");
    }
}

@TelnetTransaction 注释的方法实例化、打开并传入TelnetSession 对象。

谢谢,

詹姆斯

【问题讨论】:

  • 注解本身不会做任何事情。它们只是元数据。你需要 SOMETHING 来调查和做事。这是非常常见的自定义类加载器。

标签: java dependency-injection annotations


【解决方案1】:

之前和之后是面向方面编程的用途。

Spring 处理带有切面的事务。看看 Spring AOP 或 AspectJ。

【讨论】:

  • 而且,如果您想自己开发,请查找代理模式。
【解决方案2】:

除非您正在做一些复杂的事情,否则您希望最终得到一个委托给服务对象的对象,并执行周围的操作。两种类型都没有理由实现完全相同的接口,也有充分的理由不应该这样做。有很多方法可以解决这个问题:

  • 只需手动操作即可。我建议在开始代码生成之前总是这样开始。
  • 使用动态代理。不幸的是,java.lang.reflect.Proxy 要求您添加接口。
  • 使用 APT(或至少 1.6 javac 中的注释处理工具)生成代码。 Java 源代码比字节码容易,但我不知道有什么好的库可以生成 Java 源代码。
  • 手动使用 Execute Around 习语 - 冗长而笨拙。

【讨论】:

  • 使用 APT 生成 Java 源代码是一个非常高级的话题,尤其是如果你想修改现有的类(我知道,我最近这样做了,它给了我很大的困难,你需要与吨斗争未记录的内部 javac 调用)。我建议代理或 AOP(代理也是 AOP)
  • @seanizer 使用 apt 修改现有类是错误的。
  • 我知道这是官方的措辞,但正是它让像 Project Lombok 这样的伟大技术成为可能。但是你自己在这里建议的。他应该如何在不修改现有类的情况下使用 APT 实现这个功能?
  • @seanizer 需要明确的是,Project Lombok 是一个完整而彻底的 hack,IMO。这个想法是始终创建一个委托给原始类的新类。客户端代码将使用生成的类(即 API),然后生成的类使用实现类(SPI)。
  • a) 我猜这种方法是有道理的。 b) 我知道 Lombok 是一个 hack,但它是一个很棒的 hack c) 在我最近的案例中,这不是一个选择,因为我正在扩展检票口组件,并且有一个严格的层次结构可以防止这种委托。如果需要,请在此处阅读信息:stackoverflow.com/questions/3652463/…
【解决方案3】:

正如 duffymo 所说,AOP 是要走的路。我建议你买一份

AspectJ in Action

它是由 Spring Committer Ramnivas Laddad 编写的,它全面且易于理解地涵盖了 Spring AOP 和“真正的”AspectJ。

对于开发,您应该使用 Eclipse 的 AspectJ Developer Tools 或更好的 SpringSource Tool Suite(它包含 AJDT)。

【讨论】:

    【解决方案4】:

    如果您已经在使用 Spring AOP,它将是您的最佳选择。如果需要运行时注入,则需要使用 AspectJ。我记得读过 Spring 不支持那种注入

    【讨论】:

    • 在 AOP 调用前后不需要字节码操作。
    • @duffymo 没错。 Spring AOP 将 spring bean 上的方法执行匹配为唯一支持的切入点(AspectJ 支持更多)。但是这些切入点可以被beforeafter(几种)和around 建议作为目标。限制到这种切入点使 spring 可以选择使用 JDK 代理或使用 CGLib 进行动态子类化。如果你想要额外的切入点,你需要静态 AspectJ 编译或加载时间编织。
    猜你喜欢
    • 1970-01-01
    • 2013-05-31
    • 2014-05-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-10-27
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多