স্প্রিংয়ের অ্যাপ্লিকেশনসন্টেক্সট.বিটকে কেন খারাপ বলে বিবেচনা করা হয়?


270

আমি একটি সাধারণ বসন্তের প্রশ্ন জিজ্ঞাসা করেছি: অটো-কাস্টিং স্প্রিং বিনস এবং একাধিক লোকের প্রতিক্রিয়া ছিল যে স্প্রিংকে কল ApplicationContext.getBean()করা যতটা সম্ভব এড়ানো উচিত। তা কেন?

আমি আর কীভাবে সিমের কাছে বসন্তটি তৈরি করতে কনফিগার করেছি তাতে অ্যাক্সেস পেতে পারি?

আমি একটি নন-ওয়েব অ্যাপ্লিকেশনটিতে স্প্রিং ব্যবহার করছি এবং লিয়েরএইচ দ্বারা বর্ণিত হিসাবে একটি ভাগ করা ApplicationContextবস্তু অ্যাক্সেস করার পরিকল্পনা করেছিলাম

সংশোধন

আমি নীচের উত্তরটি গ্রহণ করি, তবে এখানে মার্টিন ফাউলারের বিকল্প বিকল্প নেওয়া যিনি একটি সার্ভিস লোকেটার (যা মূলত মোড়কে কল করার মত একই ApplicationContext.getBean()) ডিপেন্ডেন্সি ইনজেকশন বনামের গুণাবলী সম্পর্কে আলোচনা করেন

অংশ হিসাবে ফওলার বলেছেন, " সার্ভিস লোকেটারের সাথে অ্যাপ্লিকেশন ক্লাস লোকেটারের কাছে একটি বার্তা দ্বারা স্পষ্টভাবে এটি [পরিষেবা] জিজ্ঞাসা করে inj ইনজেকশন সহ কোনও স্পষ্ট অনুরোধ নেই, পরিষেবাটি অ্যাপ্লিকেশন শ্রেণিতে উপস্থিত হয় - সুতরাং নিয়ন্ত্রণের বিপরীততা। নিয়ন্ত্রণের বিপরীতকরণ ফ্রেমওয়ার্কগুলির একটি সাধারণ বৈশিষ্ট্য, তবে এটি এমন দাম যা আসে। এটি বোঝা শক্ত হয়ে যায় এবং আপনি যখন ডিবাগ করার চেষ্টা করছেন তখন সমস্যার সৃষ্টি করে to সুতরাং সামগ্রিকভাবে আমি এড়াতে পছন্দ করি [নিয়ন্ত্রণের বিপরীতকরণ ] যতক্ষণ না আমার এটির প্রয়োজন হয় This এটি একটি খারাপ জিনিস বলার অপেক্ষা রাখে না, কেবলমাত্র আমি মনে করি এটি আরও সহজবোধ্য বিকল্পের জন্য নিজেকে ন্যায্যতাযুক্ত করা দরকার ""

উত্তর:


202

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

কল ApplicationContext.getBean()করা নিয়ন্ত্রণের বিপরীতে নয়! প্রদত্ত শিমের নামটির জন্য বাস্তবায়নটি কীভাবে কনফিগার করা হয়েছে তা পরিবর্তন করা সহজ, ক্লাসটি এখন নির্ভরতা প্রদানের জন্য সরাসরি বসন্তের উপর নির্ভর করে এবং এটি অন্য কোনও উপায়ে পেতে পারে না। আপনি কেবল পরীক্ষার ক্লাসে আপনার নিজস্ব মক প্রয়োগ করতে পারবেন না এবং এটি নিজেই এটি পাস করতে পারবেন না। এটি মূলত নির্ভরতা ইনজেকশন ধারক হিসাবে বসন্তের উদ্দেশ্যকে পরাস্ত করে।

আপনি যেখানেই বলতে চান:

MyClass myClass = applicationContext.getBean("myClass");

পরিবর্তে আপনার উচিত, উদাহরণস্বরূপ, একটি পদ্ধতি ঘোষণা করুন:

public void setMyClass(MyClass myClass) {
   this.myClass = myClass;
}

এবং তারপরে আপনার কনফিগারেশনে:

<bean id="myClass" class="MyClass">...</bean>

