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 aspect not correctly applied to Java 8 lambda-defined @Beans [SPR-11807] #16427

Closed
spring-projects-issues opened this issue May 19, 2014 · 7 comments
Assignees
Labels
in: core type: enhancement
Milestone

Comments

@spring-projects-issues
Copy link
Collaborator

@spring-projects-issues spring-projects-issues commented May 19, 2014

Josh Long opened SPR-11807 and commented

In the example below, I define an aspect which I expect to be applied to all beans of type CommandLineRunner, it isn't if the bean is defined as a lambda on java version "1.8.0_05" on OSX.

(java version "1.8.0_05"
Java(TM) SE Runtime Environment (build 1.8.0_05-b13)
Java HotSpot(TM) 64-Bit Server VM (build 25.5-b02, mixed mode))


package demo;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.boot.CommandLineRunner;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.*;
import org.springframework.stereotype.Component;

@Configuration
@ComponentScan
@EnableAspectJAutoProxy
public class Application {


    /*   @Bean
       CommandLineRunner good() {
           return new CommandLineRunner() {
               @Override
               public void run(String... args) throws Exception {
                   System.out.println(String.join(",", args));
               }
           };
       }
   */
    @Bean
    CommandLineRunner bad() {
        return (args) -> System.out.println(String.join(",", args));
    }

    public static void main(String[] args) throws Exception {

        ApplicationContext applicationContext = new AnnotationConfigApplicationContext(Application.class);

        applicationContext.getBeansOfType(CommandLineRunner.class).forEach((k, v) -> System.out.println(k + '=' + v));

        for (int i = 0; i < 4; i++) {
            applicationContext.getBeansOfType(CommandLineRunner.class).forEach((k, v) -> {
                try {
                    v.run(args);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            });
        }
    }
}

@Component
@Aspect
class WrappingAspect {

    @After("execution(* org.springframework.boot.CommandLineRunner.*(..))")
    public void after(JoinPoint joinPoint) {
        System.out.println("invoked after " + joinPoint.toLongString());
    }

}

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>

	<groupId>org.demo</groupId>
	<artifactId>demo</artifactId>
	<version>0.0.1-SNAPSHOT</version>

	<name>demo</name>
	<description>Demo project</description>

	<parent>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-parent</artifactId>
		<version>1.0.2.RELEASE</version>
		<relativePath/> <!-- lookup parent from repository -->
	</parent>


	<dependencies>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-aop</artifactId>
        </dependency>


		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-test</artifactId>
			<scope>test</scope>
		</dependency>
	</dependencies>

	<properties>
        <spring.version>4.0.4.RELEASE</spring.version>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
		<start-class>demo.Application</start-class>
		<java.version>1.8</java.version>
	</properties>
 

</project>

Affects: 4.0.4

Issue Links:

  • #15303 Inferring an ApplicationListener's event type from a lambda or method reference
  • #17130 GenericTypeResolver should be able to introspect generic arguments from lambdas

1 votes, 9 watchers

@spring-projects-issues
Copy link
Collaborator Author

@spring-projects-issues spring-projects-issues commented Dec 2, 2014

Nick Williams commented

Is this still planned for being fixed in Spring 4.2?

@spring-projects-issues
Copy link
Collaborator Author

@spring-projects-issues spring-projects-issues commented Dec 2, 2014

Stéphane Nicoll commented

Nick, the fix version is set so that's the current plan yes (same answer for your other comment).

@spring-projects-issues
Copy link
Collaborator Author

@spring-projects-issues spring-projects-issues commented May 7, 2015

Juergen Hoeller commented

This turns out to be a problem in AspectJ's PointcutExpressionImpl:

public boolean couldMatchJoinPointsInType(Class aClass) {
    ResolvedType matchType = world.resolve(aClass.getName());

Instead of using the given Class reference, it tries to re-resolve it by name within its own abstraction. And lambda-defined classes can't be resolved/loaded that way; they only have the Class reference itself.

Within AspectJ, this means it'll end up with a MissingResolvedTypeWithKnownSignature for the match type which eventually leads to a ReflectionWorldException:

org.aspectj.weaver.reflect.ReflectionWorld$ReflectionWorldException: warning can't determine modifiers of missing type org.springframework.context.annotation.configuration.ConfigurationClassAspectIntegrationTests$Application$$Lambda$1.793315160
 [Xlint:cantFindType]

Andy Clement, do you see an easy way out here?

Juergen

@spring-projects-issues
Copy link
Collaborator Author

@spring-projects-issues spring-projects-issues commented May 7, 2015

Juergen Hoeller commented

I'll commit the test that I was using for this, marking it as ignored for the time being: ConfigurationClassAspectIntegrationTests.withInnerClassAndLambdaExpression

Juergen

@spring-projects-issues
Copy link
Collaborator Author

@spring-projects-issues spring-projects-issues commented May 7, 2015

Andy Clement commented

I'll look out for that test appearing and dive into a bit. I have some thoughts on how we can get this to work (obviously with changes to AspectJ).

@spring-projects-issues
Copy link
Collaborator Author

@spring-projects-issues spring-projects-issues commented May 26, 2015

Andy Clement commented

I have a fix for this coming in AspectJ 1.8.6 (due soon) - it passes the test case included in ConfigurationClassAspectIntegrationTests. Work done under this AspectJ issue: https://bugs.eclipse.org/bugs/show_bug.cgi?id=468351

@spring-projects-issues
Copy link
Collaborator Author

@spring-projects-issues spring-projects-issues commented Jun 10, 2015

Juergen Hoeller commented

Resolved through an upgrade to AspectJ 1.8.6 as the suggested version in our POMs.
Applications explicitly an declaring AspectJ version need to follow that upgrade for this to work.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
in: core type: enhancement
Projects
None yet
Development

No branches or pull requests

2 participants