Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

@Aspect pointcut declarations do not support dynamically loaded classes [SPR-15040] #19606

Closed
spring-issuemaster opened this issue Dec 22, 2016 · 0 comments

Comments

@spring-issuemaster
Copy link
Collaborator

commented Dec 22, 2016

thomas weidner opened SPR-15040 and commented

The following steps should reproduce the issue:

  1. Create a usual spring (boot) application
  2. Load some additional jar files into an URLClassloader, where the application class loader is used as parent
  3. Create a new AnnotationConfigApplicationContext using configuration classes from the jars in step 2
  4. If these classes use Spring AOP AspectJ annotation advice definitions, which reference one of the dynamically loaded classes, the error occurs.

In my setup, where I dynamically load and advice freemarker I obtain the following stacktace:

 java.lang.IllegalArgumentException: warning no match for this type name: freemarker.cache.TemplateLoader [Xlint:invalidAbsoluteTypeName]
	at org.aspectj.weaver.tools.PointcutParser.parsePointcutExpression(PointcutParser.java:301) ~[aspectjweaver-1.8.9.jar:1.8.9]
	at org.springframework.aop.aspectj.AspectJExpressionPointcut.buildPointcutExpression(AspectJExpressionPointcut.java:207) ~[spring-aop-4.3.4.RELEASE.jar:4.3.4.RELEASE]
	at org.springframework.aop.aspectj.AspectJExpressionPointcut.checkReadyToMatch(AspectJExpressionPointcut.java:193) ~[spring-aop-4.3.4.RELEASE.jar:4.3.4.RELEASE]
	at org.springframework.aop.aspectj.AspectJExpressionPointcut.getClassFilter(AspectJExpressionPointcut.java:170) ~[spring-aop-4.3.4.RELEASE.jar:4.3.4.RELEASE]
	at org.springframework.aop.support.AopUtils.canApply(AopUtils.java:220) ~[spring-aop-4.3.4.RELEASE.jar:4.3.4.RELEASE]
	at org.springframework.aop.support.AopUtils.canApply(AopUtils.java:279) ~[spring-aop-4.3.4.RELEASE.jar:4.3.4.RELEASE]
	at org.springframework.aop.support.AopUtils.findAdvisorsThatCanApply(AopUtils.java:311) ~[spring-aop-4.3.4.RELEASE.jar:4.3.4.RELEASE]
	at org.springframework.aop.framework.autoproxy.AbstractAdvisorAutoProxyCreator.findAdvisorsThatCanApply(AbstractAdvisorAutoProxyCreator.java:118) ~[spring-aop-4.3.4.RELEASE.jar:4.3.4.RELEASE]
	at org.springframework.aop.framework.autoproxy.AbstractAdvisorAutoProxyCreator.findEligibleAdvisors(AbstractAdvisorAutoProxyCreator.java:88) ~[spring-aop-4.3.4.RELEASE.jar:4.3.4.RELEASE]
	at org.springframework.aop.framework.autoproxy.AbstractAdvisorAutoProxyCreator.getAdvicesAndAdvisorsForBean(AbstractAdvisorAutoProxyCreator.java:69) ~[spring-aop-4.3.4.RELEASE.jar:4.3.4.RELEASE]
	at org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator.wrapIfNecessary(AbstractAutoProxyCreator.java:347) ~[spring-aop-4.3.4.RELEASE.jar:4.3.4.RELEASE]
	at org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator.postProcessAfterInitialization(AbstractAutoProxyCreator.java:299) ~[spring-aop-4.3.4.RELEASE.jar:4.3.4.RELEASE]
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyBeanPostProcessorsAfterInitialization(AbstractAutowireCapableBeanFactory.java:422) ~[spring-beans-4.3.4.RELEASE.jar:4.3.4.RELEASE]
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1588) ~[spring-beans-4.3.4.RELEASE.jar:4.3.4.RELEASE]
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:553) ~[spring-beans-4.3.4.RELEASE.jar:4.3.4.RELEASE]
	... 54 common frames omitted

Looking at the stack trace, the problem is caused by AspectJExpressionPointCut passing the system classloader to AspectJ instead of the correct one. The reason for this is, that the pointcut's beanFactory field is always null, and not set to the actual bean factory.
The cause of this problem seems to be that AspectJExpressionPointCut.setBeanFactory is never called when the PointCut is created by Spring for AspectJ-style annotation advices (@Aspect, @Around, etc). Otherwise, the Pointcut would pick up the correct, dynamically created classloader.

A fix for this problem shoud call AspectJExpressionPointCut.setBeanFactory for the newly created pointcut, somewhere around ReflectiveAspectJAdvisorFactory.getPointcut. where the pointcut is created.
Maybe the pointcut should be obtained as prototype bean from the factory instead of being directly instantiated.

I can provide a sample project demonstrating the error, if requested.


Affects: 4.3.4

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
2 participants
You can’t perform that action at this time.