@ স্কোপ ("প্রোটোটাইপ") শিমের সুযোগ নতুন শিম তৈরি করে না


133

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

@Component
@Scope("prototype")
public class LoginAction {

  private int counter;

  public LoginAction(){
    System.out.println(" counter is:" + counter);
  }
  public String getStr() {
    return " counter is:"+(++counter);
  }
}

নিয়ামক কোড:

@Controller
public class HomeController {
    @Autowired
    private LoginAction loginAction;

    @RequestMapping(value="/view", method=RequestMethod.GET)
    public ModelAndView display(HttpServletRequest req){
        ModelAndView mav = new ModelAndView("home");
        mav.addObject("loginAction", loginAction);
        return mav;
    }

    public void setLoginAction(LoginAction loginAction) {
        this.loginAction = loginAction;
    }

    public LoginAction getLoginAction() {
        return loginAction;
    }
    }

वेग টেম্পলেট:

 LoginAction counter: ${loginAction.str}

বসন্তে config.xmlউপাদান স্ক্যানিং সক্ষম করা হয়েছে:

    <context:annotation-config />
    <context:component-scan base-package="com.springheat" />
    <mvc:annotation-driven />

আমি প্রতিবার একটি বর্ধিত গণনা পাচ্ছি। আমি কোথায় ভুল করছি বুঝতে পারছি না!

হালনাগাদ

@Gkamal দ্বারা প্রস্তাবিত হিসাবে , আমি HomeController webApplicationContext-ওয়ার তৈরি করেছি এবং এটি সমস্যার সমাধান করেছে।

আপডেট কোড:

@Controller
public class HomeController {

    @Autowired
    private WebApplicationContext context;

    @RequestMapping(value="/view", method=RequestMethod.GET)
    public ModelAndView display(HttpServletRequest req){
        ModelAndView mav = new ModelAndView("home");
        mav.addObject("loginAction", getLoginAction());
        return mav;
    }

    public LoginAction getLoginAction() {
        return (LoginAction) context.getBean("loginAction");
    }
}

12
আমি আশা করি অন্যদের আসল পার্থক্যটি দেখার জন্য আপনার কোডে সঠিক উত্তরটি প্রয়োগ করার জন্য আপনাকে দ্বিগুণ করতে পেরেছি
আলী নেম

উত্তর:


156

স্কোপ প্রোটোটাইপটির অর্থ হ'ল প্রতিটি সময় আপনি বসন্তের (গেটবিয়ান বা নির্ভরতা ইনজেকশন) জিজ্ঞাসা করার জন্য এটি একটি নতুন উদাহরণ তৈরি করবে এবং এটিকে একটি রেফারেন্স দেবে।

আপনার উদাহরণে লগইনঅ্যাকশনটির একটি নতুন উদাহরণ আপনার হোমকন্ট্রোলারের মধ্যে তৈরি এবং ইনজেকশনের তৈরি। আপনি যদি লগইনঅ্যাকশন ইনজেক্ট করেন এমন অন্য কোনও নিয়ামক থাকে তবে আপনি একটি আলাদা উদাহরণ পাবেন।

আপনি যদি প্রতিটি কলের জন্য আলাদা উদাহরণ চান - তবে আপনাকে প্রতিবার getBean কল করতে হবে - একটি সিঙ্গলটনের শিমে ইনজেকশনের মাধ্যমে এটি অর্জন করা যাবে না।


7
আমি কন্ট্রোলার অ্যাপ্লিকেশন কনটেক্সটওয়্যার তৈরি করেছি এবং পেয়েছিলাম এবং আমি প্রতিবার তাজা শিম পেয়ে যাচ্ছি। ধন্যবাদ বন্ধুরা!!!
টিনটিন

শিমের requestস্কোপের বদলে সুযোগ থাকলে কীভাবে এটি কাজ করে prototype। আপনার কি এখনও শিমটি পুনরুদ্ধার করা দরকার context.getBean(..)?
ডাঃ জেরি

2
অথবা একটি স্কোপড প্রক্সি ব্যবহার করুন, যেমন @ স্কোপ (মান = "প্রোটোটাইপ", প্রক্সিমোড = স্কোপডপ্রক্সি মোড T টার্গেT_ক্লাএসএস)
স্নেমেয়ার

25

বসন্ত 2.5 এর পরে এটি অর্জনের জন্য খুব সহজ (এবং মার্জিত) উপায় রয়েছে।

আপনি শুধু প্যারাম পরিবর্তন করতে পারেন proxyModeএবং valueএর @Scopeটীকা।

এই কৌশলটির সাহায্যে আপনি অতিরিক্ত কোড লিখতে বা অ্যাপ্লিকেশন কনটেক্সট প্রতিবার ইনজেকশন করতে এড়াতে পারবেন যে আপনার একক বিনের প্রোটোটাইপ দরকার।

উদাহরণ:

@Service 
@Scope(value="prototype", proxyMode=ScopedProxyMode.TARGET_CLASS)  
public class LoginAction {}

উপরের কনফিগারেশনের সাথে LoginAction(অভ্যন্তরীণ HomeController) সর্বদা একটি প্রোটোটাইপ সত্ত্বেও নিয়ামক একটি সিঙ্গলটন


2
সুতরাং আমরা এখন 5 বসন্ত এটি না?
রঘুবীর

16

শিমটি কন্ট্রোলারে ইনজেক্ট করা কেবল প্রোটোটাইপ-স্কোপযুক্ত হওয়ার অর্থ এটি নিয়ামক নয়!


11