<bean id="myOtherClass" class="MyOtherClass">
   <property name="myClass" ref="myClass"/>
</bean>

স্প্রিং এর পরে স্বয়ংক্রিয়ভাবে ইনজেক্ট myClassহবে myOtherClass

সবকিছু এইভাবে ঘোষণা করুন এবং এর মূলে সবার এমন কিছু রয়েছে:

<bean id="myApplication" class="MyApplication">
   <property name="myCentralClass" ref="myCentralClass"/>
   <property name="myOtherCentralClass" ref="myOtherCentralClass"/>
</bean>

MyApplicationসর্বাধিক কেন্দ্রীয় শ্রেণি, এবং কমপক্ষে পরোক্ষভাবে আপনার প্রোগ্রামের প্রতিটি অন্যান্য পরিষেবার উপর নির্ভর করে। বুটস্ট্র্যাপিং করার সময়, আপনার mainপদ্ধতিতে, আপনি কল করতে পারেন applicationContext.getBean("myApplication")তবে আপনাকে getBean()অন্য কোথাও কল করার দরকার নেই!


3
এর সাথে সম্পর্কিত এমন কি কিছু আছে যা কোনও অবজেক্ট তৈরি করার সময় কেবল টীকা দিয়ে কাজ করে new MyOtherClass()? আমি @ অটোভায়ার্ড সম্পর্কে জানি, তবে আমি কেবল কখনও এটি মাঠে ব্যবহার করেছি এবং এটি ব্রেক হয়ে যায় new MyOtherClass()..
টিম

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

3
অ্যালেক্সের সাথে সম্মত হোন, আমার একই সমস্যা রয়েছে, যেখানে কোনও কারখানার শ্রেণি কেবল তখন জানতে পারে যে ব্যবহারকারীদের সাথে কথোপকথনের মাধ্যমে রান শুরুর সময় কোন সিম বা বাস্তবায়ন করতে হবে, আমি মনে করি কনটেক্সটওয়্যার ইন্টারফেসটি এখানে এসেছে
বেন

3
@ বেলব্যাক: applicationContext.getBeanনির্ভরতা ইনজেকশন নয়: এটি সার্ভিস লোকেটার হিসাবে এটি সরাসরি কাঠামোটিতে অ্যাক্সেস করছে ।
কলিনড

6
@ হেরম্যান: আমি স্প্রিং সম্পর্কে জানি না কারণ আমি এটি দীর্ঘ সময় ব্যবহার করি নি, তবে জেএসআর -330 / গুইস / ডাগারে, আপনি এটির Provider<Foo>পরিবর্তে একটি ইঞ্জেকশন দিয়ে Fooএবং provider.get()প্রতিবার যখন আপনার প্রয়োজন হবে কল করে এই কাজটি করবেন নতুন উদাহরণ। ধারকটির নিজেই কোনও রেফারেন্স নেই এবং আপনি সহজেই Providerপরীক্ষার জন্য একটি তৈরি করতে পারেন ।
কলিনড

64

