@ স্বীকৃত এবং অচল পদ্ধতি


104

আমার @Autowiredপরিষেবা রয়েছে যা একটি স্ট্যাটিক পদ্ধতির মধ্যে থেকে ব্যবহার করতে হবে। আমি জানি এটি ভুল তবে আমি বর্তমান নকশাটি পরিবর্তন করতে পারি না কারণ এটির জন্য প্রচুর পরিশ্রম প্রয়োজন, তাই এর জন্য আমার কিছু সাধারণ হ্যাক দরকার। আমি randomMethod()অ-স্থিতিশীল হয়ে উঠতে পারি না এবং আমাকে এই স্বয়ংক্রিয় শিমটি ব্যবহার করা দরকার। কোনও ক্লু কীভাবে করব?

@Service
public class Foo {
    public int doStuff() {
        return 1;
    }
}

public class Boo {
    @Autowired
    Foo foo;

    public static void randomMethod() {
         foo.doStuff();
    }
}

4
একটি স্থিতিশীল পদ্ধতি কোনও স্থিতিশীল / দৃষ্টান্ত ক্ষেত্রের উল্লেখ করতে পারে না।
সোটিরিওস ডেলিমনোলিস

19
এই কারণেই আমি এই থ্রেডটি তৈরি করেছি, এমন কোনও উপায়ে স্থির পদ্ধতির মধ্যে থেকে অটোভায়ার্ড উদাহরণটি অ্যাক্সেস করা যেতে পারে ...
তাকস

স্থির পদ্ধতিতে অটোভায়ার্ড ব্যবহার কেন ভুল?
ব্যবহারকারী59290

উত্তর:


154

সমাধানগুলির একটি অনুসরণ করে আপনি এটি করতে পারেন:

কনস্ট্রাক্টর @ অটোভায়ার্ড ব্যবহার করে

এই পদ্ধতির সাথে শিমটি কনস্ট্রাক্টর পরামিতি হিসাবে কিছু শিমের প্রয়োজন হবে const কনস্ট্রাক্টর কোডের মধ্যে আপনি স্থির ক্ষেত্রটি সেট করে নির্ধারিত নির্বাহের জন্য প্যারামিটার হিসাবে মানটি দিয়ে। নমুনা:

@Component
public class Boo {

    private static Foo foo;

    @Autowired
    public Boo(Foo foo) {
        Boo.foo = foo;
    }

    public static void randomMethod() {
         foo.doStuff();
    }
}

স্ট্যাটিক ক্ষেত্রের কাছে মান হস্তান্তর করতে @ পোষ্টকনস্ট্রাক্ট ব্যবহার করে

এখানে ধারণাটি হ'ল শিমটি বসন্তের মাধ্যমে কনফিগার করার পরে একটি স্টিমকে স্থির ক্ষেত্রের কাছে হস্তান্তর করা হবে।

@Component
public class Boo {

    private static Foo foo;
    @Autowired
    private Foo tFoo;

    @PostConstruct
    public void init() {
        Boo.foo = tFoo;
    }

    public static void randomMethod() {
         foo.doStuff();
    }
}

4
এটি কি নিরাপদ সমাধান?
তাক

4
আমি প্রথম সমাধানটি ব্যবহার করেছি এবং এটি একটি কবজির মতো কাজ করেছে, ধন্যবাদ!
ভিক্টোরিলেডুক

4
প্রথম সমাধান @ কোয়ালিফায়ার ব্যবহার সমর্থন করে না। এটি বেশ কয়েকটি रिपোজিটরিগুলি ব্যবহার করে থাকলে সমস্যা থেকে যায়।
ব্যবহারকারী 1767316

16
স্থির পদ্ধতি অ্যাক্সেস করার আগে কনস্ট্রাক্টরকে ডেকে আনার নিশ্চয়তা কী?
ডেভিড ডম্ব্রভস্কি

4
init পদ্ধতিটি সোনারকিউব বাগের কারণ ঘটায় কারণ অ স্থির পদ্ধতি স্থির ক্ষেত্র পরিবর্তন করে।
jDub9

45

স্থিতিশীল অ্যাপ্লিকেশন প্রসঙ্গ প্র্যাক্সেস অ্যাক্সেসর পদ্ধতির মাধ্যমে আপনাকে এটিকে একসাথে করতে হবে:

@Component
public class StaticContextAccessor {

    private static StaticContextAccessor instance;

    @Autowired
    private ApplicationContext applicationContext;

    @PostConstruct
    public void registerInstance() {
        instance = this;
    }

    public static <T> T getBean(Class<T> clazz) {
        return instance.applicationContext.getBean(clazz);
    }

}

তারপরে আপনি স্ট্যাটিক পদ্ধতিতে শিমের দৃষ্টান্ত অ্যাক্সেস করতে পারেন।

public class Boo {

    public static void randomMethod() {
         StaticContextAccessor.getBean(Foo.class).doStuff();
    }

}

আমি আসলে এই সমাধানটি পছন্দ করি যদিও আমি এটি পুরোপুরি বুঝতে পারি না .. আমি কেবল বসন্তের চারপাশে আমার মাথা পেয়েছি এবং আমাকে দ্রুত কিছু কোডের রিফ্যাক্টর করতে হবে .. এবং এটি অটোওয়ার্ডের সাথে স্ট্যাটিক মেশানোর বিষয়টি .. এই সমাধানটি কতটা নিরাপদ?
তাক

