代码之家  ›  专栏  ›  技术社区  ›  Henrik P. Hessel

JavaGETS:总是执行特定的方法

  •  2
  • Henrik P. Hessel  · 技术社区  · 15 年前

    有没有一种方法可以定义一个方法,每当我调用get时都会调用这个方法?

    我有一个对象联系人,不想在大约30个getter中为我的成员设置updateLastUsed()。

    10 回复  |  直到 15 年前
        1
  •  2
  •   ChssPly76    15 年前

    我本来会建议使用AOP,但如果它是J2ME,我们讨论的是您最好在30个访问器中手动插入“ongetCalled()”,然后在该方法中编写所需的代码。如果将来需要的话,您可能希望传入正在调用(或访问属性)的方法的名称。

        2
  •  3
  •   Johannes    15 年前

    您可以创建一个将属性名作为输入的常规getter,而不是访问属性的getter。如果属性的类型不同,则返回类型必须是对象。

    在这个常规getter中,您调用属性getter和updateLastUsed()方法。为了安全起见,请将所有财产收归私人所有。

        3
  •  2
  •   Rich Seller    15 年前

    您可以添加对每个方法的调用(无聊),或者使用某种形式的AOP(例如,下面的aspectj示例)来匹配类型的getter并调用updateLastUsed()方法。

    编辑:有人指出30个getter是一种代码味道,调用另一个方法是一种副作用。第一个陈述是一个公平的指标,但不是规则。有很多原因可以使用这种类型,如果没有进一步的信息,我会留下它作为建议,检查您是否可以将职责分为两种或更多类型。

    关于副作用的另一点可能或可能不相关。有许多横切关注,它使传感器应用于吸气剂方法。例如日志记录、身份验证和缓存。示例方法updateLastUsed()可能是缓存策略的一部分,因此我认为对该问题的无保留批评是不可取的。

    如何在AspectJ中实现切入点和通知的示例如下:

    package test;
    
    public aspect TestAspect {
        /**
         * Match all getters of test.Contact and bind the target.
         */
        protected pointcut contactGetters(Contact contact) : 
            execution(* test.Contact.get*()) && target(contact);
    
        /**
         * Before execution of each getter, invoke the updateLastUsed() method
         * of the bound target.
         */
        before(Contact contact): contactGetters(contact) {
            contact.updateLastUsed();
        }       
    }
    
        4
  •  1
  •   jsight TaherT    15 年前

    要做到这一点,需要像AOP这样的东西。我不知道在J2ME上有多好的支持,除了 this .

        5
  •  1
  •   ykaganovich Mike Samuel    15 年前

    除了AOP,您还可以使用 java.lang.reflect.Proxy 或字节码操作…

    但不在J2ME上

    我建议调用updateLastUsed()30次。

        6
  •  1
  •   dustmachine    15 年前

    这看起来像面向方面编程(AOP)的工作。

    定义要为以开头的任何内容执行的方面 get*

    “new”aspectj 5支持使用注释来定义方面切入点,这样您就可以注释getter以调用切入点。 @Before 执行方法体。

        7
  •  1
  •   Hosam Aly    15 年前

    使用正则表达式将方法调用附加到getter头。

    查找:

    \w+ get\w+\s*\(\)\s*\{(\s*)

    替换为:

    \0updateLastUsed();\1

    使用Eclipse3.5(Galileo)在“查找/替换”对话框中使用“全部替换”测试这些表达式。

    请注意,您使用的编辑器必须支持多行匹配(或者您必须启用它)。对于eMeditor 8.05,我必须将搜索字符串修改为:

    \w+ get\w+\s*\(\)\s*\{\s*(\n\s*)

    使新行显式匹配。替换字符串保持原样。

        8
  •  1
  •   Kendall Helmstetter Gelner    15 年前

    您可以做一些花哨的事情,但老实说,这就是为什么宏被添加到编辑器中,这样您就可以快速地重复枯燥的代码。

    我只需要让所有getter都调用这个方法,然后使用宏来创建调用(如果方法不同的话)。这一切只需要做一次,然后你就忘记了…

        9
  •  1
  •   Carl Manaster    15 年前

    这是一条路。它不漂亮,但你可能更喜欢它而不是重复:

    public class GetterTest extends TestCase {
        private static class Thing {
            public int  accessCount;
            private String  name;
            private int age;
    
            private <T> T get(T t) {
                accessCount++;
                return t;
            }
    
            public String getName() {
                return get(name);
            }
    
            public int getAge() {
                return get(age);
            }
        }
    
        public void testGetIncrementsAccessCount() throws Exception {
            Thing t = new Thing();
            assertEquals(0, t.accessCount);
            t.getName();
            assertEquals(1, t.accessCount);
            t.getAge();
            assertEquals(2, t.accessCount);
        }
    }
    

    显然,我的get()只是增加了accessCount,您还需要一些其他的行为,但是这个想法是存在的。

        10
  •  0
  •   John Doe    15 年前

    我会说代理对象来调用所需的方法。