Аспектно-ориентированное расширение для сущностей в Spring Boot

У меня есть приложение Spring Boot 2.7.6. У меня есть несколько объектов, которые управляются через различные репозитории Mongo. Я хотел бы расширить свои объекты метаданными. Поэтому я решил создать репозиторий метаданных, содержащий метаданные для всех сущностей, и расширить эти сущности с помощью интерфейса IMetadata, содержащего реализацию по умолчанию. Затем этот метод должен загрузить данные из репозитория метаданных, используя аспект, а затем вернуть их.

Вот как выглядят мои занятия:

package io.zzzz.interfaces;
//imports are there

public interface IMetadata {
  @JsonIgnore
  default List<Metadata> getMetadata() {
    return null;
  }


package io.zzzz.entities;
//imports are there

@Getter
@Setter
@NoArgsConstructor
@Configurable
@Document("samples")
public class SampleEntity implements IMetadata {
  @Id private String id;
  // ... many other fields

package io.zzzz;
//imports are there

@Aspect
@Component
@EnableAspectJAutoProxy(proxyTargetClass=true)
@Slf4j
public class MetadataAspect implements ApplicationContextAware {
  @Override
  public void setApplicationContext(ApplicationContext context) throws BeansException {
    metadataService = context.getBean(MetadataService.class);
  }

  @Around("execution(* getMetadata(..))")
  public Object getMetadataAdvice(ProceedingJoinPoint joinPoint) {
    log.debug("Accessing metadata ...");
    var metadataOwner = joinPoint.getTarget();
    var md = metadataService.getMetadataForEntity((IMetadata) metadataOwner);
    log.debug("Accessed metadata.");
    return md;
  }
}

Я добавил следующие зависимости:

    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-instrument</artifactId>
      <version>5.3.24</version>
      <scope>runtime</scope>
    </dependency>
    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-aop</artifactId>
    </dependency>
    <dependency>
      <groupId>org.aspectj</groupId>
      <artifactId>aspectjweaver</artifactId>
      <version>1.9.7</version>
    </dependency>
    <dependency>
      <groupId>org.aspectj</groupId>
      <artifactId>aspectjrt</artifactId>
      <version>1.9.7</version>
    </dependency>

Я добавил @EnableLoadTimeWeaving в свое приложение, а также добавил javaagent в параметры виртуальной машины -javaagent:<path>/spring-instrument-5.3.24.jar.

Поскольку ничего из этого не сработало, я создал следующее aop.xml в META-INF:

<aspectj>
  <weaver>
    <include within = "io.zzzz.entities..*"/>
  </weaver>
  <aspects>
    <aspect name = "io.zzzz.MetadataAspect"/>
  </aspects>
</aspectj>

Я добавил опцию виртуальной машины -Daj.weaving.verbose=true, чтобы продлить ведение журнала во время запуска, чтобы увидеть, не произошло ли что-то. Я вижу некоторое плетение, так что, по крайней мере, в принципе это должно сработать. Если я сформулирую аспект и аоп-конфиг немного более широко, то я также увижу, что, например, сервисные методы вызываются и передаются через аспект, а мой getMetadata-метод — нет.

Я не знаю, что делать. Возможно, моя идея вообще не сработает.

SampleEntity не похоже на компонент/компонент, управляемый Spring. Почему вы ожидаете, что Spring AOP окажет на это какое-либо влияние? Просьба уточнить. Была ли ваша цель использовать Spring AOP, как это подразумевает конфигурация, или вы хотите использовать собственный AspectJ для перехвата классов, не управляемых Spring?
kriegaex 13.03.2024 17:13

@kriegaex Извините за поздний ответ. Я надеялся, что аннотация SampleEntity будет управляться весной с помощью аннотации @Configurable.

Andreas Rieger 27.03.2024 19:16
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Версия Java на основе версии загрузки
Версия Java на основе версии загрузки
Если вы зайдете на официальный сайт Spring Boot , там представлен start.spring.io , который упрощает создание проектов Spring Boot, как показано ниже.
Документирование API с помощью Swagger на Springboot
Документирование API с помощью Swagger на Springboot
В предыдущей статье мы уже узнали, как создать Rest API с помощью Springboot и MySql .
0
2
78
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Я надеялся, что SampleEntity будет управляться весной с помощью аннотации @Configurable.

Нет, он по-прежнему неуправляем без каких-либо @Component, @Service или подобных аннотаций компонентов Spring. Как следует из названия, он просто делает неуправляемый объект настраиваемым, т. е. вы можете внедрить в него bean-компоненты Spring с помощью @Autowired. См. это руководство по Baeldung и, конечно же, документацию Spring для получения дополнительной информации:

Обратите внимание, что вам необходимо активировать встроенное переплетение аспектов в сочетании с библиотекой аспектов spring-aspects, чтобы @Configurable имел какой-либо эффект через AnnotationBeanConfigurerAspect.


Обновление: я забыл упомянуть, что если вы хотите применить АОП к неуправляемым классам, у вас есть выбор: либо сделать их управляемыми, как упоминалось ранее, либо использовать собственный AspectJ, который не имеет таких ограничений, связанных с Spring, и может быть применен. в код POJO, с Spring или без него. AspectJ также не требует и не создает никаких прокси.

Другие вопросы по теме