Spring Boot Auto-Configuration: මැජික් එක තේරුම් ගනිමු | SC Guide

Spring Boot Auto-Configuration: මැජික් එක තේරුම් ගනිමු | SC Guide

හායි කොල්ලෝ කෙල්ලෝ හැමෝටම! කොහොමද? අද අපි කතා කරන්න යන්නේ ඔයාලා හැමෝම වැඩියෙන් වගේ use කරන Spring Boot ගැන, විශේෂයෙන්ම ඒකේ තියෙන ‘මැජික්’ එකක් ගැන. ඒ තමයි Spring Boot Auto-Configuration. 🧙‍♂️

අපි දන්නවා Spring Boot කියන්නේ Java ecosystem එකේ application develop කරන්න තියෙන සුපිරිම Framework එකක් කියලා. ඒකෙන් අපිට පුළුවන් පුදුමාකාර විදියට ඉක්මනට enterprise-grade applications හදන්න. ඒකට ප්‍රධානම හේතුවක් තමයි ඒකේ තියෙන Auto-Configuration කියන Feature එක. අපි පොඩ්ඩක් හිතමුකෝ, අලුතෙන් Spring Boot project එකක් පටන් ගද්දී, අපි dependency එකක් add කරාම ඒකට අදාළ configuration ටික Spring Boot එකෙන් auto-matically set කරනවා. උදාහරණයක් විදියට, `spring-boot-starter-data-jpa` add කරොත් Database connection එකට අවශ්‍ය Configuration ටික, EntityManagerFactory වගේ Beans ටික auto-matically හදාගන්නවා. මේක නිකන් magic වගේ නේද? 🤯

අද අපි මේ magic එක පිටිපස්සේ තියෙන රහස හොයලා බලමු. කොහොමද මේක වෙන්නේ? අපිට මේක customize කරන්න පුළුවන්ද? කියන එක ගැන සවිස්තරාත්මකව කතා කරමු. ඒ වගේම, අපේම custom Auto-Configuration එකක් හදන හැටිත් අපි step-by-step බලමු. එහෙනම් පටන් ගමු!

Auto-Configuration කියන්නේ මොකක්ද? 💭

සරලවම කිව්වොත්, Spring Boot Auto-Configuration කියන්නේ, ඔයාගේ application එකේ classpath එකේ තියෙන dependencies, properties, සහ වෙනත් conditions අනුව, Spring Boot එකෙන් automatic-වම beans Configure කරන mechanism එකට. කලින් කාලේ Spring Framework එකේ projects කරද්දි අපි හැමදේම manual-ව configure කරන්න ඕනේ. XML වලින්, නැත්නම් JavaConfig වලින් bean definitions ලියන්න ඕනේ. ඒත් Spring Boot ආවට පස්සේ ඒ headache එක ගොඩක් අඩු වුණා.

උදාහරණයක් විදියට ඔයාට Spring Web application එකක් හදන්න ඕනේ නම්, කලින් නම් dispatcher servlet configure කරන්න ඕනේ, view resolvers add කරන්න ඕනේ, web mvc support enable කරන්න ඕනේ වගේ ගොඩක් දේවල් configure කරන්න තිබ්බා. ඒත් දැන් `spring-boot-starter-web` dependency එක project එකට add කරාම, Spring Boot එකෙන් ඒ හැමදේම auto-matically configure කරලා දෙනවා. නිකන් library එකක් add කරාම වැඩේ ගොඩ. 😄

මේක හරියට ඔයාගේ ගෙදර වැඩ කරන robot කෙනෙක් වගේ. ඔයා fridge එකට කෑම දැම්මම, ඒ robot එකට තේරෙනවා ඔයාට කෑම උයන්න ඕනේ කියලා. ඊට පස්සේ එයාට ඕනේ කරන හැම උපකරණයක්ම, materials ටිකත් ready කරලා දෙනවා. ඔයාට තියෙන්නේ කෑම උයන එක විතරයි. ඒ වගේ තමයි Auto-Configuration එකත්. ඔයාට ඕනේ දේ (dependency එක) දුන්නම, ඒකට අදාළ settings ටික auto-matically හදලා දෙනවා.

මැජික් එක වෙන්නේ කොහොමද? 🎩

දැන් අපි බලමු මේ Auto-Configuration කියන magic එක ඇත්තටම වෙන්නේ කොහොමද කියලා. මේකට ප්‍රධාන දේවල් 3ක් සම්බන්ධයි:

1. `@EnableAutoConfiguration` Annotation එක

