বসন্তে বিজ্ঞপ্তি নির্ভরতা


103

বসন্ত কীভাবে এটি সমাধান করে: শিম A শিম বি এর উপর নির্ভরশীল, এবং শিম বি-তে শিম বি B


4
চমৎকার নিবন্ধ baeldung.com/circular-d dependferences
in-

বিজ্ঞপ্তি নির্ভরতাগুলি কীভাবে ঘটে তা ব্যাখ্যা করে আরেকটি দরকারী নিবন্ধ: octoperf.com/blog/2018/02/15/spring-circular-d dependferences
জেরোম এল

উত্তর:


42

অন্য উত্তরগুলি যেমন বলেছে, বসন্ত কেবল এটির যত্ন নেয়, শিম তৈরি করে প্রয়োজনীয় হিসাবে সেগুলি ইনজেকশন করে।

এর একটি পরিণতি হ'ল শিমের ইনজেকশন / সম্পত্তি সেটিংটি আপনার এক্সএমএল ওয়্যারিং ফাইলগুলি বোঝায় কি তার চেয়ে আলাদা ক্রমে ঘটতে পারে। সুতরাং আপনার সতর্কতা অবলম্বন করা উচিত যে আপনার সম্পত্তি সেটাররা আরম্ভ করা না করে যা ইতিমধ্যে ডেকে আনা অন্যান্য সেটারের উপর নির্ভর করে। এর সাথে ডিল করার উপায় হ'ল মটরশুটিটি InitializingBeanইন্টারফেস বাস্তবায়ন হিসাবে ঘোষণা করা । এর জন্য আপনাকে afterPropertiesSet()পদ্ধতিটি বাস্তবায়ন করতে হবে এবং আপনি সমালোচনামূলক সূচনাটি এখানেই করেন। (গুরুত্বপূর্ণ বৈশিষ্ট্যগুলি আসলে সেট করা হয়েছে তা যাচাই করার জন্য আমি কোডও অন্তর্ভুক্ত করি))


76

স্প্রিং সহায়িকা ব্যাখ্যা বিজ্ঞপ্তি নির্ভরতা মীমাংসা করা হয়। মটরশুটি প্রথমে তাত্ক্ষণিকভাবে তৈরি করা হয়, তারপরে একে অপরের মধ্যে ইনজেকশন দেওয়া হয়।

এই শ্রেণি বিবেচনা করুন:

package mypackage;

public class A {

    public A() {
        System.out.println("Creating instance of A");
    }

    private B b;

    public void setB(B b) {
        System.out.println("Setting property b of A instance");
        this.b = b;
    }

}

এবং একটি অনুরূপ বর্গ B:

package mypackage;

public class B {

    public B() {
        System.out.println("Creating instance of B");
    }

    private A a;

    public void setA(A a) {
        System.out.println("Setting property a of B instance");
        this.a = a;
    }

}

যদি আপনার তখন এই কনফিগারেশন ফাইলটি থাকে:

<bean id="a" class="mypackage.A">
    <property name="b" ref="b" />
</bean>

<bean id="b" class="mypackage.B">
    <property name="a" ref="a" />
</bean>

এই কনফিগারেশনটি ব্যবহার করে একটি প্রসঙ্গ তৈরি করার সময় আপনি নিম্নলিখিত আউটপুটটি দেখতে পাবেন:

Creating instance of A
Creating instance of B
Setting property a of B instance
Setting property b of A instance

মনে রাখবেন যে যখন aমধ্যে ইনজেকশনের হয় b, aএখনো পুরো ইনিশিয়ালাইজ করা হয় না।


26
এই কারণেই স্প্রিংয়ের কোনও যুক্তি ছাড়াই একজন নির্মাণকারীর প্রয়োজন ;-)
ক্রিস থম্পসন

