Application Context へのさまざまな Bean 登録の方法

様々な Bean 登録の方法を確認する。

今回の検証内容のリポジトリ


まずはベーシックな @ComponentScan により Application context に登録する方法。

public static void main(String[] args) {

    var context = new AnnotationConfigApplicationContext(ConfigurationComponentScan.class);
    var bean1 = context.getBean(Bean1.class);

    bean1.sayHello();
}
@ComponentScan
public class ConfigurationComponentScan {
}

ちなみに Spring Boot を使用した時は @SpringBootApplication に @ComponentScan が設定されている。

@SpringBootApplication
public class DemoApplication {

    public static void main(String[] args) {
        SpringApplication.run(DemoApplication.class, args);
    }
}
@ComponentScan(excludeFilters = { @Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class),
        @Filter(type = FilterType.CUSTOM, classes = AutoConfigurationExcludeFilter.class) })
public @interface SpringBootApplication {

次は、Configuration class をつかって Bean登録をする。

public static void main(String[] args) {
    var context = new AnnotationConfigApplicationContext(AppConfig.class);
    var bean1 = context.getBean(Bean1.class);

    bean1.sayHello();
}
@Configuration
public class AppConfig {
    @Bean
    public Bean1 getBean1() {
        return new Bean1();
    }

    @Bean
    public Bean2 getBean2() {
        return new Bean2();
    }

    @Bean
    public Bean3 getBean3() {
        return new Bean3();
    }
}

この @Configuration に @Component が設定されているので、 Configuration class も DIコンテナにて管理される。

@Component
public @interface Configuration {

次は、 Application Context を作成時に、スキャンしたいコンポーネントのパッケージを指定するパターン。

public static void main(String[] args) {
    var context = new AnnotationConfigApplicationContext("com.kiyotakeshi.bean.creation.beans");

    var bean1 = context.getBean(Bean1.class);

    bean1.sayHello();
}

可変長引数をとるので、複数のパッケージを指定することが可能。

ただし String で受け取るので型によるチェックがないため、 typo に注意。

AnnotationConfigApplicationContext のコンストラクタに渡した引数を scan している。

public AnnotationConfigApplicationContext(String... basePackages) {
    this();
    scan(basePackages);
    refresh();
}

次は、 scan メソッドにパッケージを指定するパターン。

public static void main(String[] args) {
    AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();

    context.scan("com.kiyotakeshi.bean.creation.beans");
    context.refresh();

    Bean1 bean = context.getBean(Bean1.class);

    bean.sayHello();
}

次は、設定ファイルから読み取るパターン。

public static void main(String[] args) {
    var context = new ClassPathXmlApplicationContext("/beans.xml");
    var bean1 = context.getBean(Bean1.class);
    
    bean1.sayHello();
}

public static void main(String[] args) {
    String beansXmlLocationOnFilesystem = FileSystemXmlApplicationContextExample.class.getResource("/beans.xml").toExternalForm();

    var context = new FileSystemXmlApplicationContext(beansXmlLocationOnFilesystem);

    var bean1 = context.getBean(Bean1.class);

    bean1.sayHello();
}

xml に定義した設定で DI コンテナにBean登録できる。 xml の定義名のマッピングが必要(typo にも注意しなければならない)。

<!-- src/main/resources/beans.xml -->
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans.xsd">

    <bean id="bean1" class="com.kiyotakeshi.bean.creation.beans.Bean1">
        <!-- Bean1 class の attribute である private Bean2 bean2; に対応 -->
        <property name="bean2" ref="bean2"/>
        <property name="bean3" ref="bean3"/>
    </bean>

    <bean id="bean2" class="com.kiyotakeshi.bean.creation.beans.Bean2"/>

    <bean id="bean3" class="com.kiyotakeshi.bean.creation.beans.Bean3"/>

</beans>