ইনভার্সন অফ কন্ট্রোল (আইওসি) এর চেয়ে সার্ভিস লোকেটারকে প্রাধান্য দেওয়ার কারণগুলি হ'ল:

  1. পরিষেবা লোকেটার আপনার কোড অনুসরণ করে অন্য লোকের পক্ষে অনেক বেশি সহজ। আইওসি 'ম্যাজিক' তবে রক্ষণাবেক্ষণ প্রোগ্রামারদের অবশ্যই আপনার সংযুক্ত বসন্তের কনফিগারেশনগুলি এবং আপনার অজানাগুলি কীভাবে ওয়্যার্ড করেছিলেন তা নির্ধারণের জন্য অবশ্যই সমস্ত অগণিত লোকেশন বুঝতে হবে।

  2. আইওসি ডিবাগিং কনফিগারেশন সমস্যার জন্য ভয়ঙ্কর। অ্যাপ্লিকেশনগুলির কয়েকটি শ্রেণিতে ভুল কনফিগার করা থাকলে অ্যাপ্লিকেশন শুরু হবে না এবং আপনি কোনও ডিবাগার দিয়ে যা চলছে তাতে পদক্ষেপ নেওয়ার সুযোগ নাও পেতে পারেন।

  3. আইওসিটি মূলত এক্সএমএল ভিত্তিক (টীকাগুলি জিনিসগুলির উন্নতি করে তবে সেখানে এখনও অনেকগুলি এক্সএমএল রয়েছে)। এর অর্থ হ'ল বিকাশকারীরা স্প্রিং দ্বারা সংজ্ঞায়িত সমস্ত ম্যাজিক ট্যাগ না জেনে আপনার প্রোগ্রামে কাজ করতে পারে না। জাভা আর জেনে রাখা ভাল নয় is এটি কম অভিজ্ঞ প্রোগ্রামারগুলিকে বাধা দেয় (যেমন সার্ভিস লোকেটারের মতো সহজ সমাধান যেমন একই প্রয়োজনীয়তা পূরণ করবে তখন আরও জটিল সমাধান ব্যবহার করা আসলেই এটি খারাপ নকশা)। এছাড়াও, এক্সএমএল সমস্যাগুলি নির্ণয়ের জন্য সমর্থন জাভা সমস্যার জন্য সমর্থনের চেয়ে অনেক দুর্বল।

  4. নির্ভরতা ইনজেকশন বৃহত্তর প্রোগ্রামগুলির জন্য আরও উপযুক্ত। বেশিরভাগ সময় অতিরিক্ত জটিলতা এটি উপযুক্ত নয়।

  5. আপনি "পরে বাস্তবায়ন পরিবর্তন করতে চান" ক্ষেত্রে প্রায়শই বসন্ত ব্যবহার করা হয়। স্প্রিং আইওসির জটিলতা ছাড়াই এটি অর্জনের অন্যান্য উপায় রয়েছে।

  6. ওয়েব অ্যাপ্লিকেশনগুলির জন্য (জাভা ইই ওয়ার্স) স্প্রিং প্রসঙ্গটি কার্যকরভাবে সংকলনের সময় আবদ্ধ (আপনি যদি না অপারেটরদের বিস্ফোরিত যুদ্ধের প্রসঙ্গে ঘুরে দেখতে চান)। আপনি স্প্রিং ব্যবহারের সম্পত্তি ফাইলগুলি তৈরি করতে পারেন, তবে সার্লেলেটের সাথে সম্পত্তি ফাইলগুলি একটি পূর্ব নির্ধারিত স্থানে থাকা দরকার, যার অর্থ আপনি একই বাক্সে একই সময়ের একাধিক সার্লেটগুলি স্থাপন করতে পারবেন না। সার্ভলেট প্রারম্ভকালীন সময়ে বৈশিষ্ট্য পরিবর্তন করতে আপনি জেএনডিআই সহ স্প্রিং ব্যবহার করতে পারেন, তবে আপনি যদি প্রশাসক-সংশোধনযোগ্য পরামিতিগুলির জন্য জেএনডিআই ব্যবহার করছেন তবে স্প্রিংয়ের নিজেই প্রয়োজনকে কমিয়ে দিতে হবে (যেহেতু জেএনডিআই কার্যকরভাবে সার্ভিস লোকেটার)।

  7. স্প্রিংয়ের সাথে আপনি প্রোগ্রামটি নিয়ন্ত্রণ হারাতে পারেন যদি বসন্ত আপনার পদ্ধতিতে প্রেরণ করে চলেছে। এটি সুবিধাজনক এবং বিভিন্ন ধরণের অ্যাপ্লিকেশনগুলির জন্য কাজ করে তবে সমস্ত নয় not আপনার যখন প্রারম্ভিক চলাকালীন টাস্ক (থ্রেড ইত্যাদি) তৈরি করতে হবে বা পরিবর্তিত সংস্থান প্রয়োজন যা কবে আপনার ওয়্যারটির সাথে আবদ্ধ ছিল সে সম্পর্কে স্প্রিংয়ের জানা ছিল না এমন সময় আপনাকে প্রোগ্রাম প্রবাহ নিয়ন্ত্রণ করতে হতে পারে।

