Skip to content

Fix MapperFactoryBean constructor argument for AOT#1235

Open
DragonFSKY wants to merge 1 commit intomybatis:3.0.xfrom
DragonFSKY:fix-aot-mapper-constructor-arg-3.0
Open

Fix MapperFactoryBean constructor argument for AOT#1235
DragonFSKY wants to merge 1 commit intomybatis:3.0.xfrom
DragonFSKY:fix-aot-mapper-constructor-arg-3.0

Conversation

@DragonFSKY
Copy link
Copy Markdown

This PR fixes an AOT/native runtime failure where MapperFactoryBean tries to resolve Class<?> as an autowired dependency.

ClassPathMapperScanner currently registers the mapper interface constructor argument as a class name String. This works in the regular JVM path because Spring can convert the value to the Class<?> constructor argument required by MapperFactoryBean.

In the AOT/native path, the generated bean supplier uses the MapperFactoryBean(Class<?>) constructor, but the bean definition still contains the mapper interface constructor argument as a String. The generated supplier does not appear to apply the same String to Class<?> conversion, so native runtime fails with:

No qualifying bean of type 'java.lang.Class<?>' available

This change uses the resolved mapper interface Class<?> as the constructor argument only when the configured MapperFactoryBean has a single-argument constructor that can accept Class<?> and does not have a single-argument constructor that can accept String.

This preserves the existing String constructor argument behavior for custom MapperFactoryBean implementations that support String-compatible constructors.

Regression tests were added for the default MapperFactoryBean, a custom factory with a String constructor, and a custom factory with both String and Class<?> constructors.

The same constructor argument registration path also exists on master, so this fix may need to be forward-ported if maintainers prefer to keep the branches aligned.

Tested with:

./mvnw -Dtest=MapperScannerConfigurerTest -Dformatter.skip=true -Dwhitespace.skip=true -Dlicense.skip=true -Djacoco.skip=true -Drewrite.skip=true test

Also verified with a native reproduction project:

https://github.com/DragonFSKY/mybatis-3675-repro

Refs #929.
Refs mybatis/mybatis-3#3675.

@DragonFSKY
Copy link
Copy Markdown
Author

I also checked the same code path against current master locally.

Using mybatis-spring 4.0.1-SNAPSHOT built from origin/master with Spring Boot 4.0.6, the generated AOT bean registration still contains the mapper constructor argument as a String while the generated supplier uses the MapperFactoryBean(Class<?>) constructor.

After bypassing the separate duplicate-scan issue with spring.main.allow-bean-definition-overriding=true, the same failure is reproducible in JVM AOT mode:

No qualifying bean of type 'java.lang.Class<?>' available

Applying the same fix changes the generated constructor argument from the mapper interface name string to the mapper interface class literal, for example:

beanDefinition.getConstructorArgumentValues()
    .addGenericArgumentValue(DictionaryMapper.class);

With that change, the same AOT run succeeds and prints:

dictionary count=1

So this PR targets 3.0.x because that is the affected release line reported in #929, but the same fix likely needs to be forward-ported to master as well.

Use the resolved mapper interface class as the constructor argument when the configured MapperFactoryBean expects a Class-based constructor.

Keep the existing String constructor argument for custom MapperFactoryBean implementations that support String-compatible constructors to preserve backward compatibility.
@coveralls
Copy link
Copy Markdown

Coverage Status

coverage: 90.316% (+0.07%) from 90.242% — DragonFSKY:fix-aot-mapper-constructor-arg-3.0 into mybatis:3.0.x

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants