У меня есть приложение 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-метод — нет.
Я не знаю, что делать. Возможно, моя идея вообще не сработает.
@kriegaex Извините за поздний ответ. Я надеялся, что аннотация SampleEntity будет управляться весной с помощью аннотации @Configurable.




Я надеялся, что
SampleEntityбудет управляться весной с помощью аннотации@Configurable.
Нет, он по-прежнему неуправляем без каких-либо @Component, @Service или подобных аннотаций компонентов Spring. Как следует из названия, он просто делает неуправляемый объект настраиваемым, т. е. вы можете внедрить в него bean-компоненты Spring с помощью @Autowired. См. это руководство по Baeldung и, конечно же, документацию Spring для получения дополнительной информации:
Обратите внимание, что вам необходимо активировать встроенное переплетение аспектов в сочетании с библиотекой аспектов spring-aspects, чтобы @Configurable имел какой-либо эффект через AnnotationBeanConfigurerAspect.
Обновление: я забыл упомянуть, что если вы хотите применить АОП к неуправляемым классам, у вас есть выбор: либо сделать их управляемыми, как упоминалось ранее, либо использовать собственный AspectJ, который не имеет таких ограничений, связанных с Spring, и может быть применен. в код POJO, с Spring или без него. AspectJ также не требует и не создает никаких прокси.
SampleEntityне похоже на компонент/компонент, управляемый Spring. Почему вы ожидаете, что Spring AOP окажет на это какое-либо влияние? Просьба уточнить. Была ли ваша цель использовать Spring AOP, как это подразумевает конфигурация, или вы хотите использовать собственный AspectJ для перехвата классов, не управляемых Spring?