Pourquoi le Printemps de l'AOP n'est pas le tissage externe pots au moment de l'exécution?
J'ai une application java de construire sur le Printemps 3. Ce projet a un autre bocal comme une dépendance.
Cette dépendance contient un @org.aspectj.lang.annotation.Aspect
classe (disons, com.aspectprovider.aspects.MyAspect
). Il y a un @Before
conseils afin de tisser une méthode de classes implémentant l'interface Foo
. Quelque chose comme:
@Before("execution(* com.project.Foo.save(..))")
La Foo
interface peut être à l'intérieur du "projet" ou dans un autre bocal. Il n'a pas d'importance pour cet exemple.
Mon projet contient des classes qui implémente Foo
. Ceux sont les classes que je veux qu'il soit tissé, bien sûr.
Mon Printemps contexte de l'application le fichier de configuration (applicationContext.xml
) contient la ligne:
<aop:aspectj-autoproxy />
Je déclare également l'aspect comme un haricot, et injecter des propriétés:
<bean id="myAspect" class="com.aspectprovider.aspects.MyAspect"
factory-method="aspectOf" >
<property name="someproperty" value="somevalue" />
</bean>
Creux de journalisation je peux voir que MyAspect
est instancié et les propriétés sont injectés. Mais la méthode save n'est pas intercepté. C'est le problème.
Si je copie l'aspect des classes à partir du pot de l'application qui a le Printemps, il fonctionne. Lorsque ces aspects sont contenues dans les externes, les pots, la méthode save n'est pas intercepté. Toute indices?
edit: comment j'appelle Foo méthode save:
//in a JSF managed bean
@Inject
private Foo myFoo; //there's a implementation of Foo in a package that spring is looking at. So it is injected correctly.
public String someAction() {
myFoo.save("something"); //the @Before advice is only called if the class containing the aspect is not in an external jar
}
//in a class with a main method
void main(String[] ars) {
ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");
//right after the previous line, I can see in the log that MyAspect is instantiated.
Foo myFoo = ac.getBean(Foo.class);
myFoo.save("something"); //the @Before advice is only called if the class containing the aspect is not in an external jar
}
Fondamentalement, ma applicationContext.xml
a les lignes suivantes:
<context:annotation-config />
<context:component-scan base-package="com.project" />
<context:component-scan base-package="com.aspectprovider.aspects" />
<aop:aspectj-autoproxy />
<bean id="myAspect" class="com.aspectprovider.aspects.MyAspect" factory-method="aspectOf" >
<property name="someproperty" value="somevalue" />
</bean>
Je ne pense pas que j'ai besoin de mettre quelque chose comme
<context:component-scan base-package="com.project">
<context:include-filter type="aspectj" expression="com.aspectprovider.aspects.*" />
</context:component-scan>
- Êtes-vous en cours d'exécution en vertu d'un J2EE environnement? Weblogic, websphere, jboss ou même de tomcat?
- c'est tomcat. mais j'ai le même problème si je passe par la console, le chargement printemps contexte "à la main".
- Comment faites-vous appel à la
save
méthode en question? Si vous n'êtes pas en l'appelant par l'intermédiaire d'un renvoi que le Printemps est en fournissant votre code, la coupe transverse (pointcut) ne sera pas appelé. L'habitude erreur est d'appeler viathis
(explicitement ou implicitement), qui est une invocation directe sur le enveloppés d'instance et non pas sur le bean lui-même. - Salut. Oui. Je suis d'appel par le biais d'une référence que le printemps s'offrant à moi. Soit par getBean ou la dépression Printemps contexte d'application web, avec des annotations. Il n'y a pas de nouveau mot-clé dans mon code. Je suis en train de modifier le post et ajouter comment je fais appel. Je suis également à la fixation de l'aspect de l'emballage.
Vous devez vous connecter pour publier un commentaire.
J'ai le même problème. J'ai résolu ce problème d'emballage avec maven. De vérifier la
aspectj-maven-plugin
et optionweaveDependency
http://mojo.codehaus.org/aspectj-maven-plugin/weaveJars.html
Considérant qu'il fonctionne parfaitement bien lorsque les classes sont emballés avec de l'application et de printemps, je ne peux que penser qu'il serait un classloading question.
Si cela fonctionne bien lorsque votre forfait dans votre application, puis ensuite lors de l'AOP scans de toutes les classes qu'il aura à surveiller alors il est référence au droit du chargeur de classe avec tous les pots. Mais maintenant, quand vous la retirez et mis dans un BOCAL c'est la numérisation sous le chargeur de classe avec tous les autres tiers pots.
Je ne suis pas 100% sûr de savoir comment il est tracé, mais il pourrait être quelque chose comme ceci:
Si son aspect.jar analyse sous son chargeur de classe, alors il ne sera pas en mesure de voir toutes vos classes. Une façon, vous pouvez essayer de confirmer ce est pour obtenir un heap dump de votre application. Exécuter contre Eclipse MAT, découvrez Chargeur de Classe d'explorer et de regarder pour l'aspect classes. S'ils ne vivent pas sous le même chargeur de classe en tant que votre demande vous avez à regarder de façon de tomcat dire le tiers des bibliothèques de classes de l'application.
Foo
's implémentations dansMyAspect
's pot, puis lesave()
méthode de cette mise en œuvre a été intercepté lorsque je l'ai appelé de la manière décrite dans la question. Donc, maintenant que nous sommes sûrs de cela, il n'y a rien qui peut être fait?MyAspect
dans un bocal à un client qui utilise le Printemps et dites-lui juste pour écrire configuration simple sur son applicationContext (pas de aop.xml). De Plus, je veux être en mesure de tester les aspects avec jUnit. Jusqu'à présent, je suis à l'aide d'eclipse (sans plugins) + maven et en cours d'exécution$ mvn compile
chaque fois que je change toute la classe...Vous pouvez essayer d'aspectJ LTW au lieu de Spring AOP proxy. Pour ce faire, ajouter un aop.xml pour votre META-INF
Et c'est le printemps partie de la config:
Voir ici pour les détails : http://static.springsource.org/spring/docs/3.0.x/spring-framework-reference/html/aop.html#aop-aj-ltw
De AspectJ dans l'action du livre:
aspects utilisé avec le proxy de base de la programmation orientée aspect (déclarée à l'aide de @AspectJ
ou de la syntaxe XML) sont des beans Spring et ne devrait pas utiliser le aspectOf() approche
à l'instanciation.
Déclarer normalement et voir si ça fonctionne:
factory-method
,MyAspect
est instancié deux fois. Je crois que la première fois, c'est à cause de<aop:aspectj-autoproxy />
. Une chose ou l'autre, encore ne fonctionne que lorsqueMyAspect
n'est pas dans un bocal.J'ai fini par déclarer les aspects dans le printemps de l'applicationContext xml de config et en supprimant les annotations.
Ce qui a été travaillé jusqu'à présent a été l'aide de la aspectj plugin maven, mais à chaque fois j'ai changé de classe dans eclipse, j'ai dû courir
$ mvn compile
(parce que eclipse ne savent pas les aspects, et était en train de rassembler les classes sans eux), et c'est une chose terrible à dire à quelqu'un qui va utiliserMyAspect
.Alors je viens de créer un fichier de configuration et documenté: pour utiliser
MyAspect
, il suffit d'importer cette config règles de votre ressort du contexte de configuration.prendre un coup d'oeil à ApectWerks, il le fait au moment du chargement de tissage:
http://aspectwerkz.codehaus.org/weaving.html