@Autowired и статический метод

У меня есть служба @Autowired, которая должна использоваться из статического метода. Я знаю, что это неправильно, но я не могу изменить текущий дизайн, поскольку для этого потребуется много работы, поэтому для этого мне нужен простой хак. Я не могу изменить randomMethod() как нестатический, и мне нужно использовать этот autwired bean. Любые подсказки, как это сделать?

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

public class Boo {
    @Autowired
    Foo foo;

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

Ответ 1

Вы можете сделать это, выполнив одно из следующих решений:

Использование конструктора @Autowired

В этом подходе будет построен bean, требующий некоторых beans в качестве параметров конструктора. В коде конструктора вы устанавливаете статическое поле со значением, полученным как параметр для выполнения конструктора. Пример:

@Component
public class Boo {

    private static Foo foo;

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

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

Использование @PostConstruct для передачи значения в статическое поле

Идея здесь состоит в том, чтобы передать bean в статическое поле после bean, настроенного spring.

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

Ответ 2

Вам нужно обходиться с помощью подхода к аксессурам с использованием статического приложения:

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

}

Затем вы можете получить доступ к экземплярам bean статическим образом.

public class Boo {

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

}

Ответ 3

Что вы можете сделать, это @Autowired метод setter и установить новое статическое поле.

public class Boo {
    @Autowired
    Foo foo;

    static Foo staticFoo;   

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

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

Когда обрабатывается bean, Spring вставляет экземпляр реализации Foo в поле экземпляра Foo. Затем он также вводит тот же экземпляр Foo в список аргументов setStaticFoo(), который будет использоваться для установки статического поля.

Это ужасное обходное решение и потерпит неудачу, если вы попытаетесь использовать randomMethod(), прежде чем Spring обработал экземпляр Boo.

Ответ 4

Это отстой, но вы можете получить bean с помощью интерфейса 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;
    }
}

Ответ 5

Использовать AppContext. Убедитесь, что вы создаете bean в своем файле контекста.

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

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