ඔයා Spring Boot application එකක් පටන් ගද්දි, ඔයාගේ main class එකේ `@SpringBootApplication` annotation එක තියෙනවා නේද? මේ annotation එක ඇතුලේ තමයි `@EnableAutoConfiguration` කියන annotation එක තියෙන්නේ. මේක තමයි Spring Boot Auto-Configuration process එක trigger කරන ප්‍රධානම entry point එක. මේක Spring Boot ApplicationContext එක load වෙද්දි, classpath එක Scan කරලා Auto-Configuration classes හොයන්න පටන් ගන්නවා.

2. `META-INF/spring.factories` ෆයිල් එක

හරි, දැන් `@EnableAutoConfiguration` එකට කොහෙන්ද මේ Auto-Configuration classes ටික හොයාගන්න කියලා තේරෙන්නේ? ඒකට තමයි `META-INF/spring.factories` කියන ෆයිල් එක භාවිතා වෙන්නේ. මේ ෆයිල් එක Spring Boot Starter dependencies වල (උදා: `spring-boot-starter-web`, `spring-boot-starter-data-jpa` වගේ) ඇතුලේ තියෙනවා. මේකේ තියෙන්නේ Key-Value pairs විදියට, Spring Boot එකට load කරන්න ඕනේ Auto-Configuration classes ටිකේ නම් ටික.

උදාහරණයක් විදියට, `spring-boot-autoconfigure` JAR එක ඇතුලේ තියෙන `spring.factories` ෆයිල් එක මෙහෙම වෙන්න පුළුවන්:

# META-INF/spring.factories
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration,\\
org.springframework.boot.autoconfigure.web.servlet.WebMvcAutoConfiguration,\\
org.springframework.boot.autoconfigure.data.jpa.JpaRepositoriesAutoConfiguration,
# ... තවත් ගොඩක් Auto-Configuration classes

මේක තමයි ඇත්තටම magic එකට අවශ්‍ය rules ටික තියෙන්නේ. Spring Boot එක මේ ෆයිල් එක කියවලා, ඒකේ තියෙන හැම Auto-Configuration class එකක්ම ApplicationContext එකට load කරන්න උත්සාහ කරනවා.

3. `@Conditional` Annotations

Spring Boot එක හැම Auto-Configuration class එකක්ම load කරන්න උත්සාහ කළත්, ඒ හැම එකක්ම ඇත්තටම activate වෙන්නේ නැහැ. ඒකට හේතුව තමයි ඒ Auto-Configuration classes වල තියෙන `@Conditional` annotations. මේවා හරියට `if-else` statements වගේ වැඩ කරනවා. යම්කිසි condition එකක් fulfil වුණොත් විතරයි ඒ Auto-Configuration class එකේ තියෙන beans configure වෙන්නේ.

බහුලව භාවිතා වන `@Conditional` annotations කිහිපයක් මෙන්න:

  • `@ConditionalOnClass`: classpath එකේ යම්කිසි class එකක් තියෙනවා නම්. (උදා: `DataSourceAutoConfiguration` එක activate වෙන්නේ classpath එකේ `javax.sql.DataSource` class එක තියෙනවා නම්)
  • `@ConditionalOnMissingClass`: classpath එකේ යම්කිසි class එකක් නැති නම්.
  • `@ConditionalOnBean`: ApplicationContext එකේ යම්කිසි bean එකක් තියෙනවා නම්.
  • `@ConditionalOnMissingBean`: ApplicationContext එකේ යම්කිසි bean එකක් නැති නම්. (මේකෙන් තමයි Spring Boot එක default configurations දෙන්නේ, අපේම custom bean එකක් දැම්මොත් Spring Boot default එක skip කරනවා)
  • `@ConditionalOnProperty`: යම්කිසි Spring property එකක් set කරලා තියෙනවා නම් හෝ යම්කිසි value එකක් තියෙනවා නම්.
  • `@ConditionalOnWebApplication`: Application එක web application එකක් නම්.

මේ annotations ටික නිසා තමයි Spring Boot එකට intelligently තේරෙන්නේ, මොන configuration එකද activate කරන්න ඕනේ කියලා. උදාහරණයක් විදියට, ඔයා `spring-boot-starter-web` add කරොත්, `WebMvcAutoConfiguration` එක activate වෙනවා. ඒත් `spring-boot-starter-data-jpa` විතරක් add කරලා `spring-boot-starter-web` නැත්නම්, `WebMvcAutoConfiguration` එක activate වෙන්නේ නැහැ. වැඩේ නියමයි නේද? 😎

Custom Auto-Configuration එකක් හදමු! 🚀

