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

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

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

public class Boo {
    @Autowired
    Foo foo;

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

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() перед весной обработал экземпляр 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();
}