লেনদেন পরিচালনার জন্য বসন্ত খুব ভাল এবং এর কিছু সুবিধা রয়েছে। এটি ঠিক যে আইওসি অনেক পরিস্থিতিতে ওভার ইঞ্জিনিয়ারিং হতে পারে এবং রক্ষণাবেক্ষণকারীদের জন্য অযৌক্তিক জটিলতার পরিচয় দিতে পারে। আইওসিটি প্রথমে ব্যবহার না করার উপায়গুলির কথা চিন্তা না করে স্বয়ংক্রিয়ভাবে ব্যবহার করবেন না।


7
প্লাস - আপনার সার্ভিসলোকেটারটি সবসময় স্প্রিং থেকে আইওসি ব্যবহার করতে পারে, আপনার কোডকে বসন্তের উপর নির্ভরশীল হতে, স্প্রিং টীকাতে লিপ্ত এবং অনিবার্য ম্যাজিক থেকে বিরত রাখতে পারে। আমি সম্প্রতি গুগল অ্যাপইঙ্গিনে গুচ্ছ কোড পোর্ট করেছি যেখানে স্প্রিং সমর্থন করে না। আমি চাই যে আমি সমস্ত আইওসি একটি সার্ভিস ফ্যাক্টরীর পিছনে প্রথম স্থানে লুকিয়ে রেখেছি!
অ্যালেক্স ওয়ার্ডেন

আইওসি একটি অ্যানিমিক ডোমেন মডেলকে উত্সাহিত করে, যা আমি ঘৃণা করি। সত্তা মটরশুটিগুলি তাদের পরিষেবাগুলি সন্ধান করার জন্য একটি উপায় প্রয়োজন যাতে তারা তাদের নিজস্ব আচরণ বাস্তবায়ন করতে পারে। এই স্তরে, আপনি কোনও সার্ভিস লোকেটারের প্রয়োজনের আশেপাশে পেতে পারেন না।
জোয়েল

4
নিবন্ধন। আমি টীকা সহ সমস্ত সময় স্প্রিং ব্যবহার করি। যদিও প্রকৃতপক্ষে একটি নির্দিষ্ট শিক্ষার বক্ররেখা জড়িত, এখন, রক্ষণাবেক্ষণ, ডিবাগিং, স্পষ্টতা, পঠনযোগ্যতায় আমার কোনও সমস্যা নেই .... আমি ধারণা করি আপনি কীভাবে কাঠামোগত গঠনটি কৌশল is
লরেন্স

25

এটি সত্য যে অ্যাপ্লিকেশন-কনটেক্সট.এক্সএমএল ক্লাস সহ গেটবিয়ান ব্যবহারের প্রয়োজনীয়তা এড়িয়ে চলে। তবে এটি এমনকি অপ্রয়োজনীয়। আপনি যদি একটি স্বতন্ত্র অ্যাপ্লিকেশন লিখছেন এবং আপনি অ্যাপ্লিকেশন-প্রসঙ্গ.এক্সএমএলগুলিতে আপনার ড্রাইভার ক্লাসটি অন্তর্ভুক্ত করতে চান না, তবে আপনি স্প্রিংয়ের চালকের নির্ভরতা স্বীকার করার জন্য নিম্নলিখিত কোডটি ব্যবহার করতে পারেন:

public class AutowireThisDriver {

    private MySpringBean mySpringBean;    

    public static void main(String[] args) {
       AutowireThisDriver atd = new AutowireThisDriver(); //get instance

       ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext(
                  "/WEB-INF/applicationContext.xml"); //get Spring context 

       //the magic: auto-wire the instance with all its dependencies:
       ctx.getAutowireCapableBeanFactory().autowireBeanProperties(atd,
                  AutowireCapableBeanFactory.AUTOWIRE_BY_TYPE, true);        

       // code that uses mySpringBean ...
       mySpringBean.doStuff() // no need to instantiate - thanks to Spring
    }

    public void setMySpringBean(MySpringBean bean) {
       this.mySpringBean = bean;    
    }
}

আমার এই অ্যাপ্লিকেশনটির কিছু দিক ব্যবহার করা দরকার (যেমন, পরীক্ষার জন্য) এমন কিছু স্ট্যান্ডার্ডোন ক্লাস থাকলে আমি এটি কয়েকবার করার দরকার পড়েছিলাম তবে আমি এটিকে অ্যাপ্লিকেশন-প্রসঙ্গে অন্তর্ভুক্ত করতে চাই না কারণ এটি নয় আসলে অ্যাপ্লিকেশন অংশ। আরও মনে রাখবেন যে এটি স্ট্রিং নামটি ব্যবহার করে শিমটি খোঁজার প্রয়োজনটিকে এড়িয়ে চলে, যা আমি সবসময়ই কুৎসিত বলে ভেবেছিলাম।


