it-swarm.asia

@ أسلوب ثابت و ثابت

لدي خدمة @Autowired والتي يجب استخدامها من خلال طريقة ثابتة. أعلم أن هذا خطأ ولكن لا يمكنني تغيير التصميم الحالي لأنه سيتطلب الكثير من العمل ، لذلك أحتاج إلى بعض الاختراق البسيط لذلك. لا يمكنني تغيير randomMethod() لتكون غير ثابتة وأحتاج إلى استخدام هذه الحبة autowired. أي أدلة على كيفية القيام بذلك؟

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

public class Boo {
    @Autowired
    Foo foo;

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

يمكنك القيام بذلك عن طريق اتباع أحد الحلول:

باستخدام المنشئ

وهذا النهج بناء الفول تتطلب بعض الفول كمعلمات منشئ. ضمن رمز المنشئ ، تقوم بتعيين الحقل الثابت مع الحصول على القيمة كمعلمة لتنفيذ المنشئ. عينة:

@Component
public class Boo {

    private static Foo foo;

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

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

باستخدامPostConstruct لتسليم القيمة إلى الحقل الثابت

الفكرة هنا هي تسليم الحبة إلى حقل ثابت بعد تكوين الحبة بحلول الربيع.

@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();
    }
}
121
Francisco Spaeth

يجب عليك حل هذا عبر نهج ثابت سياق سياق التطبيق:

@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();
    }

}
37
Pavel Horal

ما يمكنك فعله هو @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();
    }
}

عندما تتم معالجة الحبة ، سيقوم Spring بإدخال مثيل تنفيذ Foo في حقل المثيل foo. بعد ذلك ، سيتم أيضًا حقن نفس مثيل Foo في قائمة وسيطة setStaticFoo() ، والتي سيتم استخدامها لتعيين الحقل الثابت.

هذا حل رهيب وسيفشل إذا حاولت استخدام randomMethod() قبل أن يعالج Spring مثيل Boo.

6
Sotirios Delimanolis

تمتص ولكن يمكنك الحصول على الفول باستخدام واجهة 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;
    }
}
3
Jean-Philippe Bond

هذا يعتمد على @ Pavel الإجابة ، لحل احتمال عدم تهيئة سياق الربيع عند الوصول إلى طريقة 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 ستكون نقطة خلاف في الكود حيث تتم مزامنته. إذا كان التطبيق الخاص بك متوازيًا بشكل كبير (على سبيل المثال: الواجهة الخلفية لموقع ذات عدد زيارات كبير) ، فقد لا يكون هذا حلاً جيدًا لك.

0
Hashken