දැන් අපි මේක තව ටිකක් practical විදියට බලමු. අපේම custom Auto-Configuration එකක් හදන හැටි බලමු. මේකෙන් අපිට පුළුවන් අපේම libraries, modules වලට auto-configuration support එකක් දෙන්න. අපි හිතමු අපිට ඕනේ කියලා simple `GreetingService` එකක් Auto-Configure කරන්න. මේකෙන් කරන්නේ message එකකට prefix එකක් සහ suffix එකක් add කරන එක.

පියවර 1: Dependency Module එකක් හදමු

මුලින්ම අපි Maven හෝ Gradle project එකක් හදාගමු (අපි මේක `my-greeting-spring-boot-starter` කියලා හඳුන්වමු). මේක Spring Boot Application එකකට dependency එකක් විදියට add කරන්න පුළුවන් වෙන විදියට තමයි හදන්නේ.

1.1 Greeting Service Class එක හදමු: `MyGreetingService.java`

package com.example.greeting.service;

public class MyGreetingService {

    private String prefix;
    private String suffix;

    public MyGreetingService(String prefix, String suffix) {
        this.prefix = prefix;
        this.suffix = suffix;
    }

    public String greet(String name) {
        return prefix + " " + name + suffix;
    }
}

1.2 Properties Class එක හදමු: `MyGreetingServiceProperties.java`

මේ class එකෙන් තමයි අපේ service එකට අවශ්‍ය configuration properties ටික read කරගන්නේ. මේකට `@ConfigurationProperties` annotation එක භාවිතා කරනවා. මෙතන `my.greeting` කියන්නේ `application.properties` හෝ `application.yml` ෆයිල් එකේ අපි define කරන prefix එක.

package com.example.greeting.properties;

import org.springframework.boot.context.properties.ConfigurationProperties;

@ConfigurationProperties("my.greeting")
public class MyGreetingServiceProperties {

    private String prefix = "Hello"; // Default value
    private String suffix = "!";    // Default value

    // Getters and Setters
    public String getPrefix() {
        return prefix;
    }

    public void setPrefix(String prefix) {
        this.prefix = prefix;
    }

    public String getSuffix() {
        return suffix;
    }

    public void setSuffix(String suffix) {
        this.suffix = suffix;
    }
}

1.3 Auto-Configuration Class එක හදමු: `MyGreetingServiceAutoConfiguration.java`

මේ තමයි ප්‍රධානම class එක. මේකෙන් තමයි `MyGreetingService` එක bean එකක් විදියට Spring Context එකට add කරන්නේ.

package com.example.greeting.autoconfig;

import com.example.greeting.properties.MyGreetingServiceProperties;
import com.example.greeting.service.MyGreetingService;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration // මේක configuration class එකක් කියලා කියනවා
@ConditionalOnClass(MyGreetingService.class) // classpath එකේ MyGreetingService class එක තියෙනවා නම් විතරයි activate වෙන්නේ
@EnableConfigurationProperties(MyGreetingServiceProperties.class) // MyGreetingServiceProperties එක load කරන්න කියනවා
public class MyGreetingServiceAutoConfiguration {

    @Bean // මේක bean එකක් විදියට Spring Context එකට add කරනවා
    @ConditionalOnMissingBean // MyGreetingService type එකේ bean එකක් දැනටමත් නැත්නම් විතරයි මේක activate වෙන්නේ
    public MyGreetingService myGreetingService(MyGreetingServiceProperties properties) {
        return new MyGreetingService(properties.getPrefix(), properties.getSuffix());
    }
}

1.4 `META-INF/spring.factories` ෆයිල් එකට Add කරමු

අපේ `my-greeting-spring-boot-starter` project එකේ `src/main/resources/META-INF` ෆෝල්ඩර් එක ඇතුලේ `spring.factories` කියලා ෆයිල් එකක් හදලා මේකේ පහත code එක add කරන්න.

# META-INF/spring.factories
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
com.example.greeting.autoconfig.MyGreetingServiceAutoConfiguration

දැන් `my-greeting-spring-boot-starter` project එක build කරලා Maven Local repository එකට install කරගන්න (e.g., `mvn clean install`).

පියවර 2: Client Application එකක මේක භාවිතා කරමු

දැන් අලුතෙන් Spring Boot Application එකක් හදමු (උදා: `greeting-demo-app` කියලා). මේකේ `pom.xml` එකට අපි හදපු `my-greeting-spring-boot-starter` එක dependency එකක් විදියට add කරන්න.