@Autowiredটীকাগুলির সাথেও আমি এই পদ্ধতিটি সফলভাবে ব্যবহার করতে সক্ষম হয়েছি ।
ব্লু

21

স্প্রিংয়ের মতো কিছু ব্যবহারের দুর্দান্ত সুবিধাগুলির মধ্যে একটি হ'ল আপনাকে নিজের জিনিসগুলি একসাথে ওয়্যার করতে হবে না। জিউসের মাথা খোলা থাকে এবং আপনার ক্লাসগুলি উপস্থিত হয়, প্রয়োজনীয়তার সাথে তাদের তৈরি এবং তারযুক্ত সমস্ত নির্ভরতাগুলির সাথে সম্পূর্ণরূপে গঠিত হয়। এটি যাদু এবং চমত্কার।

আপনি আরও বলুন ClassINeed classINeed = (ClassINeed)ApplicationContext.getBean("classINeed"); , আপনি যত কম ম্যাজিক পাচ্ছেন। কম কোড প্রায় সর্বদা ভাল। যদি আপনার ক্লাসে সত্যই ক্লাসিনিড শিমের প্রয়োজন হয় তবে আপনি কেন কেবল তারটি যুক্ত করেননি?

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


1
তবে ওপি "ক্লাসিনেইড" বলছে না তিনি "বিয়াননামেইনইইইডিড" বলছেন - যা আইওসি ধারককে কোনও উপায়ে কনফিগার করা কোনও শ্রেণিতে একটি উদাহরণ তৈরি করতে দেয়। আইওসির চেয়ে সম্ভবত এটি "সার্ভিস লোকেটার" প্যাটার্নের মতো তবে এটি এখনও শিথিল সংযোগের ফলে তৈরি হয়।
এইচডিভ

16

অনুপ্রেরণা কোড লিখতে হয় যা স্প্রিংয়ের উপর সুস্পষ্টভাবে নির্ভর করে না। এইভাবে, আপনি যদি ধারকগুলি স্যুইচ করতে চান, আপনাকে কোনও কোড নতুন করে লিখতে হবে না।

ধারকটিকে ভাবুন যে কোনও কিছু আপনার কোডের কাছে অদৃশ্য, যাদুকরভাবে তার প্রয়োজনের জন্য জিজ্ঞাসা করা হয়নি providing

নির্ভরতা ইনজেকশনটি "পরিষেবা লোকেটার" প্যাটার্নের একটি পাল্টা পয়েন্ট। আপনি যদি নাম অনুসারে নির্ভরতাগুলি অনুসন্ধান করতে যাচ্ছেন তবে আপনি ডিআই কনটেইনার থেকে মুক্তি পেয়ে জেএনডিআই এর মতো কিছু ব্যবহার করতে পারেন।


11

ব্যবহার করা @Autowiredবা ApplicationContext.getBean()আসলে একই জিনিস। উভয় উপায়ে আপনি শিমটি পান যা আপনার প্রসঙ্গে এবং উভয় উপায়ে আপনার কোডটি বসন্তের উপর নির্ভর করে। আপনার অ্যাপ্লিকেশন কনটেক্সটটি তাত্ক্ষণিক করা আপনার কেবলমাত্র এড়ানো উচিত। এটি একবারই করুন! অন্য কথায়, একটি লাইন মত

ApplicationContext context = new ClassPathXmlApplicationContext("AppContext.xml");

আপনার আবেদনে একবার ব্যবহার করা উচিত।


নাঃ। কখনও কখনও @ অটোওয়ার্ড বা অ্যাপ্লিকেশনসন্টেক্সট.জেটবিয়ান () সম্পূর্ণ ভিন্ন মটরশুটি উত্পাদন করতে পারে। এটি কীভাবে হয়েছিল তা সম্পর্কে আমি নিশ্চিত নই, তবে এই মুহুর্তে আমি লড়াই করে যাচ্ছি।
ওলেকসান্ডার_ডিজে

