javaspringminecraftspring-annotationsspring-ioc

Spring doesn't scan classes annotated with @Component/@Service etc


I have an application in java 21 that is a minecraft spigot plugin. I use spring framework 6.1.10. These are my dependencies:

        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-core</artifactId>
            <version>6.1.10</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>6.1.10</version>
        </dependency>

That is my plugin main class:

package xyz.abc;

import org.mineacademy.fo.Common;
import org.mineacademy.fo.plugin.SimplePlugin;
import org.mineacademy.fo.remain.Remain;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import xyz.abc.commands.CommandTest;

public class SparkCore extends SimplePlugin {

    @Override
    protected void onPluginStart() {
        ApplicationContext applicationContext = new AnnotationConfigApplicationContext(SpringConfig.class);
        Common.log("Available beans:");
        for (String beanName : applicationContext.getBeanDefinitionNames()) {
            Common.log(beanName);
        }
        Remain.registerCommand(applicationContext.getBean(CommandTest.class));
    }
}

This is my Spring config:

package xyz.abc;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;

@Configuration
@ComponentScan(basePackages = "xyz.abc")
public class SpringConfig {

    @Bean
    Test test() {
        return new Test("Test");
    }
}

And this is CommandTest annotated with @Component

package xyz.abc.commands;

import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
import org.mineacademy.fo.command.SimpleCommand;
import org.mineacademy.fo.menu.model.ItemCreator;
import org.mineacademy.fo.remain.CompMaterial;
import org.springframework.stereotype.Component;
import xyz.abc.Test;

@Component
public final class CommandTest extends SimpleCommand {

    private static final ItemStack wing = ItemCreator.of(CompMaterial.DIAMOND)
            .modelData(2).make();

    public CommandTest(Test test) {
        super("test|test2");
        System.out.println(test.name());
    }

    @Override
    protected void onCommand() {
        System.out.println(12);
        checkConsole();
        Player player = getPlayer();
    }
}

As you could see onPluginLoad print all available beans and this is result:

[22:16:42 INFO]: Available beans:
[22:16:42 INFO]: org.springframework.context.annotation.internalConfigurationAnnotationProcessor
[22:16:42 INFO]: org.springframework.context.annotation.internalAutowiredAnnotationProcessor
[22:16:42 INFO]: org.springframework.context.annotation.internalCommonAnnotationProcessor
[22:16:42 INFO]: org.springframework.context.annotation.internalPersistenceAnnotationProcessor
[22:16:42 INFO]: org.springframework.context.event.internalEventListenerProcessor
[22:16:42 INFO]: org.springframework.context.event.internalEventListenerFactory
[22:16:42 INFO]: springConfig
[22:16:42 INFO]: test

But then I get an error:

[22:31:37 INFO]: org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'xyz.abc.commands.CommandTest' available

As you can see bean named "test" has been initialized by @Bean annotation in configuration but class CommandTest annoteted with @Component has not.

I don't know what am I supposed to do with that.


Solution

  • Here is the answer: Spring @ComponentScan does not scan

    To Summarize, I've just added Thread.currentThread().setContextClassLoader(getClassLoader()); In my onPluginStart method.