В настоящее время я пытаюсь интегрировать внешние аспекты @AspectJ в проект Spring + JSF.То есть мои аспекты реализованы в отдельных проектах и должны быть загружены в основной контекст приложения во время выполнения.Это работает нормально, если я объявляю внешний аспект в контексте моего приложения, который затем загружается первым делом в основной.
ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext("app-context.xml");
Однако я хочу иметь возможность динамически загружать неизвестное число Аспектов, чтобы я мог упаковать некоторые аспекты в плагины, которые развертываются в зависимости от настроек зависимостей в моем maven pom.
вот мой контекст приложения:
<?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.Явное определение бина (а) будет работать нормально.Однако динамический подход не дает результатов со следующим исключением:
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, с помощью которого они могут получить start (), загружая свой собственный контекст приложения, чтобы я мог поместить определение компонента в их дочерний контекст .xml в качестве ресурса в своих соответствующих проектах.Я как бы заставил это работать (по крайней мере, загрузку нескольких контекстов приложения, чтобы я мог хранить информацию о компоненте в соответствующем пакете), но я все же предпочел бы более динамичный подход.
Спасибо за любые указатели или, возможно, даже ответы на вопрос, почему я получаю это исключение!
РЕДАКТИРОВАТЬ:
Поскольку никто, кажется, не знает решения для конфликта между autowire по имени и AnnotationAwareAspectJAutoProxyCreator
, мы регистрируем наши аспекты в контексте их проектаТеперь и импортируйте все контексты проекта в веб-приложение, которое использует аспект:
Базовый проект :
Аспект:
@Aspect
public class SomeAspect { ... }
core-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
, пожалуйста, поделитесь им.