सीडीआई के साथ क्वार्कस में निर्भरता इंजेक्शन: एआरसी, स्कोप, क्वालिफायर और बिल्ड-टाइम इंजेक्शन
डिपेंडेंसी इंजेक्शन (डीआई) आधुनिक उद्यम जावा एप्लिकेशन विकास का आधार है। वर्षों से, जावा डेवलपर्स घटक जीवनचक्र को अलग करने, सेवा निर्भरता को प्रबंधित करने और कॉन्फ़िगरेशन गुणों को इंजेक्ट करने के लिए स्प्रिंग आईओसी (नियंत्रण का उलटा) या मानक जकार्ता ईई सीडीआई (संदर्भ और निर्भरता इंजेक्शन) कंटेनरों जैसे हाइबरनेट वेल्ड या ओपनवेबबीन्स पर निर्भर थे।
हालाँकि, जैसे ही एंटरप्राइज एप्लिकेशन क्लाउड-नेटिव माइक्रोसर्विसेज, डॉकर और कुबेरनेट्स के साथ कंटेनरीकरण, और सर्वर रहित निष्पादन मॉडल (एडब्ल्यूएस लैम्ब्डा, नेटिव) की ओर परिवर्तित हुए, पारंपरिक निर्भरता इंजेक्शन कंटेनरों ने एक महत्वपूर्ण दोष उजागर किया: भारी रनटाइम प्रतिबिंब और उच्च मेमोरी ओवरहेड।
क्वार्कस और इसका हल्का सीडीआई इंजन, ArC दर्ज करें। Kubernetes और GraalVM मूल संकलन के लिए ग्राउंड अप से निर्मित, क्वार्कस रिफ्लेक्शन, क्लासपाथ स्कैनिंग और बीन ग्राफ वायरिंग को एप्लिकेशन रनटाइम से बिल्ड टाइम में स्थानांतरित करके निर्भरता इंजेक्शन को फिर से परिभाषित करता है।
इस डीप-डाइव गाइड में, हम सीडीआई के साथ क्वार्कस में निर्भरता इंजेक्शन का पता लगाएंगे, जिसमें आर्क कंटेनर के आंतरिक यांत्रिकी, सीडीआई स्कोप, कस्टम क्वालिफायर, निर्माता, इंटरसेप्टर, इवेंट-संचालित पर्यवेक्षक, प्रोग्रामेटिक लुकअप और उच्च-प्रदर्शन वाले क्लाउड-नेटिव जावा अनुप्रयोगों को लिखने के लिए सर्वोत्तम अभ्यास शामिल होंगे।
1. आर्क को समझना: क्वार्कस बिल्ड-टाइम सीडीआई इंजन
मानक जकार्ता ईई सीडीआई कंटेनर पूरी तरह से एप्लिकेशन स्टार्टअप पर काम करते हैं। जब कोई लीगेसी एप्लिकेशन बूट होता है, तो CDI कंटेनर क्लासपाथ में प्रत्येक JAR को स्कैन करता है, मेटाडेटा को पार्स करता है, जावा रिफ्लेक्शन (java.lang.reflect) का उपयोग करके एनोटेशन का निरीक्षण करता है, मेमोरी में डायनामिक प्रॉक्सी उत्पन्न करता है, और निर्भरता ग्राफ बनाता है। यह गतिशील प्रतिबिंब महत्वपूर्ण रैम (मेटास्पेस) की खपत करता है और कोल्ड-स्टार्ट बूट समय को बढ़ाता है।
क्वार्कस इस बाधा को ArC (जकार्ता CDI 4.0 विनिर्देशों पर आधारित एक बिल्ड-टाइम CDI कार्यान्वयन) के साथ हल करता है।
ArC मानक CDI से किस प्रकार भिन्न है:
- बिल्ड-टाइम ऑग्मेंटेशन:
mvn packageया./gradlew buildके दौरान, ArC सभी एप्लिकेशन बीन्स को स्कैन करता है, इंजेक्शन बिंदुओं को मान्य करता है, और निर्भरता ग्राफ को पूर्व-निर्मित करता है। - अहेड-ऑफ-टाइम (एओटी) बाइटकोड जेनरेशन: एआरसी इंस्टेंटिएशन, बीन प्रॉक्सी और इंटरसेप्टर के लिए प्रत्यक्ष जावा बाइटकोड उत्पन्न करता है, जिससे रनटाइम पर प्रतिबिंब समाप्त हो जाता है।
- अप्रयुक्त बीन प्रूनिंग (डेड कोड एलिमिनेशन): कोई भी सीडीआई बीन जिसे कभी भी इंजेक्ट नहीं किया जाता है या गतिशील रूप से संदर्भित नहीं किया जाता है, संकलन के दौरान पहचाना जाता है और स्वचालित रूप से अंतिम बाइनरी से हटा दिया जाता है, जिससे मेमोरी फ़ुटप्रिंट कम हो जाता है।
- GraalVM नेटिव इमेज ऑप्टिमाइज़ेशन: क्योंकि बीन वायरिंग को बिल्ड समय पर हल किया जाता है, क्वार्कस एप्लिकेशन शून्य प्रतिबिंब कॉन्फ़िगरेशन संकेतों के साथ मूल निष्पादन योग्य में मूल रूप से संकलित होते हैं।
2. सीडीआई बीन स्कोप्स और जीवनचक्र प्रबंधन
सीडीआई में, एक स्कोप बीन इंस्टेंस के जीवनचक्र और दृश्यता को निर्धारित करता है। क्वार्कस एआरसी बिल्ड-टाइम अनुकूलन के साथ मानक जकार्ता सीडीआई स्कोप का समर्थन करता है।
क्वार्कस में प्राथमिक सीडीआई स्कोप:
| स्कोप एनोटेशन | जीवनचक्र और व्यवहार | प्रॉक्सी निर्माण | सर्वोत्तम उपयोग का मामला |
|---|---|---|---|
@एप्लिकेशनस्कोप्ड |
प्रति एप्लिकेशन एकल उदाहरण. प्रथम आह्वान पर आलसी आरंभीकरण। राज्य सभी थ्रेड्स में साझा किया गया। | क्लाइंट प्रॉक्सी जेनरेट किया गया | स्टेटलेस सेवाएँ, रिपॉजिटरी, कॉन्फ़िगरेशन। |
@RequestScoped |
एकल HTTP अनुरोध या ईवेंट आमंत्रण से जुड़ा उदाहरण। अनुरोध पूरा होने पर नष्ट कर दिया जाएगा। | क्लाइंट प्रॉक्सी जेनरेट किया गया | उपयोगकर्ता सत्र, अनुरोध संदर्भ डेटा, सुरक्षा टोकन। |
@आश्रित |
यदि कोई निर्दिष्ट नहीं है तो डिफ़ॉल्ट दायरा। उदाहरण सीधे इंजेक्शन लगाने वाले बीन के जीवनकाल से जुड़ा हुआ है। | कोई प्रॉक्सी नहीं (प्रत्यक्ष उदाहरण) | सहायक उपयोगिता वर्ग, क्षणिक राज्य धारक। |
@सिंगलटन |
प्रति एप्लिकेशन एकल उदाहरण. उत्सुकता से या आलस्य से त्वरित किया गया। कोई क्लाइंट प्रॉक्सी रैपर नहीं. | कोई प्रॉक्सी नहीं (प्रत्यक्ष उदाहरण) | उच्च-प्रदर्शन सिंगलटन जहां क्लाइंट प्रॉक्सी ओवरहेड से बचा जाना चाहिए। |
@अनरिमूवेबल |
मार्कर एनोटेशन ArC को बिल्ड-टाइम ऑप्टिमाइज़ेशन के दौरान बीन को न हटाने का निर्देश देता है। | स्कोप पर निर्भर करता है | गतिशील लुकअप लक्ष्य या प्रतिबिंब-संदर्भित बीन्स। |
कोड उदाहरण: स्कोप्ड बीन्स की घोषणा करना
package com.ghaznix.services;
import jakarta.enterprise.context.ApplicationScoped;
import jakarta.enterprise.context.RequestScoped;
import java.util.UUID;
@ApplicationScoped
public class OrderProcessingService {
public String processOrder(String orderId) {
return "Order " + orderId + " processed successfully.";
}
}
@RequestScoped
public class RequestContextHolder {
private final String requestId = UUID.randomUUID().toString();
public String getRequestId() {
return requestId;
}
}
3. क्वार्कस में निर्भरता इंजेक्शन पैटर्न
क्वार्कस मानक jakarta.inject.Inject एनोटेशन का उपयोग करके कई इंजेक्शन शैलियों का समर्थन करता है।
ए. कंस्ट्रक्टर इंजेक्शन (अनुशंसित सर्वोत्तम अभ्यास)
कंस्ट्रक्टर इंजेक्शन अपरिवर्तनीयता (final फ़ील्ड) की गारंटी देता है, CDI कंटेनरों की आवश्यकता के बिना इकाई परीक्षण को सरल बनाता है, और निर्भरता को स्पष्ट करता है।
package com.ghaznix.resources;
import com.ghaznix.services.OrderProcessingService;
import jakarta.inject.Inject;
import jakarta.ws.rs.POST;
import jakarta.ws.rs.Path;
import jakarta.ws.rs.PathParam;
@Path("/orders")
public class OrderResource {
private final OrderProcessingService orderService;
// In Quarkus, if a class has a single constructor, @Inject is OPTIONAL!
@Inject
public OrderResource(OrderProcessingService orderService) {
this.orderService = orderService;
}
@POST
@Path("/{id}")
public String checkout(@PathParam("id") String id) {
return orderService.processOrder(id);
}
}
प्रो टिप: क्वार्कस ArC में, यदि एक बीन में केवल एक कंस्ट्रक्टर है, तो आप
@Injectएनोटेशन को पूरी तरह से छोड़ सकते हैं। ArC स्वचालित रूप से इसे इंजेक्शन कंस्ट्रक्टर के रूप में पहचानता है।
बी फील्ड इंजेक्शन
फ़ील्ड इंजेक्शन संक्षिप्त है लेकिन फ़ील्ड को परिवर्तनशील बनाता है और स्टैंडअलोन इकाई परीक्षण को जटिल बनाता है।
@ApplicationScoped
public class NotificationService {
@Inject
EmailClient emailClient; // Field injection
}
4. एकाधिक कार्यान्वयन को क्वालीफायर और असंबद्ध करना
जब एकाधिक बीन्स एक ही इंटरफ़ेस लागू करते हैं, तो CDI बिल्ड समय पर एक अस्पष्ट निर्भरता अपवाद फेंकता है। लक्ष्य बीन कार्यान्वयन को सुरक्षित रूप से हल करने के लिए क्वार्कस क्वालिफायर का उपयोग करता है।
कस्टम क्वालिफायर को परिभाषित करना
package com.ghaznix.payment;
import jakarta.inject.Qualifier;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;
import static java.lang.annotation.ElementType.*;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
@Qualifier
@Retention(RUNTIME)
@Target({TYPE, METHOD, FIELD, PARAMETER})
public @interface PaymentType {
Mode value();
enum Mode {
CREDIT_CARD,
PAYPAL,
CRYPTO
}
}
योग्य बीन्स को लागू करना
public interface PaymentProcessor {
void process(double amount);
}
@ApplicationScoped
@PaymentType(PaymentType.Mode.CREDIT_CARD)
public class CreditCardProcessor implements PaymentProcessor {
@Override
public void process(double amount) {
System.out.println("Processing Credit Card payment: $" + amount);
}
}
@ApplicationScoped
@PaymentType(PaymentType.Mode.PAYPAL)
public class PayPalProcessor implements PaymentProcessor {
@Override
public void process(double amount) {
System.out.println("Processing PayPal payment: $" + amount);
}
}
योग्य बीन्स को इंजेक्ट करना
@ApplicationScoped
public class CheckoutService {
private final PaymentProcessor creditCardProcessor;
private final PaymentProcessor payPalProcessor;
@Inject
public CheckoutService(
@PaymentType(PaymentType.Mode.CREDIT_CARD) PaymentProcessor creditCardProcessor,
@PaymentType(PaymentType.Mode.PAYPAL) PaymentProcessor payPalProcessor) {
this.creditCardProcessor = creditCardProcessor;
this.payPalProcessor = payPalProcessor;
}
}
5. निर्माता और डिस्पोज़र: तृतीय-पक्ष वस्तुओं को इंजेक्ट करना
कभी-कभी आपको तृतीय-पक्ष लाइब्रेरीज़ (उदाहरण के लिए, AWS SDK क्लाइंट, रेडिस कनेक्शन, कस्टम कॉन्फ़िगरेशन बीन्स) से कक्षाएं इंजेक्ट करने की आवश्यकता होती है जो @ApplicationScoped के साथ एनोटेट नहीं होती हैं। क्वार्कस इसे निर्माता विधियों और डिस्पोजर्स का उपयोग करके संभालता है।
package com.ghaznix.config;
import jakarta.enterprise.context.ApplicationScoped;
import jakarta.enterprise.inject.Disposes;
import jakarta.enterprise.inject.Produces;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
@ApplicationScoped
public class DatabaseConnectionProducer {
@Produces
@ApplicationScoped
public Connection createDatabaseConnection() throws SQLException {
return DriverManager.getConnection("jdbc:postgresql://localhost:5432/mydb", "user", "pass");
}
// Disposer method called automatically when bean is destroyed
public void closeConnection(@Disposes Connection connection) throws SQLException {
if (connection != null && !connection.isClosed()) {
connection.close();
}
}
}
6. सीडीआई इंटरसेप्टर: पहलू-उन्मुख प्रोग्रामिंग (एओपी)
इंटरसेप्टर व्यावसायिक तर्क को प्रदूषित किए बिना क्रॉस-कटिंग चिंताओं (लॉगिंग, ऑडिट ट्रेल्स, मेट्रिक्स, रेट-लिमिटिंग) को बीन विधियों से जोड़ने की अनुमति देते हैं।
चरण 1: इंटरसेप्टर बाइंडिंग को परिभाषित करें
package com.ghaznix.interceptors;
import jakarta.interceptor.InterceptorBinding;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;
import static java.lang.annotation.ElementType.*;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
@InterceptorBinding
@Retention(RUNTIME)
@Target({TYPE, METHOD})
public @interface LogExecutionTime {
}
चरण 2: इंटरसेप्टर लॉजिक लागू करें
package com.ghaznix.interceptors;
import jakarta.annotation.Priority;
import jakarta.interceptor.AroundInvoke;
import jakarta.interceptor.Interceptor;
import jakarta.interceptor.InvocationContext;
@LogExecutionTime
@Interceptor
@Priority(Interceptor.Priority.APPLICATION)
public class LogExecutionTimeInterceptor {
@AroundInvoke
public Object logInvocation(InvocationContext context) throws Exception {
long startTime = System.currentTimeMillis();
try {
return context.proceed();
} finally {
long duration = System.currentTimeMillis() - startTime;
System.out.printf("[AUDIT] Method %s executed in %d ms%n",
context.getMethod().getName(), duration);
}
}
}
चरण 3: लक्ष्य बीन्स को एनोटेट करें
@ApplicationScoped
public class AnalyticsService {
@LogExecutionTime
public void computeAggregates() {
// Business computation
}
}
क्योंकि क्वार्कस बिल्ड समय पर स्थिर इंटरसेप्टर प्रॉक्सी उत्पन्न करता है, स्प्रिंग बूट में गतिशील सीजीएलआईबी रनटाइम प्रॉक्सी की तुलना में विधि आमंत्रण ओवरहेड वस्तुतः शून्य है।
7. सीडीआई इवेंट के साथ इवेंट-संचालित आर्किटेक्चर
सीडीआई डिकॉउल्ड इन-प्रोसेस संचार के लिए अंतर्निहित सिंक्रोनस और एसिंक्रोनस इवेंट प्रकाशन प्रदान करता है।
घटनाओं का प्रकाशन एवं अवलोकन
// 1. Define Event Payload
public record OrderCreatedEvent(String orderId, double totalAmount) {}
// 2. Publish Event
@ApplicationScoped
public class OrderService {
@Inject
Event<OrderCreatedEvent> orderEventPublisher;
public void createOrder(String orderId, double amount) {
// Create order logic...
orderEventPublisher.fire(new OrderCreatedEvent(orderId, amount));
}
}
// 3. Observe Event Synchronously or Asynchronously
@ApplicationScoped
public class InventoryObserver {
public void onOrderCreated(@Observes OrderCreatedEvent event) {
System.out.println("Updating inventory for order: " + event.orderId());
}
public void onOrderCreatedAsync(@ObservesAsync OrderCreatedEvent event) {
System.out.println("Async audit log for order: " + event.orderId());
}
}
अनुप्रयोग जीवनचक्र घटनाएँ
एप्लिकेशन लॉन्च या समाप्त होने पर क्वार्कस आरंभीकरण कोड निष्पादित करने के लिए स्टार्टअप और शटडाउन घटनाओं को उजागर करता है:
@ApplicationScoped
public class ApplicationLifecycleBean {
void onStart(@Observes StartupEvent ev) {
System.out.println("Quarkus Application starting up...");
}
void onStop(@Observes ShutdownEvent ev) {
System.out.println("Quarkus Application shutting down...");
}
}
8. Instance<T> और Arc.container() के साथ प्रोग्रामेटिक बीन लुकअप
जब लक्ष्य कार्यान्वयन को रनटाइम पर (या लीगेसी गैर-सीडीआई उदाहरणों के अंदर) गतिशील रूप से चुना जाना चाहिए, तो Instance<T> या क्वार्कस Arc.container() स्थिर लुकअप का उपयोग करें।
@ApplicationScoped
public class DynamicPluginRegistry {
@Inject
Instance<PaymentProcessor> processors;
public void executeAll(double amount) {
for (PaymentProcessor processor : processors) {
processor.process(amount);
}
}
}
9. वास्तुकला तुलना: क्वार्कस आर्क बनाम स्प्रिंग आईओसी बनाम वेल्ड
| विशेषता | क्वार्कस आर्क | स्प्रिंग आईओसी कंटेनर | मानक जकार्ता वेल्ड |
|---|---|---|---|
| निर्भरता समाधान | बिल्ड-टाइम (एओटी) | रनटाइम प्रतिबिंब | रनटाइम प्रतिबिंब |
| मेटास्पेस रैम ओवरहेड | अत्यंत कम (मेटाडेटा के लिए ~0एमबी) | उच्च (डायनामिक प्रॉक्सी क्लास कैश) | मध्यम से उच्च |
| स्टार्टअप का समय | मिलीसेकंड (<0.05s) | सेकंड (2.5 सेकंड - 8 सेकंड) | सेकंड (1.5 सेकंड - 4 सेकंड) |
| GraalVM मूल समर्थन | नेटिव आउट-ऑफ़-द-बॉक्स | स्प्रिंग नेटिव संकेत की आवश्यकता है | जटिल विन्यास |
| अप्रयुक्त बीन प्रूनिंग | स्वचालित बिल्ड-टाइम प्रूनिंग | क्लासपाथ में रखा गया | क्लासपाथ में रखा गया |
| एकल कंस्ट्रक्टर इंजेक्शन | निहित (किसी टिप्पणी की आवश्यकता नहीं) | का समर्थन किया | @इंजेक्ट की आवश्यकता है |
10. @QuarkusTest और @InjectMock के साथ यूनिट परीक्षण CDI बीन्स
क्वार्कस JUnit 5 और रेस्टएश्योर्ड के साथ CDI बीन्स के परीक्षण को सहज बनाता है। परीक्षण के दौरान निर्भरता बीन्स को मॉकिटो मॉक से बदलने के लिए @InjectMock का उपयोग करें।
package com.ghaznix;
import com.ghaznix.services.OrderProcessingService;
import io.quarkus.test.InjectMock;
import io.quarkus.test.junit.QuarkusTest;
import jakarta.inject.Inject;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import org.mockito.Mockito;
@QuarkusTest
public class OrderServiceTest {
@Inject
OrderService orderService;
@InjectMock
OrderProcessingService orderProcessingService;
@Test
public void testOrderCheckout() {
Mockito.when(orderProcessingService.processOrder("ORD-101"))
.thenReturn("Mocked Success");
String result = orderService.checkout("ORD-101");
Assertions.assertEquals("Mocked Success", result);
}
}
11. निष्कर्ष
सीडीआई (एआरसी) के साथ क्वार्कस में निर्भरता इंजेक्शन एंटरप्राइज़ जावा डिज़ाइन में एक महत्वपूर्ण बदलाव का प्रतीक है। बीन मेटाडेटा स्कैनिंग, प्रॉक्सी जेनरेशन और इंजेक्शन ग्राफ रिज़ॉल्यूशन को संकलन समय में स्थानांतरित करके, क्वार्कस सुपरसोनिक स्टार्टअप स्पीड, सबएटोमिक मेमोरी फ़ुटप्रिंट्स, और सीमलेस GraalVM नेटिव बाइनरी सपोर्ट प्रदान करता है।
चाहे आप स्प्रिंग बूट से माइग्रेट कर रहे हों या कुबेरनेट्स पर ग्रीनफील्ड क्लाउड-नेटिव माइक्रोसर्विसेज का निर्माण कर रहे हों, क्वार्कस सीडीआई में महारत हासिल करना आपको आधुनिक सॉफ्टवेयर आर्किटेक्चर के लिए आवश्यक प्रदर्शन और डेवलपर उत्पादकता से लैस करता है।
Tags
Empower Your Digital Presence & Workflows
Explore top-tier tools built by Ghaznix to streamline your links, surveys, and brand growth.