<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>3. IoC Container on BeamFoundry Rays Core</title><link>https://rays.bfdy.dev/rays/docs/3-ioc-container/</link><description>Recent content in 3. IoC Container on BeamFoundry Rays Core</description><generator>Hugo</generator><language>en-us</language><atom:link href="https://rays.bfdy.dev/rays/docs/3-ioc-container/index.xml" rel="self" type="application/rss+xml"/><item><title>Stereotypes &amp; Beams</title><link>https://rays.bfdy.dev/rays/docs/3-ioc-container/1-stereotypes/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://rays.bfdy.dev/rays/docs/3-ioc-container/1-stereotypes/</guid><description>&lt;h1 id="stereotypes--beams"&gt;Stereotypes &amp;amp; Beams&lt;a class="anchor" href="#stereotypes--beams"&gt;&lt;/a&gt;&lt;/h1&gt;&#10;&lt;p&gt;In Rays, a &amp;ldquo;Beam&amp;rdquo; is any object managed by the IoC container.&#10;You declare a struct as a Beam by embedding a &lt;strong&gt;Stereotype&lt;/strong&gt;.&lt;/p&gt;&#10;&lt;h2 id="-simplifying-with-dot-imports"&gt;🧹 Simplifying with Dot Imports&lt;a class="anchor" href="#-simplifying-with-dot-imports"&gt;&lt;/a&gt;&lt;/h2&gt;&#10;&lt;p&gt;Before we dive in, a quick note on style. To keep your domain code clean and free of repetitive package prefixes,&#10;it is highly recommended to use Go&amp;rsquo;s dot import feature for the &lt;code&gt;core&lt;/code&gt; and &lt;code&gt;lang&lt;/code&gt; packages.&lt;/p&gt;&#10;&lt;p&gt;This allows you to use framework types like &lt;code&gt;Service&lt;/code&gt;, &lt;code&gt;Component&lt;/code&gt;, and &lt;code&gt;Error&lt;/code&gt; directly as if they were&#10;native keywords. We will use this convention in the following examples.&lt;/p&gt;</description></item><item><title>Dependency Injection</title><link>https://rays.bfdy.dev/rays/docs/3-ioc-container/2-dependency-injection/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://rays.bfdy.dev/rays/docs/3-ioc-container/2-dependency-injection/</guid><description>&lt;h1 id="dependency-injection"&gt;Dependency Injection&lt;a class="anchor" href="#dependency-injection"&gt;&lt;/a&gt;&lt;/h1&gt;&#10;&lt;p&gt;Rays relies on struct tags to identify injection points.&lt;/p&gt;&#10;&lt;h2 id="basic-injection"&gt;Basic Injection&lt;a class="anchor" href="#basic-injection"&gt;&lt;/a&gt;&lt;/h2&gt;&#10;&lt;p&gt;Add &lt;code&gt;@:&amp;quot;Inject&amp;quot;&lt;/code&gt; to any field that is a &lt;strong&gt;pointer to a struct&lt;/strong&gt; or an &lt;strong&gt;interface&lt;/strong&gt;.&#10;The container will automatically find and wire the matching Beam by type.&lt;/p&gt;&#10;&lt;p&gt;&lt;strong&gt;Note&lt;/strong&gt;: &lt;em&gt;You cannot inject into a concrete value type (like &lt;code&gt;db Database&lt;/code&gt; instead of &lt;code&gt;db *Database&lt;/code&gt;),&#10;as this would break the singleton pattern by copying the struct by value.&lt;/em&gt;&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-go" data-lang="go"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;import&lt;/span&gt; . &lt;span style="color:#e6db74"&gt;&amp;#34;github.com/BeamFoundry/rays/pkg/core&amp;#34;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;type&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;OrderService&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;struct&lt;/span&gt; {&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;Service&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;inventory&lt;/span&gt; &lt;span style="color:#f92672"&gt;*&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;InventoryService&lt;/span&gt; &lt;span style="color:#e6db74"&gt;`@:&amp;#34;Inject&amp;#34;`&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;payment&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;PaymentGateway&lt;/span&gt; &lt;span style="color:#e6db74"&gt;`@:&amp;#34;Inject&amp;#34;`&lt;/span&gt; &lt;span style="color:#75715e"&gt;// Interfaces do not need a &amp;#39;*&amp;#39;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="private-field-superiority"&gt;Private Field Superiority&lt;a class="anchor" href="#private-field-superiority"&gt;&lt;/a&gt;&lt;/h2&gt;&#10;&lt;p&gt;Idiomatic Go encourages hiding internal state. Rays uses reflection to inject into private fields,&#10;meaning your dependencies aren&amp;rsquo;t exposed to other packages.&lt;/p&gt;</description></item><item><title>Lifecycle Management</title><link>https://rays.bfdy.dev/rays/docs/3-ioc-container/3-lifecycle/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://rays.bfdy.dev/rays/docs/3-ioc-container/3-lifecycle/</guid><description>&lt;h1 id="lifecycle-management"&gt;Lifecycle Management&lt;a class="anchor" href="#lifecycle-management"&gt;&lt;/a&gt;&lt;/h1&gt;&#10;&lt;p&gt;Rays uses a strict, deterministic phase model to ensure application stability.&lt;/p&gt;&#10;&lt;h2 id="phase-1-instantiation--wiring"&gt;Phase 1: Instantiation &amp;amp; Wiring&lt;a class="anchor" href="#phase-1-instantiation--wiring"&gt;&lt;/a&gt;&lt;/h2&gt;&#10;&lt;ol&gt;&#10;&lt;li&gt;The container scans for all embedded stereotypes.&lt;/li&gt;&#10;&lt;li&gt;It calls &lt;code&gt;New()&lt;/code&gt; on structs that implement it to set up initial state.&lt;/li&gt;&#10;&lt;li&gt;It maps &lt;code&gt;ConfigurationProperties&lt;/code&gt; from YAML.&lt;/li&gt;&#10;&lt;li&gt;It resolves all &lt;code&gt;@:&amp;quot;Inject&amp;quot;&lt;/code&gt; tags and assigns pointers (or interface references).&lt;/li&gt;&#10;&lt;/ol&gt;&#10;&lt;p&gt;&lt;em&gt;Note: Because no business logic runs in Phase 1, Rays natively handles &lt;strong&gt;Circular Dependencies&lt;/strong&gt; between singletons.&lt;/em&gt;&lt;/p&gt;</description></item><item><title>Configuration &amp; Profiles</title><link>https://rays.bfdy.dev/rays/docs/3-ioc-container/4-configuration-and-profiles/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://rays.bfdy.dev/rays/docs/3-ioc-container/4-configuration-and-profiles/</guid><description>&lt;h1 id="configuration--profiles"&gt;Configuration &amp;amp; Profiles&lt;a class="anchor" href="#configuration--profiles"&gt;&lt;/a&gt;&lt;/h1&gt;&#10;&lt;p&gt;In enterprise applications, configuration and environment management go hand-in-hand.&lt;/p&gt;&#10;&lt;p&gt;Rays provides a unified system to bind YAML configurations directly to your structs,&#10;override them based on active profiles (e.g., &lt;code&gt;dev&lt;/code&gt;, &lt;code&gt;prod&lt;/code&gt;), and conditionally load&#10;specific components depending on the environment.&lt;/p&gt;&#10;&lt;h2 id="1-binding-data"&gt;1. Binding Data&lt;a class="anchor" href="#1-binding-data"&gt;&lt;/a&gt;&lt;/h2&gt;&#10;&lt;p&gt;Embed &lt;code&gt;ConfigurationProperties&lt;/code&gt; and define the YAML path via the &lt;code&gt;Name&lt;/code&gt; tag.&lt;/p&gt;&#10;&lt;p&gt;&lt;strong&gt;NOTE:&lt;/strong&gt; &lt;em&gt;Rays strictly enforces a 1-to-1 parity between your&#10;YAML files and your Go code. The &lt;code&gt;yaml&lt;/code&gt; tag is &lt;strong&gt;not honored&lt;/strong&gt;. Only properties with&#10;the exact same case name as the Go struct field will be injected.&lt;/em&gt;&lt;/p&gt;</description></item><item><title>Prototypes &amp; Foundries</title><link>https://rays.bfdy.dev/rays/docs/3-ioc-container/5-prototypes/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://rays.bfdy.dev/rays/docs/3-ioc-container/5-prototypes/</guid><description>&lt;h1 id="prototypes--foundries"&gt;Prototypes &amp;amp; Foundries&lt;a class="anchor" href="#prototypes--foundries"&gt;&lt;/a&gt;&lt;/h1&gt;&#10;&lt;p&gt;If you need a new instance of an object every time it is requested (e.g., per HTTP request, per GRPC stream), you cannot use a Singleton. You need a &lt;strong&gt;Prototype&lt;/strong&gt;.&lt;/p&gt;&#10;&lt;h2 id="foundryt"&gt;&lt;code&gt;Foundry[T]&lt;/code&gt;&lt;a class="anchor" href="#foundryt"&gt;&lt;/a&gt;&lt;/h2&gt;&#10;&lt;p&gt;A Foundry is a type-safe factory automatically provided by the container for any struct marked with &lt;code&gt;Prototype&lt;/code&gt;.&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-go" data-lang="go"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;import&lt;/span&gt; (&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;context&amp;#34;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;net/http&amp;#34;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; . &lt;span style="color:#e6db74"&gt;&amp;#34;github.com/BeamFoundry/rays/pkg/core&amp;#34;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; . &lt;span style="color:#e6db74"&gt;&amp;#34;github.com/BeamFoundry/rays/pkg/lang&amp;#34;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;)&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;type&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;SessionState&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;struct&lt;/span&gt; {&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;Prototype&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;userID&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;string&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// Optional: Initialize state when forged&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;func&lt;/span&gt; (&lt;span style="color:#a6e22e"&gt;s&lt;/span&gt; &lt;span style="color:#f92672"&gt;*&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;SessionState&lt;/span&gt;) &lt;span style="color:#a6e22e"&gt;WithContext&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;ctx&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;context&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Context&lt;/span&gt;) &lt;span style="color:#a6e22e"&gt;Error&lt;/span&gt; {&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;s&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;userID&lt;/span&gt; = &lt;span style="color:#a6e22e"&gt;ctx&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Value&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#34;userID&amp;#34;&lt;/span&gt;).(&lt;span style="color:#66d9ef"&gt;string&lt;/span&gt;)&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;nil&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;type&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;AuthMiddleware&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;struct&lt;/span&gt; {&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;Service&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;sessionFactory&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;Foundry&lt;/span&gt;[&lt;span style="color:#f92672"&gt;*&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;SessionState&lt;/span&gt;] &lt;span style="color:#e6db74"&gt;`@:&amp;#34;Inject&amp;#34;`&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;logger&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;Logging&lt;/span&gt; &lt;span style="color:#e6db74"&gt;`@:&amp;#34;Inject&amp;#34;`&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;func&lt;/span&gt; (&lt;span style="color:#a6e22e"&gt;m&lt;/span&gt; &lt;span style="color:#f92672"&gt;*&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;AuthMiddleware&lt;/span&gt;) &lt;span style="color:#a6e22e"&gt;HandleHTTP&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;req&lt;/span&gt; &lt;span style="color:#f92672"&gt;*&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;http&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Request&lt;/span&gt;) {&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// 1. Forge a brand new instance&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;session&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;_&lt;/span&gt; &lt;span style="color:#f92672"&gt;:=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;m&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;sessionFactory&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Forge&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;req&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Context&lt;/span&gt;())&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// 2. Use the isolated prototype&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;m&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;logger&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Info&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#34;Handle HTTP connection&amp;#34;&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#34;userID&amp;#34;&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;session&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;userID&lt;/span&gt;)&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;</description></item></channel></rss>