java - 当对象状态改变时调用方法

标签 java aop eclipse-plugin bcel

我提供了一个注释@validateName,任何人都可以将其包含在他们的代码中。假设有人编码

class Person {
    @validateName
    private String name;
    ....
}

然后他们可以调用 NameValidator.validate(personObject) 或一些类似的方法来验证该字段。

我想确保名称字段始终处于有效状态,即每当带注释的变量发生变化时(无论它在内部或内部发生变化,我想自动调用 validate() 方法)课外)。
我愿意编写一个 Hook 到 Eclipse 并在编译阶段调用的插件。请提供一些指示,我可以从那里开始寻找解决方案。
(我想我必须实现某种 AOP 或者应该使用 BCEL 或其他东西修改字节码。我不确定,因为我还没有尝试过这两种方法。)

最佳答案

使用 AspectJ,您可以执行以下操作:

注释

package de.scrum_master.aop.app;

import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;

@Retention(RetentionPolicy.RUNTIME)
public @interface ValidateName {}

驱动程序类别

package de.scrum_master.aop.app;

public class Application {
    private int id;
    @ValidateName
    private String firstName;
    @ValidateName
    private String lastName;
    private String placeOfBirth;

    public Application(int id, String firstName, String lastName, String placeOfBirth) {
        this.id = id;
        this.firstName = firstName;
        this.lastName = lastName;
        this.placeOfBirth = placeOfBirth;
    }

    @Override
    public String toString() {
        return "Application [id=" + id + ", firstName=" + firstName
                + ", lastName=" + lastName + ", placeOfBirth=" + placeOfBirth
                + "]";
    }

    public static void main(String[] args) {
        System.out.println(new Application(1, "Galileo", "Galilei", "Pisa, Italy"));
        System.out.println(new Application(2, "Isaac", "Newton", "Woolsthorpe-by-Colsterworth, United Kingdom"));
        System.out.println(new Application(3, "Albert", "Einstein", "Ulm, Germany"));
        System.out.println(new Application(4, "Werner", "Heisenberg", "Würzburg, Germany"));
    }
}

验证者方面

package de.scrum_master.aop.aspect;

import java.util.Random;
import de.scrum_master.aop.app.ValidateName;

public aspect NameValidator {
    void validate(String name) {
        if (new Random().nextBoolean())
            throw new RuntimeException("Invalid name " + name);
    }

    void around(String name) : set(@ValidateName * *.*) && args(name) {
        //System.out.println(thisJoinPointStaticPart);
        System.out.print("Validating name " + name);
        try {
            validate(name);
            System.out.println(" -> OK");
            proceed(name);
        }
        catch (Exception e) {
            name = name.toUpperCase();
            System.out.println(" -> " + e.getMessage() + " -> replaced by " + name);
            proceed(name);
        }
    }
}

如您所见,我的 validator 在大约 10 天内随机失败。所有案例中的 50% 基于伪随机值。当它发生时,它只是用大写版本替换“无效”名称。输出看起来像这样的变体:

Validating name Galileo -> OK
Validating name Galilei -> Invalid name Galilei -> replaced by GALILEI
Application [id=1, firstName=Galileo, lastName=GALILEI, placeOfBirth=Pisa, Italy]
Validating name Isaac -> Invalid name Isaac -> replaced by ISAAC
Validating name Newton -> Invalid name Newton -> replaced by NEWTON
Application [id=2, firstName=ISAAC, lastName=NEWTON, placeOfBirth=Woolsthorpe-by-Colsterworth, United Kingdom]
Validating name Albert -> OK
Validating name Einstein -> Invalid name Einstein -> replaced by EINSTEIN
Application [id=3, firstName=Albert, lastName=EINSTEIN, placeOfBirth=Ulm, Germany]
Validating name Werner -> OK
Validating name Heisenberg -> Invalid name Heisenberg -> replaced by HEISENBERG
Application [id=4, firstName=Werner, lastName=HEISENBERG, placeOfBirth=Würzburg, Germany]

关于java - 当对象状态改变时调用方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16352838/

相关文章:

java - 如何在docker中运行maven selenium项目(Maven + Selenium + java + TestNg + docker)

java - 如何开发(本地)和部署Storm Topology(远程)?

java - 匹配一组字符串的正则表达式

vb.net - Ninject:如何使用约定绑定(bind)的拦截

spring - 在 Spring AOP 中获取 session

java - 刷新 View 中的菜单项

java - 正则表达式查找字母和数字由符号分隔或不分隔的单词

ioc-container - Ninject:为 AoP 代理类型时可以使用注入(inject)构造函数吗?

eclipse - 如何使用 Eclipse UML Generators 插件

java - 无法安装适用于 Eclipse 的 Windows Azure 插件