{"id":589,"date":"2025-01-24T23:37:05","date_gmt":"2025-01-24T22:37:05","guid":{"rendered":"https:\/\/www.xn--javaeinfacherklrt-4qb.de\/?p=589"},"modified":"2025-02-28T23:40:43","modified_gmt":"2025-02-28T22:40:43","slug":"conditionalonmissingbean-in-spring","status":"publish","type":"post","link":"https:\/\/www.xn--javaeinfacherklrt-4qb.de\/?p=589","title":{"rendered":"@ConditionalOnMissingBean in Spring"},"content":{"rendered":"\n<p>Die Annotation <code>@ConditionalOnMissingBean<\/code> ist ein leistungsstarkes Werkzeug im Spring-Framework, das es Entwicklern erm\u00f6glicht, Beans nur dann zu registrieren, wenn keine andere Bean des gleichen Typs bereits vorhanden ist. Dies ist besonders n\u00fctzlich in Konfigurationsklassen, bei der Implementierung von Bibliotheken und beim Anpassen des Spring-Kontexts.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">1. Grundlagen von <code>@ConditionalOnMissingBean<\/code><\/h2>\n\n\n\n<p>Die Annotation <code>@ConditionalOnMissingBean<\/code> stammt aus dem Spring Boot-Projekt und befindet sich im Paket <code>org.springframework.boot.autoconfigure.condition<\/code>. Sie wird in der Regel in Konfigurationsklassen verwendet, um zu pr\u00fcfen, ob eine bestimmte Bean bereits im Kontext existiert. Falls nicht, wird eine neue Bean registriert.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">1.1 Syntax<\/h3>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-1\" data-shcb-language-name=\"PHP\" data-shcb-language-slug=\"php\"><span><code class=\"hljs language-php\">@Configuration\n<span class=\"hljs-keyword\">public<\/span> <span class=\"hljs-class\"><span class=\"hljs-keyword\">class<\/span> <span class=\"hljs-title\">MyConfiguration<\/span> <\/span>{\n    @Bean\n    @ConditionalOnMissingBean\n    <span class=\"hljs-keyword\">public<\/span> MyService myService() {\n        <span class=\"hljs-keyword\">return<\/span> <span class=\"hljs-keyword\">new<\/span> MyServiceImpl();\n    }\n}\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-1\"><span class=\"shcb-language__label\">Code-Sprache:<\/span> <span class=\"shcb-language__name\">PHP<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">php<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>In diesem Beispiel wird eine Bean vom Typ <code>MyService<\/code> nur dann registriert, wenn nicht bereits eine andere Bean dieses Typs existiert.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">2. Vorteile und Anwendungsf\u00e4lle<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\">2.1 Flexibilit\u00e4t in Bibliotheken<\/h3>\n\n\n\n<p>Bei der Entwicklung von Spring Boot Startern oder Bibliotheken ist es oft gew\u00fcnscht, Standardimplementierungen bereitzustellen, aber Entwicklern die M\u00f6glichkeit zu geben, eigene Implementierungen zu \u00fcberschreiben. <code>@ConditionalOnMissingBean<\/code> erm\u00f6glicht genau das.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">2.2 Erweiterbarkeit<\/h3>\n\n\n\n<p>In Microservice-Architekturen oder stark modularisierten Anwendungen kann diese Annotation genutzt werden, um Standardkonfigurationen anzubieten, die bei Bedarf durch spezifische Implementierungen ersetzt werden k\u00f6nnen.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">2.3 Vermeidung von Konflikten<\/h3>\n\n\n\n<p>In komplexen Spring-Kontexten mit mehreren Konfigurationsklassen kann es leicht zu Konflikten kommen, wenn mehrere Beans desselben Typs definiert sind. <code>@ConditionalOnMissingBean<\/code> hilft, solche Probleme zu vermeiden.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">3. Erweiterte Nutzung<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\">3.1 Verwendung mit <code>name<\/code>-Attribut<\/h3>\n\n\n\n<p>Die Annotation erlaubt es, nach Beans anhand ihres Namens zu suchen:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-2\" data-shcb-language-name=\"PHP\" data-shcb-language-slug=\"php\"><span><code class=\"hljs language-php\">@Bean\n@ConditionalOnMissingBean(name = <span class=\"hljs-string\">\"specificService\"<\/span>)\n<span class=\"hljs-keyword\">public<\/span> MyService defaultService() {\n    <span class=\"hljs-keyword\">return<\/span> <span class=\"hljs-keyword\">new<\/span> DefaultMyServiceImpl();\n}\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-2\"><span class=\"shcb-language__label\">Code-Sprache:<\/span> <span class=\"shcb-language__name\">PHP<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">php<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>Diese Bean wird nur dann erstellt, wenn es keine andere Bean mit dem Namen <code>specificService<\/code> gibt.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">3.2 Verwendung mit spezifischen Typen<\/h3>\n\n\n\n<p>Man kann explizit festlegen, welche Typen gepr\u00fcft werden sollen:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-3\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript\">@Bean\n@ConditionalOnMissingBean(MyService.class)\npublic MyService myService() {\n    <span class=\"hljs-keyword\">return<\/span> <span class=\"hljs-keyword\">new<\/span> MyServiceImpl();\n}\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-3\"><span class=\"shcb-language__label\">Code-Sprache:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>Hier wird sichergestellt, dass <code>myService()<\/code> nur dann erstellt wird, wenn keine andere Bean vom Typ <code>MyService<\/code> vorhanden ist.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">3.3 Kombination mit anderen <code>@Conditional<\/code>-Annotationen<\/h3>\n\n\n\n<p>Spring bietet weitere bedingte Annotationen wie <code>@ConditionalOnProperty<\/code>, <code>@ConditionalOnClass<\/code>, die sich mit <code>@ConditionalOnMissingBean<\/code> kombinieren lassen:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-4\" data-shcb-language-name=\"PHP\" data-shcb-language-slug=\"php\"><span><code class=\"hljs language-php\">@Bean\n@ConditionalOnMissingBean\n@ConditionalOnProperty(name = <span class=\"hljs-string\">\"myapp.feature.enabled\"<\/span>, havingValue = <span class=\"hljs-string\">\"true\"<\/span>)\n<span class=\"hljs-keyword\">public<\/span> MyService conditionalService() {\n    <span class=\"hljs-keyword\">return<\/span> <span class=\"hljs-keyword\">new<\/span> ConditionalMyServiceImpl();\n}\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-4\"><span class=\"shcb-language__label\">Code-Sprache:<\/span> <span class=\"shcb-language__name\">PHP<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">php<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>Diese Bean wird nur erstellt, wenn <code>myapp.feature.enabled=true<\/code> ist <strong>und<\/strong> keine andere <code>MyService<\/code>-Bean vorhanden ist.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">4. Unterschiede zu <code>@Primary<\/code> und <code>@ConditionalOnBean<\/code><\/h2>\n\n\n\n<ul class=\"wp-block-list\">\n<li><code>@Primary<\/code>: Wird genutzt, um eine bevorzugte Bean auszuw\u00e4hlen, wenn mehrere Beans eines Typs existieren.<\/li>\n\n\n\n<li><code>@ConditionalOnBean<\/code>: Das Gegenteil von <code>@ConditionalOnMissingBean<\/code>, wird nur ausgef\u00fchrt, wenn eine bestimmte Bean bereits existiert.<\/li>\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\">5. Nachteile und potenzielle Probleme<\/h2>\n\n\n\n<p>Trotz ihrer Vorteile hat <code>@ConditionalOnMissingBean<\/code> auch einige Herausforderungen und Einschr\u00e4nkungen, die beachtet werden sollten:<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">5.1 Abh\u00e4ngigkeit von der Ladereihenfolge<\/h3>\n\n\n\n<p>Die Annotation pr\u00fcft, ob eine Bean bereits existiert, was von der Reihenfolge der Konfigurationsklassen und der Initialisierung der Beans abh\u00e4ngig sein kann. Falls eine Bean erst sp\u00e4ter registriert wird, kann es zu unerwarteten Ergebnissen kommen.<\/p>\n\n\n\n<p><strong>Beispielproblem:<\/strong><\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-5\" data-shcb-language-name=\"PHP\" data-shcb-language-slug=\"php\"><span><code class=\"hljs language-php\">@Configuration\n<span class=\"hljs-class\"><span class=\"hljs-keyword\">class<\/span> <span class=\"hljs-title\">ConfigA<\/span> <\/span>{\n    @Bean\n    @ConditionalOnMissingBean\n    <span class=\"hljs-keyword\">public<\/span> MyService myService() {\n        <span class=\"hljs-keyword\">return<\/span> <span class=\"hljs-keyword\">new<\/span> MyServiceImpl();\n    }\n}\n\n@Configuration\n<span class=\"hljs-class\"><span class=\"hljs-keyword\">class<\/span> <span class=\"hljs-title\">ConfigB<\/span> <\/span>{\n    @Bean\n    <span class=\"hljs-keyword\">public<\/span> MyService customService() {\n        <span class=\"hljs-keyword\">return<\/span> <span class=\"hljs-keyword\">new<\/span> CustomMyServiceImpl();\n    }\n}\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-5\"><span class=\"shcb-language__label\">Code-Sprache:<\/span> <span class=\"shcb-language__name\">PHP<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">php<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>Falls <code>ConfigB<\/code> nach <code>ConfigA<\/code> geladen wird, wird <code>customService()<\/code> registriert, aber <code>myService()<\/code> wurde bereits erstellt. Dies kann zu unerwarteten Verhaltensweisen f\u00fchren.<\/p>\n\n\n\n<p><strong>L\u00f6sung:<\/strong> Man kann explizit die Reihenfolge mit <code>@AutoConfigureOrder<\/code> oder <code>@DependsOn<\/code> steuern.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">5.2 Schwierigkeiten bei Debugging und Wartung<\/h3>\n\n\n\n<p>Da die Bean-Registrierung von vorhandenen Beans abh\u00e4ngt, kann es schwierig sein, nachzuvollziehen, warum eine bestimmte Bean nicht registriert wurde. Besonders in komplexen Spring-Projekten mit vielen Autokonfigurationen kann dies das Debugging erschweren.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">5.3 Unbeabsichtigtes Unterdr\u00fccken von Beans<\/h3>\n\n\n\n<p>Wenn eine bereits existierende Bean f\u00e4lschlicherweise als &#8222;nicht vorhanden&#8220; erkannt wird, kann eine unerw\u00fcnschte Standardimplementierung registriert werden. Dies kann zu unerwarteten Fehlern f\u00fchren.<\/p>\n\n\n\n<p><strong>L\u00f6sung:<\/strong><\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Pr\u00fcfen, ob <code>@Primary<\/code> oder <code>@Qualifier<\/code> korrekt gesetzt wurden.<\/li>\n\n\n\n<li>Sicherstellen, dass alle notwendigen Konfigurationen geladen sind.<\/li>\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\">6. Fazit<\/h2>\n\n\n\n<p>Die Annotation <code>@ConditionalOnMissingBean<\/code> ist ein wesentliches Werkzeug zur Gestaltung flexibler, erweiterbarer Spring-Boot-Anwendungen. Sie verhindert Konflikte, erlaubt Anpassungen und sorgt f\u00fcr eine saubere, modulare Architektur. Insbesondere in Bibliotheken oder Frameworks, die mit Spring Boot arbeiten, ist sie unverzichtbar.<\/p>\n\n\n\n<p>Allerdings ist es wichtig, die Abh\u00e4ngigkeit von der Ladereihenfolge zu beachten und sicherzustellen, dass die gew\u00fcnschte Bean-Registrierung wie erwartet funktioniert. Durch geeignete Debugging-Strategien und eine bewusste Steuerung der Konfigurationsklassen kann man potenzielle Probleme minimieren und das volle Potenzial dieser Annotation nutzen.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Die Annotation @ConditionalOnMissingBean ist ein leistungsstarkes Werkzeug im Spring-Framework, das es Entwicklern erm\u00f6glicht, Beans nur dann zu registrieren, wenn keine andere Bean des gleichen Typs bereits vorhanden ist. Dies ist besonders n\u00fctzlich in Konfigurationsklassen, bei der Implementierung von Bibliotheken und beim Anpassen des Spring-Kontexts. 1. Grundlagen von @ConditionalOnMissingBean Die Annotation @ConditionalOnMissingBean stammt aus dem Spring [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[5],"tags":[],"class_list":["post-589","post","type-post","status-publish","format-standard","hentry","category-spring"],"_links":{"self":[{"href":"https:\/\/www.xn--javaeinfacherklrt-4qb.de\/index.php?rest_route=\/wp\/v2\/posts\/589","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.xn--javaeinfacherklrt-4qb.de\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.xn--javaeinfacherklrt-4qb.de\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.xn--javaeinfacherklrt-4qb.de\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.xn--javaeinfacherklrt-4qb.de\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=589"}],"version-history":[{"count":1,"href":"https:\/\/www.xn--javaeinfacherklrt-4qb.de\/index.php?rest_route=\/wp\/v2\/posts\/589\/revisions"}],"predecessor-version":[{"id":590,"href":"https:\/\/www.xn--javaeinfacherklrt-4qb.de\/index.php?rest_route=\/wp\/v2\/posts\/589\/revisions\/590"}],"wp:attachment":[{"href":"https:\/\/www.xn--javaeinfacherklrt-4qb.de\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=589"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.xn--javaeinfacherklrt-4qb.de\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=589"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.xn--javaeinfacherklrt-4qb.de\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=589"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}