spring-002: setBeanName()-of-BeanNameAware-BeanFactory

Here’s the detailed explanation of the execution flow with the actual code from a simple Java program to demonstrate BeanNameAware’s setBeanName() lifecycle interface method.
Buckle up! It will be a long ride


1. Execution Starts in main()

  • The program begins execution in the main() method. The Spring context is initialized using the AnnotationConfigApplicationContext class with TenantConfig.class as its configuration.

Code:

<span>public</span> <span>static</span> <span>void</span> <span>main</span><span>(</span><span>String</span><span>[]</span> <span>args</span><span>)</span> <span>{</span>
<span>// Initialize Spring context</span>
<span>AnnotationConfigApplicationContext</span> <span>context</span> <span>=</span> <span>new</span> <span>AnnotationConfigApplicationContext</span><span>(</span><span>TenantConfig</span><span>.</span><span>class</span><span>);</span>
<span>TenantService</span> <span>tenantService</span> <span>=</span> <span>context</span><span>.</span><span>getBean</span><span>(</span><span>TenantService</span><span>.</span><span>class</span><span>);</span>
<span>// Process tenant data</span>
<span>tenantService</span><span>.</span><span>processTenantData</span><span>();</span>
<span>}</span>
   <span>public</span> <span>static</span> <span>void</span> <span>main</span><span>(</span><span>String</span><span>[]</span> <span>args</span><span>)</span> <span>{</span>
       <span>// Initialize Spring context</span>
       <span>AnnotationConfigApplicationContext</span> <span>context</span> <span>=</span> <span>new</span> <span>AnnotationConfigApplicationContext</span><span>(</span><span>TenantConfig</span><span>.</span><span>class</span><span>);</span>
       <span>TenantService</span> <span>tenantService</span> <span>=</span> <span>context</span><span>.</span><span>getBean</span><span>(</span><span>TenantService</span><span>.</span><span>class</span><span>);</span>
       <span>// Process tenant data</span>
       <span>tenantService</span><span>.</span><span>processTenantData</span><span>();</span>
   <span>}</span>
