Как переопределить класс.getName () для определенных классов?


Моя цель-иметь возможность переопределять то, что я получаю от CustomClass.класс.getName () и CustomClass.getClass ().getName ()

Он должен возвращать пользовательское значение, которое, я думаю, лучше всего определить в атрибуте типа

@NameOverride("Custom.fully.qualified.class.name")
public class CustomClass {}
Есть ли какой-нибудь способ сделать это?
2 3

2 ответа:

Ответ Фреда в порядке, но его аспект может быть несколько более элегантным с меньшим количеством кода и особенно меньшим количеством вызовов отражения. Извините, я предпочитаю стиль собственного кода AspectJ, но стиль аннотаций @AspectJ не будет намного длиннее:

String around(Class clazz) : call(public String Class.getName()) && target(clazz) {
    NameOverride nameOverride = (NameOverride) clazz.getAnnotation(NameOverride.class);
    return nameOverride == null ? proceed(clazz) : nameOverride.value();
}

Вот полный исходный код. Я добавил класс без аннотации, чтобы показать различное поведение, а также ограничение на определения классов - @Target(ElementType.TYPE) - к классу аннотаций. Я также показываю имена пакетов и импорт:

package test;

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

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface NameOverride {
    String value();
}
package test;

public class NormalClass {}
package test;

@NameOverride("Custom.fully.qualified.class.name")
public class CustomClass {}
package test;

public class Main {
    public static void main(String[] args) {
        System.out.println(NormalClass.class.getName());
        System.out.println(CustomClass.class.getName());
        System.out.println(new NormalClass().getClass().getName());
        System.out.println(new CustomClass().getClass().getName());
    }
}
package aspectj;

import test.NameOverride;

public aspect GetNameOverrider {
    @SuppressWarnings({ "unchecked", "rawtypes" })
    String around(Class clazz) : call(public String Class.getName()) && target(clazz) {
        NameOverride nameOverride = (NameOverride) clazz.getAnnotation(NameOverride.class);
        return nameOverride == null ? proceed(clazz) : nameOverride.value();
    }
}

Вывод:

test.NormalClass
Custom.fully.qualified.class.name
test.NormalClass
Custom.fully.qualified.class.name

Это, конечно, не самое лучшее/быстрое решение, но, возможно, POC...

Прежде всего структура файла:

./src/aspectj:
GetNameOverrider.aj

./src/test:
CustomClass.java    Main.java       NameOverride.java

NameOverride.java:

@Retention(RetentionPolicy.RUNTIME)
public @interface NameOverride {
    String value();
}

GetNameOverrider.aj:

@Aspect
public class GetNameOverrider {
    @Around("call(String getName()) && !within(aspectj..*)")
    public String advice(ProceedingJoinPoint pjp) throws Throwable {

        String ret = (String) pjp.proceed();

        String className = "" + pjp.getTarget();
        className = className.replace("class ", "");
        try {
            test.NameOverride anno = Class.forName(className).getAnnotation(
                    test.NameOverride.class);

            if (anno != null) {
                return anno.value();
            }
        } catch (ClassNotFoundException e) {
            return ret;
        }

        return ret;
    }
}

Выдает меня за главного.java:

public class Main {
    public static void main(String[] args) {
        System.out.println(CustomClass.class.getName());
        System.out.println(new CustomClass().getClass().getName());
    }
}

Вывод:

Custom.fully.qualified.class.name
Custom.fully.qualified.class.name