Динамически регистрируйте внешние аспекты @AspectJ в основном весеннем проекте

В настоящее время я пытаюсь интегрировать внешние аспекты @AspectJ в проект Spring+JSF. То есть мои аспекты реализованы в отдельных проектах и ​​должны быть загружены в основной контекст приложения во время выполнения. Это работает нормально, если я объявляю внешний аспект в контексте моего приложения, который затем загружается первым делом в основной.

ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext("app-context.xml");

Однако я хочу иметь возможность динамически загружать неизвестное количество Аспектов, чтобы я мог упаковать некоторые аспекты в плагины, которые развертываются в зависимости от настроек зависимостей в моем maven pom.

вот мой app-context:

   <?xml version="1.0" encoding="UTF-8" ?>

<beans xmlns="http://www.springframework.org/schema/beans" 
    xmlns:aop="http://www.springframework.org/schema/aop"
    xmlns:context="http://www.springframework.org/schema/context"
    xmlns:task="http://www.springframework.org/schema/task"
    xmlns:jee="http://www.springframework.org/schema/jee"
    xmlns:jpa="http://www.springframework.org/schema/data/jpa"
    xmlns:tx="http://www.springframework.org/schema/tx" 
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
    xsi:schemaLocation="http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd   
                        http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd   
                        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd
                        http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task-3.0.xsd  
                        http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-3.0.xsd  
                        http://www.springframework.org/schema/data/jpa http://www.springframework.org/schema/data/jpa/spring-jpa.xsd 
                        http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd"
    default-autowire="byName">


    <context:annotation-config />
    <context:component-scan base-package="..." />

    <import resource="app-ds-jpa.xml"/>

    <!-- a explicit -->
    <bean id="stopWatchProviderAspect" class="....util.StopWatchProviderAspect" />      
    <!-- b dynamic -->
    <bean class="org.springframework.aop.aspectj.annotation.AnnotationAwareAspectJAutoProxyCreator" /> 

    <!-- Enable the @AspectJ support -->
    <aop:aspectj-autoproxy proxy-target-class="true" />
</beans>

StopWatchProvider загружается через зависимость maven. Явное определение компонента (a) будет работать нормально. Динамический подход, однако, терпит неудачу со следующим исключением:

Exception in thread "main" org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'defaultData': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: private ....manager.CustomerManager ....util.DefaultData.customerManager; nested exception is java.lang.IllegalArgumentException: Can not set ....manager.CustomerManager field ....util.DefaultData.customerManager to $Proxy26
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:285)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1074)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:517)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:456)
    at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:291)
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:222)
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:288)
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:190)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:580)
    at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:895)
    at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:425)
    at org.springframework.context.support.ClassPathXmlApplicationContext.<init>(ClassPathXmlApplicationContext.java:139)
    at org.springframework.context.support.ClassPathXmlApplicationContext.<init>(ClassPathXmlApplicationContext.java:83)
    at ....App.main(App.java:190)
Caused by: org.springframework.beans.factory.BeanCreationException: Could not autowire field: private ....manager.CustomerManager ....util.DefaultData.customerManager; nested exception is java.lang.IllegalArgumentException: Can not set ....manager.CustomerManager field ...e.util.DefaultData.customerManager to $Proxy26
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:502)
    at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:84)
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:282)
    ... 13 more
Caused by: java.lang.IllegalArgumentException: Can not set ....manager.CustomerManager field ....util.DefaultData.customerManager to $Proxy26
    at sun.reflect.UnsafeFieldAccessorImpl.throwSetIllegalArgumentException(UnsafeFieldAccessorImpl.java:146)
    at sun.reflect.UnsafeFieldAccessorImpl.throwSetIllegalArgumentException(UnsafeFieldAccessorImpl.java:150)
    at sun.reflect.UnsafeObjectFieldAccessorImpl.set(UnsafeObjectFieldAccessorImpl.java:63)
    at java.lang.reflect.Field.set(Field.java:657)
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:498)

Не знаю, возможно ли это вообще. Однако я обнаружил в старом посте в комментариях, что AnnotationAwareAspectJAutoProxyCreator конфликтует с моим Autowireing byName.

Обнаружил, что где-то еще, что предполагает такая ошибка, я использую прокси-сервер, который является незаконным, хотя я не понимаю, что это должно означать.

Один из ответов на связанный с этим вопрос заключается в том, что мне нужно выполнить autoproxy после инициализации всех компонентов, но это не помогло (как видно из контекста моего приложения).

Я постоянно искал способ автоматического определения моих Аспектов в основном приложении без необходимости статически определять их в основном app-context.xml. Мне не нужно делать это через AnnotationAwareAspectJAutoProxyCreator. Пока мне не нужно "регистрировать" все аспекты в одном файле app-context.xml, я счастлив.

Мой альтернативный вариант - сделать так, чтобы все плагины реализовывали общий интерфейс "Pluggable" с доступом к PluginManager, через который они могли бы начать () редактировать, загружая собственный контекст приложения, чтобы я мог поместить определение компонента в их дочерний контекст.xml в качестве ресурса в рамках своих соответствующих проектов. Я как бы заставил это работать (по крайней мере, загрузку нескольких контекстов приложения, чтобы я мог хранить информацию о компоненте в соответствующем пакете), но я все же предпочел бы более динамичный подход.

Спасибо за любые ссылки или, возможно, даже ответы на вопрос, почему я получаю это исключение!


РЕДАКТИРОВАТЬ:

Поскольку никто, кажется, не знает решения для конфликта между autowire по имени и AnnotationAwareAspectJAutoProxyCreator теперь мы регистрируем наши аспекты в контексте их проекта и импортируем все контексты проекта в веб-приложение, использующее этот аспект:

Основной проект:

аспект:

@Aspect
public class SomeAspect { ... }

ядро-context.xml:

<bean id="someAspect" class="path.to.core.SomeAspect />         
<aop:aspectj-autoproxy proxy-target-class="true" />

Веб-проект:

<import resource="classpath:core-context.xml"/> 

Тогда аспект будет срабатывать и в веб-проекте. Нам этого пока достаточно.

Я думаю, что другой динамический подход будет сканировать путь к классам для @Aspect аннотации внутри бина установки и регистрируют аспекты через BeanFactory.

Тем не менее, если кто-то знает больше о конфликте между Autowire: by-name а также AnnotationAwareAspectJAutoProxyCreator Пожалуйста, поделитесь этим.

0 ответов

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