public static void main(String[] args) { // Initialize Spring context AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(TenantConfig.class); TenantService tenantService = context.getBean(TenantService.class); // Process tenant data tenantService.processTenantData(); }

Enter fullscreen mode Exit fullscreen mode


2. Spring Context Initialization

  • The AnnotationConfigApplicationContext processes the TenantConfig class annotated with @Configuration. It scans the package "org.example4" for components like @Service and other Spring-managed beans.

Code:

<span>@Configuration</span>
<span>@ComponentScan</span><span>(</span><span>basePackages</span> <span>=</span> <span>"org.example4"</span><span>)</span> <span>// Adjust to your package structure</span>
<span>public</span> <span>class</span> <span>TenantConfig</span> <span>{</span>
<span>@Bean</span><span>(</span><span>name</span> <span>=</span> <span>"tenantA-dataSource"</span><span>)</span>
<span>public</span> <span>TenantDataSource</span> <span>tenantADataSource</span><span>()</span> <span>{</span>
<span>return</span> <span>new</span> <span>TenantDataSource</span><span>();</span>
<span>}</span>
<span>@Bean</span><span>(</span><span>name</span> <span>=</span> <span>"tenantB-dataSource"</span><span>)</span>
<span>public</span> <span>TenantDataSource</span> <span>tenantBDataSource</span><span>()</span> <span>{</span>
<span>return</span> <span>new</span> <span>TenantDataSource</span><span>();</span>
<span>}</span>
<span>}</span>
   <span>@Configuration</span>
   <span>@ComponentScan</span><span>(</span><span>basePackages</span> <span>=</span> <span>"org.example4"</span><span>)</span> <span>// Adjust to your package structure</span>
   <span>public</span> <span>class</span> <span>TenantConfig</span> <span>{</span>

       <span>@Bean</span><span>(</span><span>name</span> <span>=</span> <span>"tenantA-dataSource"</span><span>)</span>
       <span>public</span> <span>TenantDataSource</span> <span>tenantADataSource</span><span>()</span> <span>{</span>
           <span>return</span> <span>new</span> <span>TenantDataSource</span><span>();</span>
       <span>}</span>

       <span>@Bean</span><span>(</span><span>name</span> <span>=</span> <span>"tenantB-dataSource"</span><span>)</span>
       <span>public</span> <span>TenantDataSource</span> <span>tenantBDataSource</span><span>()</span> <span>{</span>
           <span>return</span> <span>new</span> <span>TenantDataSource</span><span>();</span>
       <span>}</span>
   <span>}</span>
@Configuration @ComponentScan(basePackages = "org.example4") // Adjust to your package structure public class TenantConfig { @Bean(name = "tenantA-dataSource") public TenantDataSource tenantADataSource() { return new TenantDataSource(); } @Bean(name = "tenantB-dataSource") public TenantDataSource tenantBDataSource() { return new TenantDataSource(); } }

Enter fullscreen mode Exit fullscreen mode


3. Bean Creation in TenantConfig

  • Spring invokes the two @Bean methods (tenantADataSource() and tenantBDataSource()) to create two beans of type TenantDataSource:
    • "tenantA-dataSource"
    • "tenantB-dataSource"

Code for @Bean definitions:

<span>@Bean</span><span>(</span><span>name</span> <span>=</span> <span>"tenantA-dataSource"</span><span>)</span>
<span>public</span> <span>TenantDataSource</span> <span>tenantADataSource</span><span>()</span> <span>{</span>
<span>return</span> <span>new</span> <span>TenantDataSource</span><span>();</span>
<span>}</span>
<span>@Bean</span><span>(</span><span>name</span> <span>=</span> <span>"tenantB-dataSource"</span><span>)</span>
<span>public</span> <span>TenantDataSource</span> <span>tenantBDataSource</span><span>()</span> <span>{</span>
<span>return</span> <span>new</span> <span>TenantDataSource</span><span>();</span>
<span>}</span>
   <span>@Bean</span><span>(</span><span>name</span> <span>=</span> <span>"tenantA-dataSource"</span><span>)</span>
   <span>public</span> <span>TenantDataSource</span> <span>tenantADataSource</span><span>()</span> <span>{</span>
       <span>return</span> <span>new</span> <span>TenantDataSource</span><span>();</span>
   <span>}</span>

   <span>@Bean</span><span>(</span><span>name</span> <span>=</span> <span>"tenantB-dataSource"</span><span>)</span>
   <span>public</span> <span>TenantDataSource</span> <span>tenantBDataSource</span><span>()</span> <span>{</span>
       <span>return</span> <span>new</span> <span>TenantDataSource</span><span>();</span>
   <span>}</span>
@Bean(name = "tenantA-dataSource") public TenantDataSource tenantADataSource() { return new TenantDataSource(); } @Bean(name = "tenantB-dataSource") public TenantDataSource tenantBDataSource() { return new TenantDataSource(); }

Enter fullscreen mode Exit fullscreen mode


4. TenantDataSource Bean Initialization

  • The TenantDataSource class implements BeanNameAware, allowing the Spring container to call the setBeanName(String beanName) method during bean initialization.
  • The setBeanName method extracts the tenant name (tenantA or tenantB) from the bean name and assigns a corresponding database URL.

Code:

<span>public</span> <span>class</span> <span>TenantDataSource</span> <span>implements</span> <span>BeanNameAware</span> <span>{</span>
<span>private</span> <span>String</span> <span>tenantName</span><span>;</span>
<span>private</span> <span>String</span> <span>databaseUrl</span><span>;</span>
<span>@Override</span>
<span>public</span> <span>void</span> <span>setBeanName</span><span>(</span><span>String</span> <span>beanName</span><span>)</span> <span>{</span>
<span>// Extract tenant name from the bean name</span>
<span>if</span> <span>(</span><span>beanName</span><span>.</span><span>contains</span><span>(</span><span>"-"</span><span>))</span> <span>{</span>
<span>this</span><span>.</span><span>tenantName</span> <span>=</span> <span>beanName</span><span>.</span><span>split</span><span>(</span><span>"-"</span><span>)[</span><span>0</span><span>];</span>
<span>}</span> <span>else</span> <span>{</span>
<span>throw</span> <span>new</span> <span>IllegalArgumentException</span><span>(</span><span>"Invalid bean naming convention. Expected format: <tenantName>-dataSource"</span><span>);</span>
<span>}</span>
<span>// Assign a database URL dynamically based on the tenant name</span>
<span>this</span><span>.</span><span>databaseUrl</span> <span>=</span> <span>"jdbc:mysql://localhost:3306/"</span> <span>+</span> <span>tenantName</span> <span>+</span> <span>"_db"</span><span>;</span>
<span>}</span>
<span>public</span> <span>void</span> <span>connect</span><span>()</span> <span>{</span>
<span>System</span><span>.</span><span>out</span><span>.</span><span>println</span><span>(</span><span>"Connecting to database for tenant: "</span> <span>+</span> <span>tenantName</span><span>);</span>
<span>System</span><span>.</span><span>out</span><span>.</span><span>println</span><span>(</span><span>"Using database URL: "</span> <span>+</span> <span>databaseUrl</span><span>);</span>
<span>// Simulate connection logic here</span>
<span>}</span>
<span>}</span>
   <span>public</span> <span>class</span> <span>TenantDataSource</span> <span>implements</span> <span>BeanNameAware</span> <span>{</span>

       <span>private</span> <span>String</span> <span>tenantName</span><span>;</span>
       <span>private</span> <span>String</span> <span>databaseUrl</span><span>;</span>

       <span>@Override</span>
       <span>public</span> <span>void</span> <span>setBeanName</span><span>(</span><span>String</span> <span>beanName</span><span>)</span> <span>{</span>
           <span>// Extract tenant name from the bean name</span>
           <span>if</span> <span>(</span><span>beanName</span><span>.</span><span>contains</span><span>(</span><span>"-"</span><span>))</span> <span>{</span>
               <span>this</span><span>.</span><span>tenantName</span> <span>=</span> <span>beanName</span><span>.</span><span>split</span><span>(</span><span>"-"</span><span>)[</span><span>0</span><span>];</span>
           <span>}</span> <span>else</span> <span>{</span>
               <span>throw</span> <span>new</span> <span>IllegalArgumentException</span><span>(</span><span>"Invalid bean naming convention. Expected format: <tenantName>-dataSource"</span><span>);</span>
           <span>}</span>

           <span>// Assign a database URL dynamically based on the tenant name</span>
           <span>this</span><span>.</span><span>databaseUrl</span> <span>=</span> <span>"jdbc:mysql://localhost:3306/"</span> <span>+</span> <span>tenantName</span> <span>+</span> <span>"_db"</span><span>;</span>
       <span>}</span>

       <span>public</span> <span>void</span> <span>connect</span><span>()</span> <span>{</span>
           <span>System</span><span>.</span><span>out</span><span>.</span><span>println</span><span>(</span><span>"Connecting to database for tenant: "</span> <span>+</span> <span>tenantName</span><span>);</span>
           <span>System</span><span>.</span><span>out</span><span>.</span><span>println</span><span>(</span><span>"Using database URL: "</span> <span>+</span> <span>databaseUrl</span><span>);</span>
           <span>// Simulate connection logic here</span>
       <span>}</span>
   <span>}</span>
public class TenantDataSource implements BeanNameAware { private String tenantName; private String databaseUrl; @Override public void setBeanName(String beanName) { // Extract tenant name from the bean name if (beanName.contains("-")) { this.tenantName = beanName.split("-")[0]; } else { throw new IllegalArgumentException("Invalid bean naming convention. Expected format: <tenantName>-dataSource"); } // Assign a database URL dynamically based on the tenant name this.databaseUrl = "jdbc:mysql://localhost:3306/" + tenantName + "_db"; } public void connect() { System.out.println("Connecting to database for tenant: " + tenantName); System.out.println("Using database URL: " + databaseUrl); // Simulate connection logic here } }

Enter fullscreen mode Exit fullscreen mode


5. TenantService Bean Creation

  • Spring scans the package "org.example4" and finds the TenantService class annotated with @Service.
  • The TenantService constructor has dependencies annotated with @Qualifier, which specifies which TenantDataSource beans to inject:
    • "tenantA-dataSource"
    • "tenantB-dataSource"

Code:

<span>@Service</span>
<span>public</span> <span>class</span> <span>TenantService</span> <span>{</span>
<span>private</span> <span>final</span> <span>TenantDataSource</span> <span>tenantADataSource</span><span>;</span>
<span>private</span> <span>final</span> <span>TenantDataSource</span> <span>tenantBDataSource</span><span>;</span>
<span>@Autowired</span>
<span>public</span> <span>TenantService</span><span>(</span>
<span>@Qualifier</span><span>(</span><span>"tenantA-dataSource"</span><span>)</span> <span>TenantDataSource</span> <span>tenantADataSource</span><span>,</span>
<span>@Qualifier</span><span>(</span><span>"tenantB-dataSource"</span><span>)</span> <span>TenantDataSource</span> <span>tenantBDataSource</span>
<span>)</span> <span>{</span>
<span>this</span><span>.</span><span>tenantADataSource</span> <span>=</span> <span>tenantADataSource</span><span>;</span>
<span>this</span><span>.</span><span>tenantBDataSource</span> <span>=</span> <span>tenantBDataSource</span><span>;</span>
<span>}</span>
<span>public</span> <span>void</span> <span>processTenantData</span><span>()</span> <span>{</span>
<span>System</span><span>.</span><span>out</span><span>.</span><span>println</span><span>(</span><span>"Processing data for all tenants..."</span><span>);</span>
<span>tenantADataSource</span><span>.</span><span>connect</span><span>();</span>
<span>tenantBDataSource</span><span>.</span><span>connect</span><span>();</span>
<span>}</span>
<span>}</span>
   <span>@Service</span>
   <span>public</span> <span>class</span> <span>TenantService</span> <span>{</span>

       <span>private</span> <span>final</span> <span>TenantDataSource</span> <span>tenantADataSource</span><span>;</span>
       <span>private</span> <span>final</span> <span>TenantDataSource</span> <span>tenantBDataSource</span><span>;</span>

       <span>@Autowired</span>
       <span>public</span> <span>TenantService</span><span>(</span>
               <span>@Qualifier</span><span>(</span><span>"tenantA-dataSource"</span><span>)</span> <span>TenantDataSource</span> <span>tenantADataSource</span><span>,</span>
               <span>@Qualifier</span><span>(</span><span>"tenantB-dataSource"</span><span>)</span> <span>TenantDataSource</span> <span>tenantBDataSource</span>
       <span>)</span> <span>{</span>
           <span>this</span><span>.</span><span>tenantADataSource</span> <span>=</span> <span>tenantADataSource</span><span>;</span>
           <span>this</span><span>.</span><span>tenantBDataSource</span> <span>=</span> <span>tenantBDataSource</span><span>;</span>
       <span>}</span>

       <span>public</span> <span>void</span> <span>processTenantData</span><span>()</span> <span>{</span>
           <span>System</span><span>.</span><span>out</span><span>.</span><span>println</span><span>(</span><span>"Processing data for all tenants..."</span><span>);</span>
           <span>tenantADataSource</span><span>.</span><span>connect</span><span>();</span>
           <span>tenantBDataSource</span><span>.</span><span>connect</span><span>();</span>
       <span>}</span>
   <span>}</span>
@Service public class TenantService { private final TenantDataSource tenantADataSource; private final TenantDataSource tenantBDataSource; @Autowired public TenantService( @Qualifier("tenantA-dataSource") TenantDataSource tenantADataSource, @Qualifier("tenantB-dataSource") TenantDataSource tenantBDataSource ) { this.tenantADataSource = tenantADataSource; this.tenantBDataSource = tenantBDataSource; } public void processTenantData() { System.out.println("Processing data for all tenants..."); tenantADataSource.connect(); tenantBDataSource.connect(); } }

Enter fullscreen mode Exit fullscreen mode


6. Retrieving TenantService from Context

  • Back in the main() method, the TenantService bean is retrieved from the Spring context:

    <span>TenantService</span> <span>tenantService</span> <span>=</span> <span>context</span><span>.</span><span>getBean</span><span>(</span><span>TenantService</span><span>.</span><span>class</span><span>);</span>
     <span>TenantService</span> <span>tenantService</span> <span>=</span> <span>context</span><span>.</span><span>getBean</span><span>(</span><span>TenantService</span><span>.</span><span>class</span><span>);</span>
    TenantService tenantService = context.getBean(TenantService.class);
  • This bean is fully initialized, with its dependencies injected.


7. Calling processTenantData()

  • The processTenantData() method is invoked on the TenantService bean.
  • Inside the method:
    • A message is printed: "Processing data for all tenants...".
    • The connect() method is called on both tenantADataSource and tenantBDataSource.

Code in main():

<span>tenantService</span><span>.</span><span>processTenantData</span><span>();</span>
   <span>tenantService</span><span>.</span><span>processTenantData</span><span>();</span>
tenantService.processTenantData();

Enter fullscreen mode Exit fullscreen mode

Code in TenantService:

<span>public</span> <span>void</span> <span>processTenantData</span><span>()</span> <span>{</span>
<span>System</span><span>.</span><span>out</span><span>.</span><span>println</span><span>(</span><span>"Processing data for all tenants..."</span><span>);</span>
<span>tenantADataSource</span><span>.</span><span>connect</span><span>();</span>
<span>tenantBDataSource</span><span>.</span><span>connect</span><span>();</span>
<span>}</span>
   <span>public</span> <span>void</span> <span>processTenantData</span><span>()</span> <span>{</span>
       <span>System</span><span>.</span><span>out</span><span>.</span><span>println</span><span>(</span><span>"Processing data for all tenants..."</span><span>);</span>
       <span>tenantADataSource</span><span>.</span><span>connect</span><span>();</span>
       <span>tenantBDataSource</span><span>.</span><span>connect</span><span>();</span>
   <span>}</span>
public void processTenantData() { System.out.println("Processing data for all tenants..."); tenantADataSource.connect(); tenantBDataSource.connect(); }

Enter fullscreen mode Exit fullscreen mode


8. Connecting to Tenant Databases

  • For each TenantDataSource bean, the connect() method:

    • Prints the tenantName and databaseUrl:
    Connecting to database for tenant: tenantA
    Using database URL: jdbc:mysql://localhost:3306/tenantA_db
    Connecting to database for tenant: tenantB
    Using database URL: jdbc:mysql://localhost:3306/tenantB_db
       Connecting to database for tenant: tenantA
       Using database URL: jdbc:mysql://localhost:3306/tenantA_db
    
       Connecting to database for tenant: tenantB
       Using database URL: jdbc:mysql://localhost:3306/tenantB_db
    Connecting to database for tenant: tenantA Using database URL: jdbc:mysql://localhost:3306/tenantA_db Connecting to database for tenant: tenantB Using database URL: jdbc:mysql://localhost:3306/tenantB_db

Code in TenantDataSource:

<span>public</span> <span>void</span> <span>connect</span><span>()</span> <span>{</span>
<span>System</span><span>.</span><span>out</span><span>.</span><span>println</span><span>(</span><span>"Connecting to database for tenant: "</span> <span>+</span> <span>tenantName</span><span>);</span>
<span>System</span><span>.</span><span>out</span><span>.</span><span>println</span><span>(</span><span>"Using database URL: "</span> <span>+</span> <span>databaseUrl</span><span>);</span>
<span>// Simulate connection logic here</span>
<span>}</span>
   <span>public</span> <span>void</span> <span>connect</span><span>()</span> <span>{</span>
       <span>System</span><span>.</span><span>out</span><span>.</span><span>println</span><span>(</span><span>"Connecting to database for tenant: "</span> <span>+</span> <span>tenantName</span><span>);</span>
       <span>System</span><span>.</span><span>out</span><span>.</span><span>println</span><span>(</span><span>"Using database URL: "</span> <span>+</span> <span>databaseUrl</span><span>);</span>
       <span>// Simulate connection logic here</span>
   <span>}</span>
public void connect() { System.out.println("Connecting to database for tenant: " + tenantName); System.out.println("Using database URL: " + databaseUrl); // Simulate connection logic here }

Enter fullscreen mode Exit fullscreen mode


9. Program Completion

  • After processing data for both tenants, the program completes execution.

Complete Output:

Processing data for all tenants...
Connecting to database for tenant: tenantA
Using database URL: jdbc:mysql://localhost:3306/tenantA_db
Connecting to database for tenant: tenantB
Using database URL: jdbc:mysql://localhost:3306/tenantB_db
Processing data for all tenants...
Connecting to database for tenant: tenantA
Using database URL: jdbc:mysql://localhost:3306/tenantA_db
Connecting to database for tenant: tenantB
Using database URL: jdbc:mysql://localhost:3306/tenantB_db
Processing data for all tenants... Connecting to database for tenant: tenantA Using database URL: jdbc:mysql://localhost:3306/tenantA_db Connecting to database for tenant: tenantB Using database URL: jdbc:mysql://localhost:3306/tenantB_db

Enter fullscreen mode Exit fullscreen mode

More info at https://docs.spring.io/spring-framework/docs/6.2.2/javadoc-api/org/springframework/beans/factory/BeanFactory.html

原文链接:spring-002: setBeanName()-of-BeanNameAware-BeanFactory

© 版权声明
THE END
喜欢就支持一下吧
点赞6 分享
Someone to love, something to do, and something to hope for.
有爱的人,有喜欢的事业,有梦想
评论 抢沙发

请登录后发表评论

    暂无评论内容