4

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

ApplicationContext.getBean()আপনার উপাদানগুলির মধ্যে আপনাকে স্পষ্টত একটি শিমের নামকরণ করতে হবে। পরিবর্তে, আইওসি ব্যবহার করে আপনার কনফিগারেশনটি নির্ধারণ করতে পারে কোন উপাদানটি ব্যবহৃত হবে।

এটি আপনাকে সহজেই বিভিন্ন উপাদান প্রয়োগের সাথে আপনার অ্যাপ্লিকেশনটিকে পুনরায় ওয়াইর করতে দেয় বা মজাদার রূপগুলি সরবরাহ করে (যেমন একটি উপহাস করা ডিএও যাতে আপনি পরীক্ষার সময় কোনও ডেটাবেসকে আঘাত না করেন) সরবরাহ করে কোনও সরল ফ্যাশনে পরীক্ষার জন্য অবজেক্টগুলিকে কনফিগার করতে সহায়তা করে This


4

অন্যরা সাধারণ সমস্যাটির দিকে ইঙ্গিত করেছেন (এবং বৈধ উত্তর) তবে আমি কেবল একটি অতিরিক্ত মন্তব্য করব: এটি এমন নয় যে এটি করা উচিত নয়, বরং এটি যতটা সম্ভব সামান্যই করা উচিত।

সাধারণত এর অর্থ এটি হ'ল একবার: বুটস্ট্র্যাপিংয়ের সময়। এবং তারপরে এটি কেবলমাত্র "মূল" শিমটি অ্যাক্সেস করার জন্য, যার মাধ্যমে অন্যান্য নির্ভরতাগুলি সমাধান করা যেতে পারে। এটি বেস সার্ভলেটের মতো (যদি ওয়েব অ্যাপ্লিকেশন বিকাশ করে) পুনরায় ব্যবহারযোগ্য কোড হতে পারে।


4

বসন্ত প্রাঙ্গণগুলির মধ্যে একটি হ'ল সংযুক্তি এড়ানো । ইন্টারফেস, ডিআই, এওপি সংজ্ঞা এবং ব্যবহার করুন এবং অ্যাপিকেশনকন্টেক্সট.বিটবিয়ান () :-) ব্যবহার করা এড়ানো


4

এর অন্যতম কারণ হ'ল টেস্টেবলি। বলুন আপনার এই ক্লাস রয়েছে:

interface HttpLoader {
    String load(String url);
}
interface StringOutput {
    void print(String txt);
}
@Component
class MyBean {
    @Autowired
    MyBean(HttpLoader loader, StringOutput out) {
        out.print(loader.load("http://stackoverflow.com"));
    }
}

আপনি কিভাবে এই শিম পরীক্ষা করতে পারেন? যেমন:

class MyBeanTest {
    public void creatingMyBean_writesStackoverflowPageToOutput() {
        // setup
        String stackOverflowHtml = "dummy";
        StringBuilder result = new StringBuilder();

        // execution
        new MyBean(Collections.singletonMap("https://stackoverflow.com", stackOverflowHtml)::get, result::append);

        // evaluation
        assertEquals(result.toString(), stackOverflowHtml);
    }
}

সহজ, তাই না?

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

অ্যাপ্লিকেশন কনটেক্সটটি ব্যবহার করার সময় এখনও এটি করা সম্ভব। তবে আপনাকে বিদ্রূপ করা দরকার ApplicationContextযা একটি বিশাল ইন্টারফেস। আপনার হয় একটি ডামি বাস্তবায়ন প্রয়োজন বা আপনি মকিতো এর মতো একটি মশকরা কাঠামো ব্যবহার করতে পারেন:

@Component
class MyBean {
    @Autowired
    MyBean(ApplicationContext context) {
        HttpLoader loader = context.getBean(HttpLoader.class);
        StringOutput out = context.getBean(StringOutput.class);

        out.print(loader.load("http://stackoverflow.com"));
    }
}
class MyBeanTest {
    public void creatingMyBean_writesStackoverflowPageToOutput() {
        // setup
        String stackOverflowHtml = "dummy";
        StringBuilder result = new StringBuilder();
        ApplicationContext context = Mockito.mock(ApplicationContext.class);
        Mockito.when(context.getBean(HttpLoader.class))
            .thenReturn(Collections.singletonMap("https://stackoverflow.com", stackOverflowHtml)::get);
        Mockito.when(context.getBean(StringOutput.class)).thenReturn(result::append);

        // execution
        new MyBean(context);

        // evaluation
        assertEquals(result.toString(), stackOverflowHtml);
    }
}

