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


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

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

public class Boo {
    @Autowired
    Foo foo;

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

5 ответов:

вы можете сделать это, следуя одному из решений:

С помощью конструктора @Autowired

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

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

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

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

}

что вы можете сделать, это @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() перед Spring обработал экземпляр Boo.

Это отстой, но вы можете сделать боб с помощью 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;
    }
}

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

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

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