Java Spring AOP: Могу ли я игнорировать ошибку Xlint: invalidAbsoluteTypeName, которая вызвана переходами к классам, которые я не использую?

У меня проблема с общим компонентом и одним (из дюжины) приложений. В моем компоненте есть точечные сокращения для многих аннотаций, которые можно использовать в классах и методах в моих приложениях. Когда все аннотации присутствуют в пути к классам, все работает нормально. Но не во всех моих приложениях есть эти зависимости. Быстрое решение - это, конечно, добавить их, но это дает моему приложению много кода, который мне не нужен в этом приложении. Я ищу способ игнорировать ошибку Xlint:invalidAbsoluteTypeName, как указано здесь: Xlint: invalidAbsoluteTypeName

Итак, что у меня есть:

  • У меня много приложений с соединениями Soap / JMS, и все они аннотированы @Annotation org.springframework.ws.server.endpoint.annotation.Endpoint.
  • У меня есть точка в моем общем компоненте (банке): @Around("within(@org.springframework.ws.server.endpoint.annotation.Endpoint *)")

И вот результат:

  • Все приложения, имеющие зависимость Spring WS вместе с моим универсальным компонентом, не имеют проблем
  • Приложения без аннотации не могут запуститься из-за java.lang.IllegalArgumentException: warning no match for this type name: org.springframework.ws.server.endpoint.annotation.Endpoint [Xlint:invalidAbsoluteTypeName] (что очевидно, см. Ссылку)

Итак, проблема выглядит как Xlint: invalidAbsoluteTypeName НО Я не Я не хочу добавлять зависимости Spring, которые я не использую. Я просто хочу, чтобы эта точка AOP игнорировалась. Другие обходные пути, такие как разделение pointcut на разные jar-файлы, imho создают слишком много накладных расходов. Есть ли способ заставить Spring AOP просто игнорировать этот pointcut или, например, установить pointcut на st как if-exists (class)?

Чтобы показать, почему я думаю, что разделение вызывает слишком много накладных расходов, взгляните на мою структуру аспектов:

@Aspect
public class PerformanceLoggingAspect {
    private LogWriter logWriter;

    @Inject
    public PerformanceLoggingAspect(LogWriter logWriter) {
        this.logWriter = logWriter;
    }

    @Around("within(@org.springframework.web.bind.annotation.RestController *)")
    public Object withinARestController(ProceedingJoinPoint pjp) throws Throwable {
        return proceedWithLogging(pjp, MetingType.REST);
    }

    @Around("within(@org.springframework.ws.server.endpoint.annotation.Endpoint *)")
    public Object withinAnEndpoint(ProceedingJoinPoint pjp) throws Throwable {
        return proceedWithLogging(pjp, MetingType.BERICHT);
    }

    @Around("within(@javax.inject.Named *)")
    public Object withinAService(ProceedingJoinPoint pjp) throws Throwable {
        return proceedWithLogging(pjp, MetingType.SERVICE);
    }

    private Object proceedWithLogging(ProceedingJoinPoint pjp, String metingType) throws Throwable {
        (... Working code (performance logging) if the annotation is on the classpath...)
    }
}

Обновление: я попытался создать @NeedsClass("any.package.Class"), который является аннотацией @Conditional из spring-context. Класс условия - это ClasspathCondition, который проверяет, может ли загрузчик классов загрузить данный класс. Но ошибка возникает до того, как условие будет оценено, поэтому я боюсь, что это тупик. Но если вам интересно:

Аннотации @NeedsClass, которые я пробовал

    @Retention(RetentionPolicy.RUNTIME)
    @Target({ElementType.TYPE, ElementType.METHOD})
    @Documented
    @Conditional(ClasspathCondition.class)
    public @interface NeedsClass {
        String[] value();
    }

Реализация Condition. У меня здесь был журнал, который так и не был записан

    public class ClasspathCondition implements Condition {
        @Override
        public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
            try {
                String[] classes = (String[]) metadata.getAnnotationAttributes(NeedsClass.class.getName()).get("classes");
                for (String clazz : classes) {
                    ClassUtils.resolveClassName(clazz, context.getClassLoader());
                }
                return true;
            } catch (Throwable t) { /* noOp() */}
            return false;
        }
    }

person Jeroen van Dijk-Jun    schedule 27.06.2017    source источник
comment
Попробуйте ввести бобы: stackoverflow.com/a/22872161/1888799   -  person veysiertekin    schedule 05.07.2017


Ответы (1)


На данный момент у меня есть обходной путь:

  • Я создал суперкласс методом:

    protected Object proceedWithLogging(ProceedingJoinPoint pjp, String metingType) throws Throwable {
        (... code which adds performance logging ...)
    }
    
  • Я создал 4 подкласса с аннотацией @Aspect и 1 метод, вызывающий super. Например, это нацелено на JMS:

    @Aspect
    public class JmsPerformanceLogger extends PerformanceLoggingAspect {
        @Inject
        private LogWriter logWriter;
    
        @Around("within(@org.springframework.ws.server.endpoint.annotation.Endpoint *)")
        public Object withinAnEndpoint(ProceedingJoinPoint pjp) throws Throwable {
            return proceedWithLogging(pjp, MetingType.BERICHT);
        }
    }
    
  • В качестве недостатка мне нужно настроить все необходимые bean-компоненты в моем приложении, и я не могу добавить один простой файл конфигурации, как показано ниже, со всеми предварительно настроенными bean-компонентами:

    @Configuration
    public class PerformanceloggingConfig {
    
        @Bean
        public LogWriter performanceLogWriter(){
            return new DefaultLogWriter();
        }
    
        @Bean
        public JmsPerformanceLogger jmsPerformanceLogger(){
            return new JmsPerformanceLogger();
        }
        @Bean
        public RestPerformanceLogger restPerformanceLogger(){
            return new RestPerformanceLogger();
        }
        @Bean
        public ServicesPerformanceLogger servicesPerformanceLogger(){
            return new ServicesPerformanceLogger();
        }
        @Bean
        public DaoPerformanceLogger daoPerformanceLogger(){
            return new DaoPerformanceLogger();
        }
    }
    

    И поэтому также не удобная аннотация для автоконфигурирования класса:

    @Retention(RetentionPolicy.RUNTIME)
    @Target(ElementType.TYPE)
    @Import(PerformanceloggingConfig.class)
    public @interface EnablePerformanceLogging {
    
    }
    

    Но пока добавление этих 4 bean-компонентов, когда они мне нужны, позволяет различать приложения. Но, конечно, это все еще обходной путь, так как я хочу использовать @EnablePerformanceLogging и покончить с этим. Если у кого-то есть лучший ответ, пожалуйста, скажите мне

person Jeroen van Dijk-Jun    schedule 28.06.2017