4
স্থিতিকাল কলগুলি আপনার নিয়ন্ত্রণে থাকলে এটি মোটামুটি নিরাপদ। সর্বাধিক সুস্পষ্ট নেতিবাচক দিকটি হ'ল এটি ঘটতে পারে যে আপনি getBeanপ্রসঙ্গটি সূচনা হওয়ার আগে (এনপিই) শুরু করার আগে বা এর বিনগুলি বিন্যাসটি বিনষ্ট হওয়ার পরে কল করবেন call এই পদ্ধতির সুবিধা রয়েছে যে "কুরুচিপূর্ণ" স্থির প্রসঙ্গ অ্যাক্সেস একটি পদ্ধতি / শ্রেণিতে আবদ্ধ।
পাভেল হোরাল

4
এটি আমার জীবন বাঁচিয়েছিল। এটি অন্যান্য পদ্ধতির উপর খুব দরকারী।
ফিনিক্স

6

আপনি যা করতে পারেন তা @Autowiredএকটি সেটার পদ্ধতি এবং এটি একটি নতুন স্ট্যাটিক ক্ষেত্র সেট করে।

public class Boo {
    @Autowired
    Foo foo;

    static Foo staticFoo;   

    @Autowired
    public void setStaticFoo(Foo foo) {
        Boo.staticFoo = foo;
    }

    public static void randomMethod() {
         staticFoo.doStuff();
    }
}

শিমটি প্রক্রিয়াজাত হয়ে গেলে, বসন্ত Fooউদাহরণস্বরূপ ক্ষেত্রের মধ্যে একটি প্রয়োগকরণ ইনস্ট্যান্স ইনজেক্ট করবে foo। এরপরে যুক্তি তালিকায় একই Fooউদাহরণটি ইনজেক্ট করা setStaticFoo()হবে, যা স্থির ক্ষেত্র সেট করতে ব্যবহৃত হবে।

এটি একটি ভয়াবহ কাজ এবং যদি আপনি randomMethod()স্প্রিংয়ের কোনও উদাহরণ প্রক্রিয়া করার আগে ব্যবহার করার চেষ্টা করেন তবে ব্যর্থ হয়ে যাবে Boo


@ পোষ্টকনস্ট্রাক্ট সহায়তা ব্যবহার করবেন?
তাক

@ টাক্স শিওর, এটিও কার্যকর। উপর setStaticFoo()যে ছাড়া হয় Fooপ্যারামিটার।
সোটিরিওস ডেলিমনোলিস

প্রশ্নটি কী এটি নিরাপদ করে তুলবে .. :) আমি ভেবেছিলাম যে কোনও পদ্ধতি কার্যকর করার অনুমতি দেওয়ার আগে বসন্ত সবকিছু প্রক্রিয়াজাত করবে ...
টাকস

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

3

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

public class Boo implements ApplicationContextAware {

    private static ApplicationContext appContext;

    @Autowired
    Foo foo;

    public static void randomMethod() {
         Foo fooInstance = appContext.getBean(Foo.class);
         fooInstance.doStuff();
    }

    @Override
    public void setApplicationContext(ApplicationContext appContext) {
        Boo.appContext = appContext;
    }
}

0

স্থিতিশীল getBean পদ্ধতি থেকে অ্যাক্সেস করার সময় স্প্রিং প্রসঙ্গটি আরম্ভ না হওয়ার সম্ভাবনা সমাধানের জন্য এটি @ পাভেলের উত্তরের উপর ভিত্তি করে তৈরি হয়েছে :

@Component
public class Spring {
  private static final Logger LOG = LoggerFactory.getLogger (Spring.class);

  private static Spring spring;

  @Autowired
  private ApplicationContext context;

  @PostConstruct
  public void registerInstance () {
    spring = this;
  }

  private Spring (ApplicationContext context) {
    this.context = context;
  }

  private static synchronized void initContext () {
    if (spring == null) {
      LOG.info ("Initializing Spring Context...");
      ApplicationContext context = new AnnotationConfigApplicationContext (io.zeniq.spring.BaseConfig.class);
      spring = new Spring (context);
    }
  }

  public static <T> T getBean(String name, Class<T> className) throws BeansException {
    initContext();
    return spring.context.getBean(name, className);
  }

  public static <T> T getBean(Class<T> className) throws BeansException {
    initContext();
    return spring.context.getBean(className);
  }

  public static AutowireCapableBeanFactory getBeanFactory() throws IllegalStateException {
    initContext();
    return spring.context.getAutowireCapableBeanFactory ();
  }
}

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


-2

অ্যাপকন্টেক্সট ব্যবহার করুন। নিশ্চিত হয়ে নিন যে আপনি আপনার প্রসঙ্গ ফাইলটিতে শিম তৈরি করেছেন।

private final static Foo foo = AppContext.getApplicationContext().getBean(Foo.class);

public static void randomMethod() {
     foo.doStuff();
}

এটা কি?? @ অটোভায়ার্ড এবং গেটবিনের মধ্যে পার্থক্য কী
মধাইরসিলেন্স

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