2.1 `pom.xml` එකට Dependency එක Add කරමු

<dependency>
    <groupId>com.example</groupId>
    <artifactId>my-greeting-spring-boot-starter</artifactId>
    <version>0.0.1-SNAPSHOT</version> <!-- ඔයාගේ version එක -->
</dependency>

2.2 `application.yml` (හෝ `application.properties`) එකේ Properties Set කරමු

අපිට පුළුවන් අපේ Auto-Configuration එකේ default values override කරන්න. `src/main/resources/application.yml` ෆයිල් එකට මේක add කරන්න:

my:
  greeting:
    prefix: Ayubowan
    suffix: Digatama!

මේ properties set නොකලොත්, `MyGreetingServiceProperties` එකේ තියෙන default values (`Hello` සහ `!`) භාවිතා වෙනවා.

2.3 Application එක Run කරලා බලමු

දැන් ඔයාගේ Spring Boot Application එකේ main class එකේ `MyGreetingService` එක Inject කරලා භාවිතා කරලා බලන්න.

package com.example.greeting.demo;

import com.example.greeting.service.MyGreetingService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class GreetingDemoApplication implements CommandLineRunner {

    @Autowired
    private MyGreetingService myGreetingService; // Auto-configured service එක inject කරනවා

    public static void main(String[] args) {
        SpringApplication.run(GreetingDemoApplication.class, args);
    }

    @Override
    public void run(String... args) {
        System.out.println(myGreetingService.greet("Kolaba")); // Service එක භාවිතා කරනවා
        System.out.println(myGreetingService.greet("Kandy"));
    }
}

මේ application එක run කළාම, console එකේ මෙහෙම output එකක් එන්න ඕනේ:

Ayubowan Kolaba Digatama!
Ayubowan Kandy Digatama!

අපි `MyGreetingService` එක bean එකක් විදියට කොහෙවත් explicit-ව define කළේ නැහැ. Spring Boot එකෙන් අපේ custom Auto-Configuration එක හරහා ඒක configure කළා. මේක තමයි Auto-Configuration වල බලය! 💪

Auto-Configuration Extend කරන හැටි 🔍

දැනට තියෙන Auto-Configurations extend කිරීම හෝ disable කිරීමත් අපිට කරන්න පුළුවන්.

  • Override කරන්න: යම්කිසි auto-configured bean එකක default behaviour එක වෙනස් කරන්න ඕනේ නම්, අපිට පුළුවන් අපේම bean එකක් define කරන්න. Spring Boot එකේ Auto-Configurations බොහෝ විට `@ConditionalOnMissingBean` භාවිතා කරන නිසා, අපේම bean එකක් define කළොත්, Spring Boot එකෙන් auto-configure කරන default bean එක skip වෙනවා.

Disable කරන්න: යම්කිසි Auto-Configuration එකක් disable කරන්න ඕනේ නම්, `@SpringBootApplication` annotation එකේ `exclude` property එක භාවිතා කරන්න පුළුවන්. උදාහරණයක් විදියට, `DataSourceAutoConfiguration` එක disable කරන්න ඕනේ නම්:

@SpringBootApplication(exclude = {DataSourceAutoConfiguration.class})
public class MySpringBootApp {
    // ...
}

හෝ `application.properties` ෆයිල් එකේ:

spring.autoconfigure.exclude=org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration

අවසන් වශයෙන් 📈

Spring Boot Auto-Configuration කියන්නේ Spring Boot වල කොඳු නාරටිය වගේ. මේක නැත්නම් Spring Boot මේ තරම් popular වෙන්නේ නැහැ. මේ mechanism එක නිසා Developers ලට boilerplate code ලියන එකෙන් ගොඩක් නිදහස ලැබෙනවා. ඒ වගේම, අපිට පුළුවන් අපේම libraries වලටත් මේ Auto-Configuration power එක දෙන්න, ඒකෙන් ඒ libraries භාවිතා කරන developers ලට විශාල පහසුවක් වෙනවා.

මේ article එකෙන් ඔයාලට Auto-Configuration ගැන හොඳ අවබෝධයක් ලැබෙන්න ඇති කියලා හිතනවා. විශේෂයෙන්ම custom Auto-Configuration එකක් හදන හැටි. මේක ඔයාලගේ project වලටත් අත්හදා බලන්න. මොනවා හරි ප්‍රශ්න තියෙනවා නම්, comment එකක් දාලා යන්න අමතක කරන්න එපා! 😊 අලුත් දෙයක් එක්ක ආයෙත් හමුවෙමු. එතකන් Happy Coding! 💻