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

@EnableLoadTimeWeaving does not work for spring beans annotated by @Component, @Configuration, etc. #26851

Closed
pop1213 opened this issue Apr 23, 2021 · 13 comments
Labels
in: core Issues in core modules (aop, beans, core, context, expression)

Comments

@pop1213
Copy link

pop1213 commented Apr 23, 2021

Affects: Spring Framework 5.3.4

When I use the @EnableLoadTimeWeaving annotation, beans will not be woven, but using XML configuration <context:load-time-weaver/> can be successfully woven.

Here's a snippet that use @EnableLoadTimeWeaving annotation:

@ComponentScan({"com.example.demo","foo"})
@EnableLoadTimeWeaving
public class LwtStart {
    public static void main(String[] args) {
        AnnotationConfigApplicationContext ctx=new AnnotationConfigApplicationContext(LwtStart.class);
        //ClassPathXmlApplicationContext ctx=new ClassPathXmlApplicationContext("beans.xml");
        //a bean annotated by @Component
        EntitlementCalculationService service1=ctx.getBean(EntitlementCalculationService.class);
        service1.calculateEntitlement();
        
        
        //A simple object that is not managed by the Spring container ,not annotated by @Component
        EntitlementCalculationService service2=new MyEntitlementCalculationService();
        //For comparison,to prove load-time-weaver takes effect
        service2.calculateEntitlement();
    }
}

aop.xml

<aspectj>
    <weaver options="-debug">
        <!-- only weave classes in our application-specific packages -->
        <include within="foo.*"/>
        <include within="com.example.demo.ltw.aspect.*"/>
    </weaver>

    <aspects>
        <!-- weave in just this aspect -->
        <aspect name="com.example.demo.ltw.aspect.ProfilingAspect"/>
    </aspects>
</aspectj>

the aspect

@Around("methodsToBeProfiled()")
public Object profile(ProceedingJoinPoint pjp) throws Throwable {
    StopWatch sw = new StopWatch(getClass().getSimpleName());
    try {
        System.out.println(pjp.getTarget());
        sw.start(pjp.getSignature().getName());
        return pjp.proceed();
    } finally {
        sw.stop();
        System.out.println(sw.prettyPrint());
    }
}

@Pointcut("execution(public * foo.*.*(..))")
public void methodsToBeProfiled(){}

In this simple case, the EntitlementCalculationService object that was successfully woven will print the execution time . As mentioned before, service2 prints the execution time, service1 does not, proving that it was not successfully woven.

When switching to the XML configuration method, both service1 and service2 can be successfully woven, and they can both print the execution time.

// AnnotationConfigApplicationContext ctx=new AnnotationConfigApplicationContext(LwtStart.class);
ClassPathXmlApplicationContext ctx=new ClassPathXmlApplicationContext("beans.xml");

EntitlementCalculationService service1=ctx.getBean(EntitlementCalculationService.class);
service1.calculateEntitlement();

EntitlementCalculationService service2=new MyEntitlementCalculationService();
service2.calculateEntitlement();
<!-- a service object; we will be profiling its methods -->
<bean id="entitlementCalculationService"
      class="foo.StubEntitlementCalculationService"/>

<!-- this switches on the load-time weaving -->
<context:load-time-weaver aspectj-weaving="on"/>

When using Java configuration, the AspectJWeavingEnabler.enableAspectJWeaving method will not be called until Spring loads the bean classes, which seems to be the reason why @EnableLoadTimeWeaving does not take effect.

@spring-projects-issues spring-projects-issues added the status: waiting-for-triage An issue we've not yet triaged or decided on label Apr 23, 2021
@pop1213
Copy link
Author

pop1213 commented Apr 23, 2021

spring-ltw.zip

@sbrannen
Copy link
Member

This appears to be a duplicate of #26199.

I am therefore closing this issue.

If you find that the issue still exists after upgrading to Spring Framework 5.3.5 or 5.3.6, please post back here as a comment, and we will investigate further.

@sbrannen sbrannen added in: core Issues in core modules (aop, beans, core, context, expression) status: duplicate A duplicate of another issue and removed status: waiting-for-triage An issue we've not yet triaged or decided on labels Apr 23, 2021
@pop1213
Copy link
Author

pop1213 commented Apr 24, 2021

This appears to be a duplicate of #26199.

I am therefore closing this issue.

If you find that the issue still exists after upgrading to Spring Framework 5.3.5 or 5.3.6, please post back here as a comment, and we will investigate further.

After I upgraded Spring to the latest version(5.3.6), this problem still exists. Although the bean class is not loaded earlier in the ConfigurationClassPostProcessor, it is still before AspectJWeavingEnabler.enableAspectJWeaving method is called(As far as I know, it is the key code that causes the load time weaver to work).

I found through debug mode that in the process of instantiating LoadTimeWeavingConfiguration, it will call the DefaultListableBeanFactory#doGetBeanNamesForType
method when it resolves dependencies, which will cause all bean classes to be loaded in advance.