@ কন্ট্রোলার একটি সিঙ্গলটন অবজেক্ট এবং প্রোটোটাইপ শিমকে সিঙ্গেলটন ক্লাসে ইনজেক্ট করলে আপনি প্রোটোটাইপ শিমকে সিঙ্গলটন হিসাবে তৈরি করবেন যতক্ষণ না আপনি লুকিং-মেথড প্রোপার্টি ব্যবহার করেন যা আপনার প্রতিটি কলের জন্য প্রোটোটাইপ শিমের একটি নতুন উদাহরণ তৈরি করে।


5

উল্লেখ হিসাবে nicholas.hauschild ইনজেকশন নেওয়ার স্প্রিং প্রসঙ্গ একটি ভাল ধারণা নয়। আপনার ক্ষেত্রে, @ স্কোপ ("অনুরোধ") এটি ঠিক করার জন্য যথেষ্ট। তবে যাক আপনাকে LoginActionনিয়ামক পদ্ধতিতে বেশ কয়েকটি দৃষ্টান্ত প্রয়োজন । এই ক্ষেত্রে, আমি সরবরাহকারী ( স্প্রিং 4 সমাধান) এর শিম তৈরি করার পরামর্শ দেব :

    @Bean
    public Supplier<LoginAction> loginActionSupplier(LoginAction loginAction){
        return () -> loginAction;
    }

তারপরে এটি নিয়ামকের মধ্যে ইনজেক্ট করুন:

@Controller
public class HomeController {
    @Autowired
    private  Supplier<LoginAction> loginActionSupplier;  

1
আমি স্প্রিংস ইনজেকশন প্রস্তাব করব ObjectFactoryযা সরবরাহকারী হিসাবে একই উদ্দেশ্যে কাজ করে তবে এটিকে একটি সাধারণ হিসাবে সংজ্ঞায়িত করা যেতে পারে @Beanযার অর্থ ল্যাম্বদা ফেরত দেওয়ার দরকার নেই।
xenoterracide

3

ব্যবহার ApplicationContextAwareআপনাকে বসন্তে বেঁধে রাখছে (যা কোনও সমস্যা হতে পারে এবং নাও হতে পারে)। আমি একটিতে যাওয়ার পরামর্শ দিচ্ছি LoginActionFactory, যা আপনি যখন যা LoginActionপ্রয়োজন প্রতিবারের জন্য একটি নতুন উদাহরণ চাইতে পারেন ।


1
ইতিমধ্যে স্প্রিং-নির্দিষ্ট টীকা আছে, যদিও; এটি অনেকটা উদ্বেগের মতো বলে মনে হচ্ছে না।
ডেভ নিউটন

1
@ ডেভ, ভাল পয়েন্ট কিছু ডি আই স্টাফের (জেএসআর 311) বিকল্প রয়েছে, তবে এই উদাহরণে বসন্ত নির্ভর সমস্ত কিছু থেকে নিজেকে মুক্তি দেওয়া আরও কঠিন হতে পারে। আমি মনে করি আমি সত্যিই factory-methodএখানে পরামর্শ করছি ...
নিকোলাস.হাউসচাইল্ড

1
LoginActionFactoryকন্ট্রোলারে একটি সিঙ্গলটন ইনজেকশন দেওয়ার জন্য +1 , তবে factory-methodমনে হয় না যে এটি সমস্যার সমাধান করবে কারণ এটি কেবল কারখানার মাধ্যমে অন্য একটি বসন্ত বিন তৈরি করে। সিঙ্গেলটন কন্ট্রোলারে সেই শিমটি ইনজেকশন করা সমস্যার সমাধান করবে না।
ব্র্যাড কাপিত

ভাল পয়েন্ট ব্র্যাড, আমি আমার উত্তর থেকে এই পরামর্শটি সরিয়ে ফেলব।
নিকোলাস.হসচিল্ড

3

@Scope("request")প্রতিটি অনুরোধের জন্য শিম পেতে, বা @Scope("session")প্রতিটি সেশনের 'ব্যবহারকারীর' জন্য সিম পেতে অনুরোধের সুযোগটি ব্যবহার করুন


1

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

context.getBean("Your Bean")


0

আপনি আপনার নিয়ামকের অভ্যন্তরে এই জাতীয় স্থির শ্রেণি তৈরি করতে পারেন:

    @Controller
    public class HomeController {
        @Autowired
        private LoginServiceConfiguration loginServiceConfiguration;

        @RequestMapping(value = "/view", method = RequestMethod.GET)
        public ModelAndView display(HttpServletRequest req) {
            ModelAndView mav = new ModelAndView("home");
            mav.addObject("loginAction", loginServiceConfiguration.loginAction());
            return mav;
        }


        @Configuration
        public static class LoginServiceConfiguration {

            @Bean(name = "loginActionBean")
            @Scope("prototype")
            public LoginAction loginAction() {
                return new LoginAction();
            }
        }
}

0

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

সমস্যাটি সমাধানের আরেকটি উপায় হ'ল @ লুপআপ টীকা সহ পদ্ধতিতে ইনজেকশন ।

একাধিক সমাধান সহ একক উদাহরণে প্রোটোটাইপ মটরশুটি ইনজেকশনের এই ইস্যুতে এখানে একটি সুন্দর নিবন্ধ ।

https://www.baeldung.com/spring-inject-prototype-bean-into-singleton


-11

আপনার নিয়ামক এছাড়াও প্রয়োজন @Scope("prototype") সংজ্ঞায়িত

এটার মত:

@Controller
@Scope("prototype")
public class HomeController { 
 .....
 .....
 .....

}

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