Это больше похоже на AOP (Аспектно-ориентированное программирование), чем на аннотации. Темы часто путаются, так как АОП использует аннотации для достижения своих целей. Вместо того, чтобы заново изобретать AOP, я бы порекомендовал поискать и существующую библиотеку AOP, например AspectJ .
Однако, чтобы ответить на ваш конкретный вопрос, есть два возможных подхода к достижению вашей цели.
Подход во время выполнения
Это подход, обычно используемый в контейнерах (например, Spring). Это работает так, что вместо того, чтобы создавать экземпляры своих классов самостоятельно, вы запрашиваете у контейнера экземпляр вашего класса.
Контейнер имеет логику для проверки класса на предмет любых RuntimeAnnotations (например, @Widgetize). Затем контейнер будет динамически создавать прокси вашего класса, который сначала вызывает правильный метод Widgetize, а затем вызывает целевой метод.
Затем контейнер вернет этот прокси исходному запрашивающему. Запрашивающий по-прежнему обнаружит, что он получил класс (или интерфейс), который он запрашивал, и не будет знать о поведении прокси, добавленном контейнером.
Это также поведение, используемое AspectJ.
Подход к усовершенствованию
Это подход, принятый AspectJ. Если честно, я не знаю много деталей о том, как это работает. Каким-то образом AspectJ будет сканировать ваши файлы классов (байт-код), выяснить, где находятся аннотации, а затем изменить сам байт-код, чтобы вызывать прокси-класс вместо фактического класса.
Преимущество этого подхода в том, что вам не нужно использовать контейнер. Недостатком является то, что теперь вы должны выполнить этот шаг улучшения после компиляции кода.