Как переопределить класс.getName () для определенных классов?
Моя цель-иметь возможность переопределять то, что я получаю от CustomClass.класс.getName () и CustomClass.getClass ().getName ()
Он должен возвращать пользовательское значение, которое, я думаю, лучше всего определить в атрибуте типа
@NameOverride("Custom.fully.qualified.class.name")
public class CustomClass {}
Есть ли какой-нибудь способ сделать это?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