এটি বেশ সম্ভাবনা, তবে আমি মনে করি বেশিরভাগ লোক সম্মত হবে যে প্রথম বিকল্পটি আরও মার্জিত এবং পরীক্ষাকে আরও সহজ করে তোলে।

সত্যিই সমস্যা হ'ল একমাত্র বিকল্পটি হ'ল:

@Component
class MyBean {
    @Autowired
    MyBean(StringOutput out) {
        out.print(new HttpLoader().load("http://stackoverflow.com"));
    }
}

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

সুতরাং উপসংহার হিসাবে আমি বলব না যে ApplicationContextসরাসরি ব্যবহার করা স্বয়ংক্রিয়ভাবে ভুল এবং কোনও মূল্যে এড়ানো উচিত। তবে যদি আরও ভাল বিকল্প থাকে (এবং বেশিরভাগ ক্ষেত্রে রয়েছে), তবে আরও ভাল বিকল্পগুলি ব্যবহার করুন।


3

আমি কেবল দুটি পরিস্থিতি পেয়েছি যেখানে getBean () প্রয়োজন ছিল:

অন্যরা স্ট্যান্ডএলোন প্রোগ্রামের জন্য "মেইন" শিমটি আনতে মূল () প্রধানতে) getBean () ব্যবহার করে উল্লেখ করেছেন।

আমি getBean () এর তৈরি আরেকটি ব্যবহার এমন পরিস্থিতিতে রয়েছি যেখানে কোনও ইন্টারেক্টিভ ব্যবহারকারী কনফিগারেশন কোনও নির্দিষ্ট পরিস্থিতির জন্য বিন মেকআপ নির্ধারণ করে। সুতরাং, উদাহরণস্বরূপ, বুট সিস্টেমের একটি অংশ স্কোপ = 'প্রোটোটাইপ' বিনের সংজ্ঞা সহ গেটবিয়ান () ব্যবহার করে একটি ডাটাবেস টেবিলের মধ্য দিয়ে যায় এবং তারপরে অতিরিক্ত বৈশিষ্ট্য নির্ধারণ করে। সম্ভবত, একটি ইউআই রয়েছে যা ডাটাবেস টেবিলটি সামঞ্জস্য করে যা অ্যাপ্লিকেশন প্রসঙ্গে XML লেখার চেষ্টা করার চেয়ে বন্ধুত্বপূর্ণ হবে।


3

GetBean ব্যবহার করার সময় অন্য একটি সময় আসে। আপনি যদি এমন একটি সিস্টেম পুনর্নির্মাণ করছেন যা ইতিমধ্যে বিদ্যমান, যেখানে নির্ভরতা স্পষ্টতই বসন্ত প্রসঙ্গে ফাইলগুলিতে ডাকা হয় না। আপনি getBean- এ কল রেখে প্রক্রিয়াটি শুরু করতে পারেন, যাতে আপনাকে একবারে এটির ওয়্যার আপ করতে না হয়। এইভাবে আপনি ধীরে ধীরে আপনার বসন্তের কনফিগারেশনটি প্রতিটি টুকরোগুলিকে যথাযথভাবে যথাযথভাবে স্থির করে তুলতে পারেন properly GetBean- এ কলগুলি শেষ পর্যন্ত প্রতিস্থাপন করা হবে, তবে আপনি কোডটির কাঠামো বুঝতে পেরেছেন বা না থাকায় আপনি আরও সিমের তারের সংযোজন এবং getBean এর জন্য কম এবং কম কল ব্যবহার করার প্রক্রিয়া শুরু করতে পারেন।


2

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


0

আপনার ব্যবহার করা উচিত: অ্যাপ্লিকেশন কনটেক্সটের পরিবর্তে কনফিগারযোগ্য অ্যাপ্লিকেশনসনটেক্সট

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