6.

【Spring】@Componentアノテーションとは

編集
この記事の要点
  • @ComponentSpring コンテナにクラスを Bean として登録する汎用アノテーション
  • @Service / @Repository / @Controller はこの特殊化版(意味付き)
  • @ComponentScan の範囲内でないと登録されない
  • 名前はクラス名の先頭小文字がデフォルト: UserHelperuserHelper
  • 明示する場合: @Component("customName")

 

@Component の役割

クラスに @Component を付けると Spring が自動的にインスタンス化してコンテナに Bean として登録します。他のクラスから @Autowired で注入できるようになります。

基本的な使い方

@Component
public class MailSender {
    public void send(String to, String body) { ... }
}

// 別の Bean から注入
@Service
public class NotificationService {
    private final MailSender mailSender;

    public NotificationService(MailSender mailSender) {  // 自動注入
        this.mailSender = mailSender;
    }
}

@Component と他のステレオタイプ

Spring には 4 つのステレオタイプアノテーションがあり、すべて @Component から派生:

アノテーション用途追加機能
@Component汎用 Bean
@Serviceビジネスロジック層意味付け(機能は @Component と同等)
@Repositoryデータアクセス層DB 例外を DataAccessException に変換
@ControllerWeb MVC コントローラSpring MVC ハンドラとして認識
@RestControllerREST API コントローラ@Controller + @ResponseBody
@ConfigurationJavaConfig クラス@Bean メソッドの登録

意味的に他のが当てはまるならそちらを使い、当てはまらないなら @Component を使う、というのが習慣です。

Bean 名のカスタマイズ

デフォルト名はクラス名の先頭小文字:

@Component
public class UserHelper { ... }
// → Bean 名: "userHelper"

// 明示
@Component("myHelper")
public class UserHelper { ... }
// → Bean 名: "myHelper"

// @Qualifier で名前指定して注入
public Foo(@Qualifier("myHelper") UserHelper helper) { ... }

スコープ(ライフサイクル)

// デフォルト: シングルトン(アプリ全体で 1 インスタンス)
@Component
public class CacheService { ... }

// プロトタイプ(注入されるたびに新インスタンス)
@Component
@Scope("prototype")
public class TaskWorker { ... }

// Web リクエストごと
@Component
@Scope(value = "request", proxyMode = ScopedProxyMode.TARGET_CLASS)
public class RequestContext { ... }

// セッションごと
@Component
@Scope(value = "session", proxyMode = ScopedProxyMode.TARGET_CLASS)
public class UserSession { ... }

初期化と破棄

@Component
public class ConnectionPool {

    @PostConstruct
    public void init() {
        // インスタンス化 + 注入完了後に呼ばれる
        System.out.println("Initializing connection pool...");
    }

    @PreDestroy
    public void cleanup() {
        // コンテナ終了時に呼ばれる
        System.out.println("Closing connection pool...");
    }
}

条件付き Bean 登録

// プロファイルで切替
@Component
@Profile("prod")
public class ProductionConfig { ... }

@Component
@Profile({"dev", "test"})
public class DevConfig { ... }

// 条件式
@Component
@ConditionalOnProperty(name = "feature.enabled", havingValue = "true")
public class FeatureService { ... }

@Component
@ConditionalOnClass(name = "javax.mail.MessagingService")
public class MailService { ... }

@ComponentScan の範囲

@Component が認識されるには、@ComponentScan のスキャン範囲内である必要があります:

@SpringBootApplication  // 内部で @ComponentScan を含む
public class MyApp { ... }
// → メインクラスのパッケージ以下を自動スキャン

// 明示
@SpringBootApplication(scanBasePackages = {"com.example", "com.other"})

// または
@ComponentScan(basePackages = "com.example")

// 除外
@ComponentScan(
    basePackages = "com.example",
    excludeFilters = @Filter(type = FilterType.ANNOTATION, classes = Service.class)
)

@Component vs @Bean の使い分け

状況使うもの
自分で書いたクラス@Component をクラスに付与
サードパーティのクラス@Configuration + @Bean メソッド
初期化に複雑なロジックが必要@Bean メソッド
条件付きで複数 Bean@Bean + @Conditional
@Configuration
public class AppConfig {

    @Bean
    public RestTemplate restTemplate() {
        // サードパーティクラスを Bean として登録
        return new RestTemplate();
    }

    @Bean
    public DataSource dataSource(@Value("${db.url}") String url) {
        HikariConfig config = new HikariConfig();
        config.setJdbcUrl(url);
        return new HikariDataSource(config);
    }
}

関連記事

編集
Post Share
子ページ

子ページはありません

同階層のページ
  1. @After
  2. @Autowired
  3. @Bean
  4. @Before
  5. @Column
  6. @Component
  7. @Configuration
  8. @Controller
  9. @Data
  10. @Entity
  11. @GeneratedValue
  12. @Id
  13. @Modifying
  14. @PathVariable
  15. @PropertySource
  16. @Repository
  17. @RequestBody
  18. @RequestMapping
  19. @ResponseBody
  20. @RestController
  21. @Service
  22. @SpringBootApplication
  23. @Table
  24. @Transactional
  25. @Value