private String[] doGetBeanNamesForType(ResolvableType type, boolean includeNonSingletons, boolean allowEagerInit) {
		List<String> result = new ArrayList<>();

		// Check all bean definitions.
		for (String beanName : this.beanDefinitionNames) {
			// Only consider bean as eligible if the bean name is not defined as alias for some other bean.
			if (!isAlias(beanName)) {
				try {
					RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
					// Only check bean definition if it is complete.
					if (!mbd.isAbstract() && (allowEagerInit ||
							(mbd.hasBeanClass() || !mbd.isLazyInit() || isAllowEagerClassLoading()) &&
									!requiresEagerInitForType(mbd.getFactoryBeanName()))) {
//**************************This line of code will cause other bean classes to be loaded*******************                      
						boolean isFactoryBean = isFactoryBean(beanName, mbd);

I think this may be the cause of the load time weaver not working. Hope to get your reply , thank you very much.

@pop1213
Copy link
Author

pop1213 commented Apr 26, 2021

@sbrannen

@snicoll snicoll reopened this Apr 27, 2021
@sbrannen sbrannen added status: waiting-for-triage An issue we've not yet triaged or decided on type: regression A bug that is also a regression and removed status: duplicate A duplicate of another issue labels Apr 27, 2021
@sbrannen
Copy link
Member

sbrannen commented Apr 27, 2021

After I upgraded Spring to the latest version(5.3.6), this problem still exists.

Thanks for looking into it and providing feedback.

We have reopened this issue and will investigate the cause.

@sbrannen sbrannen removed the status: waiting-for-triage An issue we've not yet triaged or decided on label Apr 27, 2021
@sbrannen sbrannen added this to the 5.3.7 milestone Apr 27, 2021
@sbrannen
Copy link
Member

When I use the @EnableLoadTimeWeaving annotation, beans will not be woven, but using XML configuration <context:load-time-weaver/> can be successfully woven.

Did it work for your application using @EnableLoadTimeWeaving in a version of Spring Framework prior to 5.3.4?

If so, which version?

@sbrannen sbrannen added status: waiting-for-feedback We need additional information before we can continue status: waiting-for-triage An issue we've not yet triaged or decided on and removed type: regression A bug that is also a regression labels Apr 27, 2021
@sbrannen sbrannen removed this from the 5.3.7 milestone Apr 27, 2021
@pop1213
Copy link
Author

pop1213 commented Apr 27, 2021

When I use the @EnableLoadTimeWeaving annotation, beans will not be woven, but using XML configuration <context:load-time-weaver/> can be successfully woven.

Did it work for your application using @EnableLoadTimeWeaving in a version of Spring Framework prior to 5.3.4?

If so, which version?

Sorry, I haven't tried any version before 5.3.4 so far

@spring-projects-issues spring-projects-issues added status: feedback-provided Feedback has been provided and removed status: waiting-for-feedback We need additional information before we can continue labels Apr 27, 2021
@sbrannen
Copy link
Member

Sorry, I haven't tried any version before 5.3.4 so far

OK. Thanks for the feedback.

I was asking in order to confirm if this is a "regression", but since you don't know that we might discover that this scenario never worked.

@fsgonz
Copy link
Contributor

fsgonz commented Jun 13, 2022

@sbrannen I think there was a problem in this commit.
You are not taking into account the includeNonSingletons parameter after this change. The same that was mentioned above.

Is there a rationale for that or is it a bug? we have a change of behavior because of this.
Is this still opened?

This verification was missed I think.

@sbrannen
Copy link
Member

Please note that #28616 has been resolved for Spring Framework 5.3.21, scheduled for release later this week.

@pop1213, please let us know if the fix in #28616 also resolves your issue.

@sbrannen sbrannen added status: waiting-for-feedback We need additional information before we can continue and removed status: feedback-provided Feedback has been provided labels Jun 14, 2022
@spring-projects-issues
Copy link
Collaborator

If you would like us to look at this issue, please provide the requested information. If the information is not provided within the next 7 days this issue will be closed.

@spring-projects-issues spring-projects-issues added the status: feedback-reminder We've sent a reminder that we need additional information before we can continue label Jun 21, 2022
@spring-projects-issues
Copy link
Collaborator

Closing due to lack of requested feedback. If you would like us to look at this issue, please provide the requested information and we will re-open the issue.

@spring-projects-issues spring-projects-issues removed status: waiting-for-feedback We need additional information before we can continue status: feedback-reminder We've sent a reminder that we need additional information before we can continue status: waiting-for-triage An issue we've not yet triaged or decided on labels Jun 28, 2022
@pdeneve
Copy link
Contributor

pdeneve commented Aug 14, 2023

Please note that #28616 has been resolved for Spring Framework 5.3.21, scheduled for release later this week.

@pop1213, please let us know if the fix in #28616 also resolves your issue.

@sbrannen The issue is not resolved in Spring Framework 5.3.21. It can be reproduced by cloning this repo, checking out branch 5.3.21 and running mvn test -pl spring.ltw.

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)
Projects
None yet
Development

No branches or pull requests

6 participants