15
যদি আপনি আপনার বিন এর সংজ্ঞাগুলিতে কনস্ট্রাক্টর আর্গুমেন্ট ব্যবহার করেন না! (তবে
সেক্ষেত্রে

4
@ রিচার্ড ফেরন সমাধান সরবরাহের পরিবর্তে আপনার পোস্টটি কি সমস্যার ব্যাখ্যা সম্পর্কে জানায়?
gstackoverflow

4
আপনি যদি কনস্ট্রাক্টর ইঞ্জেকশনটি ব্যবহার করার চেষ্টা করেন তবে ত্রুটি বার্তাটি হ'লorg.springframework.beans.factory.BeanCurrentlyInCreationException: Error creating bean with name 'a': Requested bean is currently in creation: Is there an unresolvable circular reference?
এক্স Sat ও সাতুক

20

কোডবেসে আমি (1 মিলিয়ন + কোডের লাইন) সাথে কাজ করছি আমাদের দীর্ঘ প্রারম্ভকালীন সময়, প্রায় 60 সেকেন্ডের মধ্যে একটি সমস্যা হয়েছিল। আমরা 12000+ ফ্যাক্টরিবিয়াননোটইনটিয়ালাইজড এক্সেকশন পেয়ে যাচ্ছিলাম

আমি যা করেছি তা অ্যাবস্ট্রাকবিয়ানফ্যাক্টরী # doGetBean এ শর্তযুক্ত ব্রেকপয়েন্ট স্থাপন করেছিল

catch (BeansException ex) {
   // Explicitly remove instance from singleton cache: It might have been put there
   // eagerly by the creation process, to allow for circular reference resolution.
   // Also remove any beans that received a temporary reference to the bean.
   destroySingleton(beanName);
   throw ex;
}

এটি destroySingleton(beanName)শর্তযুক্ত ব্রেকপয়েন্ট কোড সহ আমি ব্যতিক্রমটি কোথায় মুদ্রিত করেছি:

   System.out.println(ex);
   return false;

স্পষ্টতই এটি ঘটে যখন ফ্যাক্টরিবিয়ানগুলি একটি চক্রীয় নির্ভরতা গ্রাফের সাথে জড়িত থাকে। আমরা এপ্লিকেশনকন্টেক্সটওয়্যার বাস্তবায়ন করে এবং বিয়ান শুরু করে এবং মটরশুটি মটরশুটি ইনজেকশনের মাধ্যমে সমাধান করেছি ।

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;

public class A implements ApplicationContextAware, InitializingBean{

    private B cyclicDepenency;
    private ApplicationContext ctx;

    @Override
    public void setApplicationContext(ApplicationContext applicationContext)
            throws BeansException {
        ctx = applicationContext;
    }
    @Override
    public void afterPropertiesSet() throws Exception {
        cyclicDepenency = ctx.getBean(B.class);
    }

    public void useCyclicDependency()
    {
        cyclicDepenency.doSomething();
    }
}

এটি সূচনার সময়টিকে প্রায় 15 সেকেন্ডে কেটে দেয়।

সুতরাং সবসময় ধরে নিবেন না যে আপনার জন্য এই উল্লেখগুলি সমাধান করতে বসন্ত ভাল হতে পারে good

এই কারণে আমি ভবিষ্যতের অনেক সমস্যা রোধ করার জন্য অ্যাবস্ট্রাকরফ্রেসিয়েবল অ্যাপ্লিকেশন কনটেক্সট # সেটএলসক্রাইকুলার রেফারেন্স (মিথ্যা) দিয়ে চক্রীয় নির্ভরতা রেজোলিউশনটি অক্ষম করার প্রস্তাব দিই ।


4
আকর্ষণীয় সুপারিশ। আমার পাল্টা সুপারিশটি কেবল তখনই করা হবে যদি আপনি সন্দেহ করেন যে বিজ্ঞপ্তি সংক্রান্ত রেফারেন্সগুলি পারফরম্যান্সে সমস্যা সৃষ্টি করছে। (এমন কোনও সমস্যা ভাঙার দরকার নেই যা ফিক্সিংয়ের দরকার নেই এমন সমস্যাটি সমাধান করার চেষ্টা করার জন্য এটি লজ্জার বিষয় হবে।)
স্টিফেন সি

4
বিজ্ঞপ্তি নির্ভরতাগুলি রক্ষণাবেক্ষণের জন্য এটি পিচ্ছিল slালু নিচে, বৃত্তাকার নির্ভরতা থেকে আপনার আর্কিটেকচারকে নতুন করে ডিজাইন করা সত্যিই জটিল হতে পারে, যেমনটি আমাদের ক্ষেত্রে ছিল। আমাদের পক্ষে এটি মোটামুটি বোঝাতে চাইছিল যে সেশনফ্যাক্টরিটি বিজ্ঞপ্তি নির্ভরতার সাথে জড়িত হওয়ায় আমরা শুরু করার সময় দ্বিগুণ ডাটাবেস সংযোগ পেয়েছিলাম। অন্যান্য পরিস্থিতিগুলিতে শিমটি 12000+ বার ইনস্ট্যান্ট করার কারণে আরও বিপর্যয়কর ঘটনা ঘটতে পারে। অবশ্যই আপনার মটরশুটিটি লিখুন যাতে তারা সেগুলি ধ্বংস করার পক্ষে সমর্থন করে তবে কেন এই আচরণটিকে প্রথমে অনুমতি দেওয়া উচিত?
jontejj

@ জোন্টেজেজ, আপনি একটি কুকির প্রাপ্য
সার্প্রাইম

15

সমস্যা ->

Class A {
    private final B b; // must initialize in ctor/instance block
    public A(B b) { this.b = b };
}


Class B {
    private final A a; // must initialize in ctor/instance block
    public B(A a) { this.a = a };
 }

// এর দ্বারা তৈরি: org.springframework.beans.factory.BeanCurrentlyInCreationException: 'A' নাম দিয়ে শিম তৈরিতে ত্রুটি: অনুরোধ করা শিমটি বর্তমানে তৈরিতে রয়েছে: কোনও অদলিতযোগ্য বৃত্তাকার রেফারেন্স আছে কি?

সমাধান 1 ->

Class A {
    private B b; 
    public A( ) {  };
    //getter-setter for B b
}

Class B {
    private A a;
    public B( ) {  };
    //getter-setter for A a
}

সমাধান 2 ->

Class A {
    private final B b; // must initialize in ctor/instance block
    public A(@Lazy B b) { this.b = b };
}

Class B {
    private final A a; // must initialize in ctor/instance block
    public B(A a) { this.a = a };
}

12

এটা ঠিক এটা করে। এটি তাত্ক্ষণিকভাবে aএবং b, এবং একে অপরকে ইনজেক্ট করে (তাদের সেটার পদ্ধতিগুলি ব্যবহার করে)।

সমস্যা কি?


9
@ জাভাগুয়ে: না, তা হবে না।
স্কাফম্যান

প্রোফেসিটসেট পদ্ধতি ব্যবহারের পরে কেবলমাত্র স্ক্যাফম্যানের সাথেই উপায়?
gstackoverflow

7

বলুন এ বি এর উপর নির্ভর করে, তারপরে স্প্রিং প্রথমে এ, তারপরে বি ইনস্ট্যান্ট করবে, তারপরে বি এর জন্য প্রোপার্টি সেট করবে, তারপরে বি কে এ এ সেট করবে Say

তবে বি যদি এ এর ​​উপরও নির্ভর করে?

আমার উপলব্ধিটি হ'ল: বসন্তটি সবেমাত্র পাওয়া গেছে যে এ নির্মাণ করা হয়েছে (নির্বাহককে মৃত্যুদন্ড কার্যকর করা হয়েছে), তবে পুরোপুরি আরম্ভ করা হয়নি (সমস্ত ইনজেকশন সম্পন্ন করা হয়নি), ভাল, এটি ভেবেছিল, এটি ঠিক আছে, এটি সম্পূর্ণ সহনীয় যে এটিকে পুরোপুরি আরম্ভ করা হয়নি, কেবল এটি সেট করুন- আপাতত সম্পূর্ণ বি-তে এ-দের উদাহরণস্বরূপ। বি সম্পূর্ণরূপে আরম্ভ করার পরে এটি এ এ সেট করা হয়েছিল এবং শেষ পর্যন্ত এটিকে পুরোপুরি এখন আরম্ভ করা হয়েছিল।

অন্য কথায়, এটি কেবল A থেকে B কে আগাম প্রকাশ করে।

কনস্ট্রাক্টরের মাধ্যমে নির্ভরতার জন্য, স্প্রিন্টটি কেবল বিয়ানক্রেনলিআইক্রিসেশন এক্সেপশন নিক্ষেপ করুন, এই ব্যতিক্রমটি সমাধান করার জন্য, বিনের জন্য আরসের জন্য সত্যটি সেট করুন যা কনস্ট্রাক্টর-আর্গের মাধ্যমে অন্যের উপর নির্ভর করে।


সহজ এবং সেরা ব্যাখ্যা এক।
শ্রীতম জগদেব

6

থেকে বসন্ত রেফারেন্স :

সঠিকভাবে কাজ করার জন্য আপনি সাধারণত বসন্তকে বিশ্বাস করতে পারেন। এটি কনফিগারেশন সমস্যাগুলি সনাক্ত করে যেমন কনটেইনার লোড-টাইমে অস্তিত্বহীন মটরশুটি এবং বিজ্ঞপ্তি নির্ভরতাগুলির উল্লেখ। বসন্ত বৈশিষ্ট্যগুলি নির্ধারণ করে এবং যতটা সম্ভব শিমটি তৈরি করা হয় ততক্ষণে নির্ভরতাগুলি সমাধান করে।


6

বসন্তের ধারক সেটার-ভিত্তিক বিজ্ঞপ্তি নির্ভরতাগুলি সমাধান করতে সক্ষম তবে কনস্ট্রাক্টর-ভিত্তিক বিজ্ঞপ্তি নির্ভরতাগুলির ক্ষেত্রে একটি রানটাইম ব্যতিক্রম BeanCurrentlyInCreationException দেয়। সেটার-ভিত্তিক বিজ্ঞপ্তি নির্ভরতার ক্ষেত্রে, আইওসি কনটেইনার এটি একটি সাধারণ দৃশ্যের থেকে আলাদাভাবে পরিচালনা করে যেখানে এটি ইনজেকশনের আগে সহযোগী বিনকে সম্পূর্ণরূপে কনফিগার করে। উদাহরণস্বরূপ, শিম কলের বিন বিন এবং শিম বি এর উপর নির্ভরশীলতা থাকলে কনটেইনারটি বিতে ইনজেকশন দেওয়ার আগে সিটিকে সম্পূর্ণরূপে আরম্ভ করে এবং একবার বি পুরোপুরি শুরু করা হলে এটি এ এ ইনজেক্ট করা হয় তবে বৃত্তাকার নির্ভরতার ক্ষেত্রে, একটি মটরশুটি এর সম্পূর্ণরূপে শুরু করার আগে অন্যটিতে ইনজেকশনের ব্যবস্থা করা হয়।


5

এটি এখানে পরিষ্কারভাবে ব্যাখ্যা করা হয়েছে । ইউজেন প্যারাসিচকে ধন্যবাদ।

বিজ্ঞপ্তি নির্ভরতা হ'ল একটি ডিজাইনের গন্ধ, এটি ঠিক করুন বা নির্ভরশীলতার জন্য @ অলস ব্যবহার করুন যার ফলে এটি সমস্যার সমাধান করতে পারে।


3

আপনি যদি সাধারণত কন্সট্রাক্টর-ইঞ্জেকশন ব্যবহার করেন এবং সম্পত্তি-ইনজেকশনে স্যুইচ করতে না চান তবে স্প্রিংয়ের চেহারা -পদ্ধতি -ইনজেকশনের ফলে একটি শিমকে অন্য আলস্যভাবে তল্লাশি করতে দেওয়া হয় এবং তাই চক্র নির্ভরতা নির্ভর করে। এখানে দেখুন: http://docs.spring.io/spring/docs/1.2.9/references/beans.html#d0e1161


3

কনস্ট্রাক্টর ইনজেকশন ব্যর্থ হয় যখন বসন্ত শিমের মধ্যে বিজ্ঞপ্তি নির্ভরতা থাকে। সুতরাং এই ক্ষেত্রে আমরা ইনজেকশন সেটটারটি সমস্যাটি সমাধান করতে সহায়তা করে।

মূলত, কনস্ট্রাক্টর ইনজেকশন বাধ্যতামূলক নির্ভরতাগুলির জন্য দরকারী, terচ্ছিক নির্ভরতার জন্য সেটার ইঞ্জেকশন ব্যবহার করা আরও ভাল কারণ আমরা পুনরায় ইনজেকশন করতে পারি।


0

যদি দুটি মটরশুটি একে অপরের উপর নির্ভরশীল হয় তবে আমাদের উভয় শিমের সংজ্ঞাতে কনস্ট্রাক্টর ইঞ্জেকশন ব্যবহার করা উচিত নয়। পরিবর্তে আমাদের শিমের যে কোনও একটিতে সেটার ইঞ্জেকশন ব্যবহার করতে হবে। (অবশ্যই আমরা সেটের ইনজেকশন এন উভয় বিনের সংজ্ঞা ব্যবহার করতে পারি, তবে উভয় কনট্রাক্টর ইনজেকশনগুলি 'বিয়ানকন্ট্রালিআইক্রেশন এক্সেক্সশন' নিক্ষেপ করে)

" Https://docs.spring.io/spring/docs/current/spring-framework-references/core.html#resources-resource " এ স্প্রিং ডক রেফারেন্স করুন

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.