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

@Lazy injection point is resolved from BeanFactory for every invocation on proxy #28173

Closed
kevin-wang001 opened this issue Mar 13, 2022 · 2 comments
Assignees
Labels
in: core Issues in core modules (aop, beans, core, context, expression) status: declined A suggestion or change that we don't feel we should currently apply

Comments

@kevin-wang001
Copy link

kevin-wang001 commented Mar 13, 2022

I found that, when I use @Lazy on @Resource fields, Spring injects a lazy proxy.

The lazy proxy's TargetSource is not static, so every time I invoke a method on the lazy proxy, it calls beanFactory.resolveDependency() to resolve the target object.

Why doesn't Spring set the lazy proxy's TargetSource to static?

If so, it will be faster when invoking the lazy proxy's methods.

For example, in CommonAnnotationBeanPostProcessor:

protected Object buildLazyResourceProxy(final LookupElement element, final @Nullable String requestingBeanName) {
    TargetSource ts = new TargetSource() {
        @Override
        public Class<?> getTargetClass() {
            return element.lookupType;
        }
        @Override
        public boolean isStatic() {
            // this place: why not use "true"?
            return false;
        }
        @Override
        public Object getTarget() {
            return getResource(element, requestingBeanName);
        }
        @Override
        public void releaseTarget(Object target) {
        }
    };

// ...

} 
@spring-projects-issues spring-projects-issues added the status: waiting-for-triage An issue we've not yet triaged or decided on label Mar 13, 2022
@sbrannen sbrannen added the in: core Issues in core modules (aop, beans, core, context, expression) label Mar 13, 2022
@sbrannen sbrannen changed the title @Lazy has performance problem? @Lazy field is resolved from BeanFactory for every method invocation Mar 13, 2022
@sbrannen sbrannen changed the title @Lazy field is resolved from BeanFactory for every method invocation @Lazy injection point is resolved from BeanFactory for every method invocation on proxy Mar 13, 2022
@sbrannen sbrannen changed the title @Lazy injection point is resolved from BeanFactory for every method invocation on proxy @Lazy injection point is resolved from BeanFactory for every invocation on proxy Mar 13, 2022
@sbrannen sbrannen added this to the Triage Queue milestone Mar 13, 2022
@sbrannen
Copy link
Member

Why doesn't Spring set the lazy proxy's TargetSource to static?

That's a good question. I imagine that having a static TargetSource (which caches the resolved target bean) might make sense if the underlying bean is a singleton, but I may be overlooking something.

While looking into this issue, I noticed another issue which I reported in #28176.

The team will investigate both of these related issues.


As a side note, please note that this issue applies not only to @Lazy @Resource fields but also to @Lazy @Autowired injection points. Thus, this issue applies to both CommonAnnotationBeanPostProcessor.buildLazyResourceProxy(...) and ContextAnnotationAutowireCandidateResolver.buildLazyResolutionProxy(...).

@sbrannen
Copy link
Member

The reason that CommonAnnotationBeanPostProcessor and ContextAnnotationAutowireCandidateResolver both build a proxy for a @Lazy injection point with a non-static TargetSource is in order to allow the BeanFactory to dynamically determine how the bean is resolved. This is true even for singleton target beans in order to support edge cases where a BeanDefinition may have been removed since the last time the proxy was invoked.

In light of that, the team has decided to close this issue as "works as designed".

However, if you discover that the use of a non-static TargetSource in such cases leads to a performance bottleneck for a real application, please provide a sample project that reproduces the issue.

Thanks

@sbrannen sbrannen removed this from the Triage Queue milestone Mar 15, 2022
@sbrannen sbrannen added status: declined A suggestion or change that we don't feel we should currently apply and removed status: waiting-for-triage An issue we've not yet triaged or decided on labels Mar 15, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
in: core Issues in core modules (aop, beans, core, context, expression) status: declined A suggestion or change that we don't feel we should currently apply
Projects
None yet
Development

No branches or pull requests

3 participants