spring-projects / spring-framework

Spring Framework
https://spring.io/projects/spring-framework
Apache License 2.0
56.51k stars 38.11k forks source link

Consider allowing to exclude some beans from AOT processed applications #29484

Open philwebb opened 1 year ago

philwebb commented 1 year ago

See https://github.com/spring-projects/spring-boot/issues/32262 for background.

Currently we have a number of areas where we want to exclude beans from being used in AOT processed applications. There are a number of ways we currently do this.

It would be nice if we could review these existing usages and see if we can find a common way to perform exclusions.

wilkinsona commented 1 year ago

https://github.com/spring-projects/spring-boot/issues/33374 is another example of beans that aren't needed after AOT processing.

sdeleuze commented 1 year ago

I tentatively schedule this issue for Spring Framework 6.1.0-M1 along to #29555 as they are related and it is important to move forward on this topic.

dsyer commented 1 year ago

Can this be implemented in a way that doesn't require me to use an annotation? I might want to manage bean definitions for classes that I didn't write or have no control over the annotations on. E.g. register bean definitions with a well-known attribute that says "I have a supplier already, you don't need to generate any code for me". I can already do this kind of manually, and it works in my use case, by registering a BeanRegistrationExcludeFilter in aot.factories. Example:

public class ExcludeFilter implements BeanRegistrationExcludeFilter {

    static final String IGNORE_ME = "ignore.me";

    @Override
    public boolean isExcludedFromAotProcessing(RegisteredBean registeredBean) {
        if (registeredBean.getMergedBeanDefinition().hasAttribute(IGNORE_ME)) {
            return true;
        }
        return false;
    }

}
sdeleuze commented 1 year ago

I also would like to avoid making annotation mandatory to manage this kind of concept, just not sure yet what we should use. See also use case in #29555 where annotation may not be ideal. I will discuss with @jhoeller the related design we should use.

mmarimuthu commented 6 months ago

I tried applying filter as suggested by @dsyer but no luck. let me know if the implementation is wrong.

public class CloudFunctionSample implements Function<Map<String, Object>, Map<String, Object>> {

    private String hasAttribute = "ignore.me";
...
}

Main:

// other annotations
@SpringBootConfiguration
@ComponentScan(basePackages = { "com.myorg" }, excludeFilters = @ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE, classes = ExcludeFilter.class))
public class CredentialingJobApplication implements ApplicationContextInitializer<GenericApplicationContext> {

    public static void main(String[] args) {
        FunctionalSpringApplication app = new FunctionalSpringApplication(CredentialingJobApplication.class);
        app.run(args);
    }

    @Override
      public void initialize(GenericApplicationContext context) {
        context.registerBean("cloudFunctionOne", FunctionRegistration.class,
            () -> new FunctionRegistration<>(new CloudFunctionSample())
                .type(FunctionTypeUtils.functionType(Map.class, Map.class)));
      }
}
dsyer commented 6 months ago

You didn't really show a complete sample. Maybe if you post a minimal reproducer we could inspect it and decide one way or the other? It doesn't look like you add the "ignore.me" attribute to your bean definition (I assume it is the FunctionRegistration)?

snicoll commented 6 months ago

@mmarimuthu please stop asking the same question on multiple issue trackers. Refer to StackOverflow or the documentation.

mmarimuthu commented 6 months ago

@snicoll I apologize for the concern. I will try to improve.

@dsyer here is the sample

@ aot-issue.zip

snicoll commented 3 months ago

@dsyer yes, as of 6.2, you can set BeanRegistrationAotProcessor.IGNORE_REGISTRATION_ATTRIBUTE to true on the bean definition. I think this issue is really about two different things. There is the cases where a bean is excluded, and there's the case where a component that register beans is invoked twice. These are fairly different and, while I think we've made so good progress for the former, we really didn't for the latter.